diff --git a/Build.proj b/Build.proj index bff94b97a7a799..5f47e869fb6e42 100644 --- a/Build.proj +++ b/Build.proj @@ -10,7 +10,7 @@ - + $(NetCoreAppCurrentIdentifier),Version=v$(NetCoreAppToolCurrentVersion) Microsoft.NETCore.App .NET $(NetCoreAppCurrentVersion) + + net472 + + @@ -72,7 +76,7 @@ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)', 'publish')) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)', 'publish')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmBuildTasks', 'Debug', '$(NetCoreAppToolCurrent)', 'publish')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WorkloadBuildTasks', 'Debug', '$(NetCoreAppToolCurrent)', 'publish')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoAOTCompiler', 'Debug', '$(NetCoreAppToolCurrent)')) @@ -206,6 +210,10 @@ $([MSBuild]::NormalizeDirectory('$(MicrosoftNetCoreAppRuntimePackRidDir)', 'native')) + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', '$(OutputRid).$(Configuration)', 'corehost')) + + true @@ -251,14 +259,12 @@ https://go.microsoft.com/fwlink/?LinkID=799421 - true - $(MSBuildProjectName.Contains('Experimental')) + false $(MSBuildProjectName.Contains('Private')) - - true - false + + true - false + false $(RepositoryEngineeringDir)_._ @@ -270,6 +276,8 @@ strict;nullablePublicOnly true + + $(NoWarn),CS8969 portable true diff --git a/NuGet.config b/NuGet.config index f39fab9df8ec4f..086ee6ef505994 100644 --- a/NuGet.config +++ b/NuGet.config @@ -7,6 +7,13 @@ + + + + + + + - diff --git a/docs/design/features/images/intel-cet-dotnet6-fig1.png b/docs/design/features/images/intel-cet-dotnet6-fig1.png new file mode 100644 index 00000000000000..37d2aebb570397 Binary files /dev/null and b/docs/design/features/images/intel-cet-dotnet6-fig1.png differ diff --git a/docs/design/features/intel-cet-dotnet6.md b/docs/design/features/intel-cet-dotnet6.md new file mode 100644 index 00000000000000..abf5ca32b06223 --- /dev/null +++ b/docs/design/features/intel-cet-dotnet6.md @@ -0,0 +1,30 @@ +# .NET 6 compatibility with Intel CET shadow stacks (early preview on Windows) + +Intel�s [Control-flow Enforcement Technology (CET)](https://newsroom.intel.com/editorials/intel-cet-answers-call-protect-common-malware-threats/) is a security feature available in some newer Intel and AMD processors. It adds capabilities to the hardware that protect against some common types of attacks involving control-flow hijacking. With CET shadow stacks, the processor and operating system can track the control flow of calls and returns in a thread in the shadow stack in addition to the data stack, and detect unintended changes to the control flow. The shadow stack is protected from application code memory accesses and helps to defend against attacks involving return-oriented programming (ROP). Windows offers [Hardware-enforced Stack Protection](https://techcommunity.microsoft.com/t5/windows-kernel-internals/understanding-hardware-enforced-stack-protection/ba-p/1247815) for CET shadow stack compatibility and is available as an early preview in [Windows Insider preview builds (Dev channel)](https://insider.windows.com/en-us/understand-flighting). + +## Opting into CET shadow stack compatibility + +CET compatibility in .NET 6 is available as an early preview. In order to receive the security benefits of CET shadow stacks in .NET applications, ensure the following to opt into the feature for an executable: +- Verify that your processor supports Intel CET. There are Intel and AMD processors currently available with the feature. +- Get a recent build of Windows that has Hardware-enforced Stack Protection. The latest versions from [Windows Insider preview builds (Dev channel)](https://insider.windows.com/en-us/understand-flighting) have the feature. +- Install [.NET 6](https://dotnet.microsoft.com/download/dotnet) RC1 or a more recent release +- Build or publish your application targeting framework `net6.0` and runtime `win-x64` +- Open the Windows Security app + - Inside the "App & browser control" pane, select "Explicit protection settings" + - Under the "Program settings" tab, select "Add program to customize" and "Add by program name" + - Enter the file name of your application�s executable file and select "Add" + - Select the following options and select "Apply": + + ![Hardware-enforced Stack Protection settings](images/intel-cet-dotnet6-fig1.png) + - See the [Developer Guidance for Hardware-enforced Stack Protection](https://techcommunity.microsoft.com/t5/windows-kernel-internals/developer-guidance-for-hardware-enforced-stack-protection/ba-p/2163340) for more details +- Task Manager�s Details tab has a new column "Hardware-enforced Stack Protection" that shows the compatibility level of a running process. If CET shadow stacks are enabled for the process, the column for the application should say "Compatible modules only". + +## Limitations + +CET shadow stack compatibility in .NET is under development and will be available as an early preview from .NET 6 RC1 as an opt-in for x64 applications. Aside from a notable limitation, most run-time scenarios should work as expected. There are plans for expanding the compatibility for .NET 7 and to have it be enabled by default on supported hardware for Windows x64 applications. + +For a .NET 6 application that is opted into CET shadow stack compatibility, managed or mixed-mode debugging through Visual Studio may not work as expected, and may cause the application to crash. Some basic features such as expression evaluation (including autos, locals, watch list expressions, quick watch, etc.) and stepping through code are currently incompatible with CET shadow stacks. Native debugging through Visual Studio and WinDbg/SOS should continue to work as expected with CET shadow stacks enabled for the application being debugged. + +When opted in as above, CET shadow stacks are enabled in compatibility mode. .NET 6 is not compatible with strict mode, support for strict mode is planned for .NET 7. + +For .NET 6 applications, CET shadow stack compatibility is available to try for Windows x64 applications. Support for the feature on Linux is pending. diff --git a/eng/MultiTargetRoslynComponent.targets.template b/eng/MultiTargetRoslynComponent.targets.template new file mode 100644 index 00000000000000..420693a6262b9f --- /dev/null +++ b/eng/MultiTargetRoslynComponent.targets.template @@ -0,0 +1,31 @@ + + + + + <_{TargetPrefix}Analyzer Include="@(Analyzer)" Condition="'%(Analyzer.NuGetPackageId)' == '{NuGetPackageId}'" /> + + + + + + + + + + + + + + + + + + + diff --git a/eng/Publishing.props b/eng/Publishing.props index ba44e57c7c744b..920e79cbbd2f7c 100644 --- a/eng/Publishing.props +++ b/eng/Publishing.props @@ -1,3 +1,6 @@ + + 3 + \ No newline at end of file diff --git a/eng/SourceBuild.props b/eng/SourceBuild.props index 7dfc80d41fd14c..bba40f534e5b62 100644 --- a/eng/SourceBuild.props +++ b/eng/SourceBuild.props @@ -36,14 +36,11 @@ $(InnerBuildArgs) --arch $(TargetRidPlatform) $(InnerBuildArgs) --configuration $(Configuration) - $(InnerBuildArgs) --ci - $(InnerBuildArgs) --allconfigurations + $(InnerBuildArgs) --allconfigurations $(InnerBuildArgs) --verbosity $(LogVerbosity) $(InnerBuildArgs) --nodereuse false $(InnerBuildArgs) --warnAsError false - $(InnerBuildArgs) --cmakeargs -DCLR_CMAKE_USE_SYSTEM_LIBUNWIND=TRUE - $(InnerBuildArgs) /p:MicrosoftNetFrameworkReferenceAssembliesVersion=1.0.0 - $(InnerBuildArgs) /p:ContinuousIntegrationBuild=true + $(InnerBuildArgs) /p:MicrosoftNetFrameworkReferenceAssembliesVersion=1.0.2 $(InnerBuildArgs) /p:PackageRid=$(TargetRid) $(InnerBuildArgs) /p:NoPgoOptimize=true $(InnerBuildArgs) /p:KeepNativeSymbols=true diff --git a/eng/Subsets.props b/eng/Subsets.props index 332632c32e5163..be4c6a8862480b 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -22,11 +22,19 @@ that indicates tests should be run. Otherwise, they'll only be built.) --> + + + CoreCLR + Mono + + clr+mono+libs+host+packs mono+libs+packs - - clr+libs+host+packs + + clr+libs+host+packs @@ -35,14 +43,6 @@ <_subset Condition="'$(Subset)' == ''">+$(DefaultSubsets)+ - - - CoreCLR - Mono - - Mono Mono @@ -66,13 +66,13 @@ $(DefaultLibrariesSubsets)libs.ref+libs.src $(DefaultLibrariesSubsets)+libs.pretest - host.native+host.tools - $(DefaultHostSubsets)+host.pkg+host.tests + host.native+host.tools+host.pkg + $(DefaultHostSubsets)+host.tests host.native packs.product - $(DefaultPacksSubsets)+packs.tests + $(DefaultPacksSubsets)+packs.tests $(DefaultPacksSubsets)+packs.installers @@ -120,7 +120,14 @@ - + + + + + + + + @@ -130,13 +137,6 @@ - - - - - - - @@ -263,6 +263,22 @@ + + + + + + + + + + + + + + + + @@ -288,22 +304,7 @@ - - - - - - - - - - - - - - - - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1ebd09b7378e75..be61afe4daac46 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,130 +1,138 @@ - + https://github.com/dotnet/icu - 05dbba88d0ae799b4fea1e13c69b0c02beb7dcbe + 183f41cd63abd8dcba7389c22d19ebad7df65bfa https://github.com/dotnet/msquic 98129287d56a5e0348c291ce4260e630b4aa510d - + https://github.com/dotnet/emsdk - 9f2345b3c5f43dbf34790e21657ae1f2445cd06a + ee0a97a0009c0e048789126253fea7994db676ac + + + https://github.com/dotnet/wcf + 04c3656e0325277aefa18378f24238d39b259222 - + + https://github.com/dotnet/arcade + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d + + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 https://github.com/dotnet/llvm-project @@ -158,9 +166,9 @@ https://github.com/dotnet/llvm-project cea4a95e1505e737e768c8094d6aa880f5442ab7 - + https://github.com/dotnet/runtime - 38017c3935de95d0335bac04f4901ddfc2718656 + fde6b37e985605d862c070256de7c97e2a3f3342 https://github.com/dotnet/runtime @@ -190,9 +198,9 @@ https://github.com/dotnet/runtime fde6b37e985605d862c070256de7c97e2a3f3342 - + https://github.com/mono/linker - 5b2391c2c56af47350a5789375e8dbddc692e67f + c8499798a2a09639174e2f5c694d6652794cc73d https://github.com/dotnet/xharness @@ -202,9 +210,9 @@ https://github.com/dotnet/xharness e9669dc84ecd668d3bbb748758103e23b394ffef - + https://github.com/dotnet/arcade - 9b7027ba718462aa6410cef61a8be5a4283e7528 + fe5cc1841d12196d94a4ae3b276cb92d8d7ca73d https://dev.azure.com/dnceng/internal/_git/dotnet-optimization @@ -226,13 +234,17 @@ https://github.com/dotnet/hotreload-utils 802e79f0cf423249d54bfaafca2da4a272f4ca07 - + https://github.com/dotnet/runtime-assets - 7f980667ff908c5b5d7cf0dd66d48e7af23daae1 + 6c6b7f90677142ad7bd829eb28d3bcf8ad775dd7 https://github.com/dotnet/roslyn-analyzers 9a1f02eff42635a5a9934735f12c722c3bfba8e8 + + https://github.com/dotnet/sdk + f6028bc958dbab0094be39b94ba9e9c761cde13f + diff --git a/eng/Versions.props b/eng/Versions.props index 4265ca90427500..5e9d0039096bbf 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,77 +1,65 @@ - 6.0.0 + 6.0.3 6 0 - 0 - 6.0.100 - rc - 1 + 3 + 6.0.200 + servicing + + $(MajorVersion).$(MinorVersion).0.0 - false + true release true - - 4.0.0-3.21376.12 true false false + $(AssemblyVersion) - - - + + - - 3.9.0 - 3.9.0 + + 3.11.0 + 4.0.0-3.final + 4.0.0-3.final 3.10.0 3.10.0 - 6.0.0-rc1.21413.4 + 6.0.0-rtm.21514.4 - 1.0.0-rc.1.21404.21 + 1.0.0-rc.2.21511.46 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 2.5.1-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 - 6.0.0-beta.21413.4 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 2.5.1-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 + 6.0.0-beta.22107.2 6.0.0-preview.1.102 - 6.0.0-alpha.1.20612.4 + 6.0.0-alpha.1.20612.4 6.0.0-rc.1.21415.6 6.0.0-rc.1.21415.6 3.1.0 @@ -85,7 +73,7 @@ 4.5.1 4.3.0 5.0.0 - 4.8.2 + 4.8.3 4.5.0 4.3.0 4.3.0 @@ -96,6 +84,8 @@ 4.3.1 4.5.0 5.0.0 + + 5.0.0 4.7.0 4.7.0 4.7.0 @@ -109,24 +99,24 @@ 5.0.0 5.0.0 5.0.0 - 4.8.1 + 4.9.0 6.0.0-rc.1.21415.6 6.0.0-rc.1.21415.6 4.5.4 4.5.0 6.0.0-rc.1.21415.6 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 - 6.0.0-beta.21416.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 + 6.0.0-beta.21518.1 1.0.0-prerelease.21416.5 1.0.0-prerelease.21416.5 @@ -142,37 +132,31 @@ 1.0.0-beta-build0015 1.0.4-preview6.19326.1 0.2.61701 - - 16.10.0 - $(RefOnlyMicrosoftBuildVersion) - $(RefOnlyMicrosoftBuildVersion) - $(RefOnlyMicrosoftBuildVersion) - 5.8.0 - 5.8.0 + 16.10.0 + $(MicrosoftBuildVersion) + 5.8.0 + 5.8.0 1.0.1-prerelease-00006 16.9.0-preview-20201201-01 1.0.0-prerelease.21404.1 1.0.0-prerelease.21404.1 1.0.2-alpha.0.21413.1 - 2.4.1 + 2.4.2-pre.9 2.4.2 1.3.0 12.0.3 2.0.4 4.12.0 2.14.3 - 6.0.100-rc.1.21412.8 + 6.0.200-preview.22055.18 - 5.0.0-preview-20201009.2 + 6.0.0-preview-20211019.1 - 6.0.100-preview.6.21416.1 + 6.0.100-1.21459.1 $(MicrosoftNETILLinkTasksVersion) - 6.0.0-rc.1.21416.1 + 6.0.0-rtm.22108.1 6.0.0-preview.7.21417.1 @@ -185,11 +169,11 @@ 11.1.0-alpha.1.21416.1 11.1.0-alpha.1.21416.1 - 6.0.0-rc.1.21416.1 + 6.0.2 $(MicrosoftNETWorkloadEmscriptenManifest60100Version) 1.1.87-gba258badda - 3.14.0-dotnet + 1.0.0-v3.14.0.5722 6.0.0-preview.5.21275.7 diff --git a/eng/build.ps1 b/eng/build.ps1 index af253dfb3dbd43..14dadeec13b1de 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -254,6 +254,10 @@ foreach ($argument in $PSBoundParameters.Keys) $failedBuilds = @() +# Disable targeting pack caching as we reference a partially constructed targeting pack and update it later. +# The later changes are ignored when using the cache. +$env:DOTNETSDK_ALLOW_TARGETING_PACK_CACHING=0 + if ($os -eq "Browser") { # override default arch for Browser, we only support wasm $arch = "wasm" diff --git a/eng/build.sh b/eng/build.sh index 128e720d3c0b2d..8836bde10c492f 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -468,6 +468,10 @@ fi initDistroRid $os $arch $crossBuild $portableBuild +# Disable targeting pack caching as we reference a partially constructed targeting pack and update it later. +# The later changes are ignored when using the cache. +export DOTNETSDK_ALLOW_TARGETING_PACK_CACHING=0 + # URL-encode space (%20) to avoid quoting issues until the msbuild call in /eng/common/tools.sh. # In *proj files (XML docs), URL-encoded string are rendered in their decoded form. cmakeargs="${cmakeargs// /%20}" diff --git a/eng/common/build.sh b/eng/common/build.sh index 55b298f16ccd1f..a16e18b174a759 100755 --- a/eng/common/build.sh +++ b/eng/common/build.sh @@ -187,6 +187,7 @@ function InitializeCustomToolset { } function Build { + InitializeToolset InitializeCustomToolset diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake index fc11001aa76c82..ec8971eb0195f8 100644 --- a/eng/common/cross/toolchain.cmake +++ b/eng/common/cross/toolchain.cmake @@ -138,8 +138,8 @@ function(add_toolchain_linker_flag Flag) if (NOT Config STREQUAL "") set(CONFIG_SUFFIX "_${Config}") endif() - set("CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}" "${CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}} ${Flag}" PARENT_SCOPE) - set("CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}" "${CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}} ${Flag}" PARENT_SCOPE) + set("CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}_INIT" "${CMAKE_EXE_LINKER_FLAGS${CONFIG_SUFFIX}_INIT} ${Flag}" PARENT_SCOPE) + set("CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}_INIT" "${CMAKE_SHARED_LINKER_FLAGS${CONFIG_SUFFIX}_INIT} ${Flag}" PARENT_SCOPE) endfunction() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/eng/common/generate-graph-files.ps1 b/eng/common/generate-graph-files.ps1 deleted file mode 100644 index 0728b1a8b570d6..00000000000000 --- a/eng/common/generate-graph-files.ps1 +++ /dev/null @@ -1,86 +0,0 @@ -Param( - [Parameter(Mandatory=$true)][string] $barToken, # Token generated at https://maestro-prod.westus2.cloudapp.azure.com/Account/Tokens - [Parameter(Mandatory=$true)][string] $gitHubPat, # GitHub personal access token from https://github.com/settings/tokens (no auth scopes needed) - [Parameter(Mandatory=$true)][string] $azdoPat, # Azure Dev Ops tokens from https://dev.azure.com/dnceng/_details/security/tokens (code read scope needed) - [Parameter(Mandatory=$true)][string] $outputFolder, # Where the graphviz.txt file will be created - [string] $darcVersion, # darc's version - [string] $graphvizVersion = '2.38', # GraphViz version - [switch] $includeToolset # Whether the graph should include toolset dependencies or not. i.e. arcade, optimization. For more about - # toolset dependencies see https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md#toolset-vs-product-dependencies -) - -function CheckExitCode ([string]$stage) -{ - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTelemetryError -Category 'Arcade' -Message "Something failed in stage: '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode - } -} - -try { - $ErrorActionPreference = 'Stop' - . $PSScriptRoot\tools.ps1 - - Import-Module -Name (Join-Path $PSScriptRoot 'native\CommonLibrary.psm1') - - Push-Location $PSScriptRoot - - Write-Host 'Installing darc...' - . .\darc-init.ps1 -darcVersion $darcVersion - CheckExitCode 'Running darc-init' - - $engCommonBaseDir = Join-Path $PSScriptRoot 'native\' - $graphvizInstallDir = CommonLibrary\Get-NativeInstallDirectory - $nativeToolBaseUri = 'https://netcorenativeassets.blob.core.windows.net/resource-packages/external' - $installBin = Join-Path $graphvizInstallDir 'bin' - - Write-Host 'Installing dot...' - .\native\install-tool.ps1 -ToolName graphviz -InstallPath $installBin -BaseUri $nativeToolBaseUri -CommonLibraryDirectory $engCommonBaseDir -Version $graphvizVersion -Verbose - - $darcExe = "$env:USERPROFILE\.dotnet\tools" - $darcExe = Resolve-Path "$darcExe\darc.exe" - - Create-Directory $outputFolder - - # Generate 3 graph descriptions: - # 1. Flat with coherency information - # 2. Graphviz (dot) file - # 3. Standard dependency graph - $graphVizFilePath = "$outputFolder\graphviz.txt" - $graphVizImageFilePath = "$outputFolder\graph.png" - $normalGraphFilePath = "$outputFolder\graph-full.txt" - $flatGraphFilePath = "$outputFolder\graph-flat.txt" - $baseOptions = @( '--github-pat', "$gitHubPat", '--azdev-pat', "$azdoPat", '--password', "$barToken" ) - - if ($includeToolset) { - Write-Host 'Toolsets will be included in the graph...' - $baseOptions += @( '--include-toolset' ) - } - - Write-Host 'Generating standard dependency graph...' - & "$darcExe" get-dependency-graph @baseOptions --output-file $normalGraphFilePath - CheckExitCode 'Generating normal dependency graph' - - Write-Host 'Generating flat dependency graph and graphviz file...' - & "$darcExe" get-dependency-graph @baseOptions --flat --coherency --graphviz $graphVizFilePath --output-file $flatGraphFilePath - CheckExitCode 'Generating flat and graphviz dependency graph' - - Write-Host "Generating graph image $graphVizFilePath" - $dotFilePath = Join-Path $installBin "graphviz\$graphvizVersion\release\bin\dot.exe" - & "$dotFilePath" -Tpng -o"$graphVizImageFilePath" "$graphVizFilePath" - CheckExitCode 'Generating graphviz image' - - Write-Host "'$graphVizFilePath', '$flatGraphFilePath', '$normalGraphFilePath' and '$graphVizImageFilePath' created!" -} -catch { - if (!$includeToolset) { - Write-Host 'This might be a toolset repo which includes only toolset dependencies. ' -NoNewline -ForegroundColor Yellow - Write-Host 'Since -includeToolset is not set there is no graph to create. Include -includeToolset and try again...' -ForegroundColor Yellow - } - Write-Host $_.ScriptStackTrace - Write-PipelineTelemetryError -Category 'Arcade' -Message $_ - ExitWithExitCode 1 -} finally { - Pop-Location -} \ No newline at end of file diff --git a/eng/common/init-tools-native.sh b/eng/common/init-tools-native.sh index 5bd205b5da3b79..3e6a8d6acf2f57 100755 --- a/eng/common/init-tools-native.sh +++ b/eng/common/init-tools-native.sh @@ -10,7 +10,7 @@ force=false download_retries=5 retry_wait_time_seconds=30 global_json_file="$(dirname "$(dirname "${scriptroot}")")/global.json" -declare -A native_assets +declare -a native_assets . $scriptroot/pipeline-logging-functions.sh . $scriptroot/native/common-library.sh diff --git a/eng/common/native/common-library.sh b/eng/common/native/common-library.sh index bf272dcf55a538..080c2c283ae468 100755 --- a/eng/common/native/common-library.sh +++ b/eng/common/native/common-library.sh @@ -148,8 +148,12 @@ function NewScriptShim { fi if [[ ! -f $tool_file_path ]]; then - Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Specified tool file path:'$tool_file_path' does not exist" - return 1 + # try to see if the path is lower cased + tool_file_path="$(echo $tool_file_path | tr "[:upper:]" "[:lower:]")" + if [[ ! -f $tool_file_path ]]; then + Write-PipelineTelemetryError -category 'NativeToolsBootstrap' "Specified tool file path:'$tool_file_path' does not exist" + return 1 + fi fi local shim_contents=$'#!/usr/bin/env bash\n' diff --git a/eng/common/post-build/publish-using-darc.ps1 b/eng/common/post-build/publish-using-darc.ps1 index 2427ca6b6aec74..8508397d77640e 100644 --- a/eng/common/post-build/publish-using-darc.ps1 +++ b/eng/common/post-build/publish-using-darc.ps1 @@ -5,13 +5,8 @@ param( [Parameter(Mandatory=$true)][string] $MaestroToken, [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro-prod.westus2.cloudapp.azure.com', [Parameter(Mandatory=$true)][string] $WaitPublishingFinish, - [Parameter(Mandatory=$false)][string] $EnableSourceLinkValidation, - [Parameter(Mandatory=$false)][string] $EnableSigningValidation, - [Parameter(Mandatory=$false)][string] $EnableNugetValidation, - [Parameter(Mandatory=$false)][string] $PublishInstallersAndChecksums, [Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters, - [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters, - [Parameter(Mandatory=$false)][string] $SigningValidationAdditionalParameters + [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters ) try { @@ -35,27 +30,6 @@ try { $optionalParams.Add("--no-wait") | Out-Null } - if ("false" -ne $PublishInstallersAndChecksums) { - $optionalParams.Add("--publish-installers-and-checksums") | Out-Null - } - - if ("true" -eq $EnableNugetValidation) { - $optionalParams.Add("--validate-nuget") | Out-Null - } - - if ("true" -eq $EnableSourceLinkValidation) { - $optionalParams.Add("--validate-sourcelinkchecksums") | Out-Null - } - - if ("true" -eq $EnableSigningValidation) { - $optionalParams.Add("--validate-signingchecksums") | Out-Null - - if ("" -ne $SigningValidationAdditionalParameters) { - $optionalParams.Add("--signing-validation-parameters") | Out-Null - $optionalParams.Add($SigningValidationAdditionalParameters) | Out-Null - } - } - & $darc add-build-to-channel ` --id $buildId ` --publishing-infra-version $PublishingInfraVersion ` diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 index 85c89861719ada..e8ab29afeb3330 100644 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ b/eng/common/post-build/sourcelink-validation.ps1 @@ -17,6 +17,7 @@ $global:RepoFiles = @{} $MaxParallelJobs = 16 $MaxRetries = 5 +$RetryWaitTimeInSeconds = 30 # Wait time between check for system load $SecondsBetweenLoadChecks = 10 @@ -99,21 +100,25 @@ $ValidatePackage = { $Status = 200 $Cache = $using:RepoFiles - $totalRetries = 0 + $attempts = 0 - while ($totalRetries -lt $using:MaxRetries) { + while ($attempts -lt $using:MaxRetries) { if ( !($Cache.ContainsKey($FilePath)) ) { try { $Uri = $Link -as [System.URI] - # Only GitHub links are valid - if ($Uri.AbsoluteURI -ne $null -and ($Uri.Host -match 'github' -or $Uri.Host -match 'githubusercontent')) { + if ($Link -match "submodules") { + # Skip submodule links until sourcelink properly handles submodules + $Status = 200 + } + elseif ($Uri.AbsoluteURI -ne $null -and ($Uri.Host -match 'github' -or $Uri.Host -match 'githubusercontent')) { + # Only GitHub links are valid $Status = (Invoke-WebRequest -Uri $Link -UseBasicParsing -Method HEAD -TimeoutSec 5).StatusCode } else { # If it's not a github link, we want to break out of the loop and not retry. $Status = 0 - $totalRetries = $using:MaxRetries + $attempts = $using:MaxRetries } } catch { @@ -123,9 +128,15 @@ $ValidatePackage = { } if ($Status -ne 200) { - $totalRetries++ + $attempts++ - if ($totalRetries -ge $using:MaxRetries) { + if ($attempts -lt $using:MaxRetries) + { + $attemptsLeft = $using:MaxRetries - $attempts + Write-Warning "Download failed, $attemptsLeft attempts remaining, will retry in $using:RetryWaitTimeInSeconds seconds" + Start-Sleep -Seconds $using:RetryWaitTimeInSeconds + } + else { if ($NumFailedLinks -eq 0) { if ($FailedFiles.Value -eq 0) { Write-Host diff --git a/eng/common/sdl/configure-sdl-tool.ps1 b/eng/common/sdl/configure-sdl-tool.ps1 index 4999c307088a03..adea8e8da2ab24 100644 --- a/eng/common/sdl/configure-sdl-tool.ps1 +++ b/eng/common/sdl/configure-sdl-tool.ps1 @@ -15,7 +15,9 @@ Param( # Optional: Additional params to add to any tool using CredScan. [string[]] $CrScanAdditionalRunConfigParams, # Optional: Additional params to add to any tool using PoliCheck. - [string[]] $PoliCheckAdditionalRunConfigParams + [string[]] $PoliCheckAdditionalRunConfigParams, + # Optional: Additional params to add to any tool using CodeQL/Semmle. + [string[]] $CodeQLAdditionalRunConfigParams ) $ErrorActionPreference = 'Stop' @@ -78,6 +80,11 @@ try { $tool.Args += "Target < $TargetDirectory" } $tool.Args += $PoliCheckAdditionalRunConfigParams + } elseif ($tool.Name -eq 'semmle' -or $tool.Name -eq 'codeql') { + if ($targetDirectory) { + $tool.Args += "`"SourceCodeDirectory < $TargetDirectory`"" + } + $tool.Args += $CodeQLAdditionalRunConfigParams } # Create variable pointing to the args array directly so we can use splat syntax later. diff --git a/eng/common/sdl/execute-all-sdl-tools.ps1 b/eng/common/sdl/execute-all-sdl-tools.ps1 index 1157151f4862a2..b9fe7317964319 100644 --- a/eng/common/sdl/execute-all-sdl-tools.ps1 +++ b/eng/common/sdl/execute-all-sdl-tools.ps1 @@ -34,6 +34,7 @@ Param( [string] $GuardianLoggerLevel='Standard', # Optional: the logger level for the Guardian CLI; options are Trace, Verbose, Standard, Warning, and Error [string[]] $CrScanAdditionalRunConfigParams, # Optional: Additional Params to custom build a CredScan run config in the format @("xyz:abc","sdf:1") [string[]] $PoliCheckAdditionalRunConfigParams, # Optional: Additional Params to custom build a Policheck run config in the format @("xyz:abc","sdf:1") + [string[]] $CodeQLAdditionalRunConfigParams, # Optional: Additional Params to custom build a Semmle/CodeQL run config in the format @("xyz < abc","sdf < 1") [bool] $BreakOnFailure=$False # Optional: Fail the build if there were errors during the run ) @@ -105,7 +106,8 @@ try { -AzureDevOpsAccessToken $AzureDevOpsAccessToken ` -GuardianLoggerLevel $GuardianLoggerLevel ` -CrScanAdditionalRunConfigParams $CrScanAdditionalRunConfigParams ` - -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams + -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams ` + -CodeQLAdditionalRunConfigParams $CodeQLAdditionalRunConfigParams if ($BreakOnFailure) { Exit-IfNZEC "Sdl" } diff --git a/eng/common/sdl/packages.config b/eng/common/sdl/packages.config index 3bd8b29ebd721b..b7bcfe38caf15f 100644 --- a/eng/common/sdl/packages.config +++ b/eng/common/sdl/packages.config @@ -1,4 +1,4 @@ - + diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 69eb67849d741d..d0a1ea8b0f23fd 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -29,14 +29,6 @@ parameters: # Optional: download a list of pipeline artifacts. 'downloadArtifacts' controls build artifacts, # not pipeline artifacts, so doesn't affect the use of this parameter. pipelineArtifactNames: [] - # Optional: location and ID of the AzDO build that the build/pipeline artifacts should be - # downloaded from. By default, uses runtime expressions to decide based on the variables set by - # the 'setupMaestroVars' dependency. Overriding this parameter is necessary if SDL tasks are - # running without Maestro++/BAR involved, or to download artifacts from a specific existing build - # to iterate quickly on SDL changes. - AzDOProjectName: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - AzDOPipelineId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - AzDOBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] jobs: - job: Run_SDL @@ -54,21 +46,26 @@ jobs: # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in # sync with the packages.config file. - name: DefaultGuardianVersion - value: 0.53.3 + value: 0.110.1 - name: GuardianVersion value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} - name: GuardianPackagesConfigFile value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config pool: - # To extract archives (.tar.gz, .zip), we need access to "tar", added in Windows 10/2019. - ${{ if eq(parameters.extractArchiveArtifacts, 'false') }}: - name: Hosted VS2017 - ${{ if ne(parameters.extractArchiveArtifacts, 'false') }}: - vmImage: windows-2019 + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: - checkout: self clean: true + - template: /eng/common/templates/post-build/setup-maestro-vars.yml + - ${{ if ne(parameters.downloadArtifacts, 'false')}}: - ${{ if ne(parameters.artifactNames, '') }}: - ${{ each artifactName in parameters.artifactNames }}: diff --git a/eng/common/templates/job/generate-graph-files.yml b/eng/common/templates/job/generate-graph-files.yml deleted file mode 100644 index e54ce956f9088e..00000000000000 --- a/eng/common/templates/job/generate-graph-files.yml +++ /dev/null @@ -1,48 +0,0 @@ -parameters: - # Optional: dependencies of the job - dependsOn: '' - - # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: {} - - # Optional: Include toolset dependencies in the generated graph files - includeToolset: false - -jobs: -- job: Generate_Graph_Files - - dependsOn: ${{ parameters.dependsOn }} - - displayName: Generate Graph Files - - pool: ${{ parameters.pool }} - - variables: - # Publish-Build-Assets provides: MaestroAccessToken, BotAccount-dotnet-maestro-bot-PAT - # DotNet-AllOrgs-Darc-Pats provides: dn-bot-devdiv-dnceng-rw-code-pat - - group: Publish-Build-Assets - - group: DotNet-AllOrgs-Darc-Pats - - name: _GraphArguments - value: -gitHubPat $(BotAccount-dotnet-maestro-bot-PAT) - -azdoPat $(dn-bot-devdiv-dnceng-rw-code-pat) - -barToken $(MaestroAccessToken) - -outputFolder '$(Build.StagingDirectory)/GraphFiles/' - - ${{ if ne(parameters.includeToolset, 'false') }}: - - name: _GraphArguments - value: ${{ variables._GraphArguments }} -includeToolset - - steps: - - task: PowerShell@2 - displayName: Generate Graph Files - inputs: - filePath: eng\common\generate-graph-files.ps1 - arguments: $(_GraphArguments) - continueOnError: true - - task: PublishBuildArtifacts@1 - displayName: Publish Graph to Artifacts - inputs: - PathtoPublish: '$(Build.StagingDirectory)/GraphFiles' - PublishLocation: Container - ArtifactName: GraphFiles - continueOnError: true - condition: always() diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 8669679348024c..30d1de5835e828 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -24,6 +24,7 @@ parameters: enablePublishBuildAssets: false enablePublishTestResults: false enablePublishUsingPipelines: false + disableComponentGovernance: false mergeTestResults: false testRunTitle: '' testResultsFormat: '' @@ -103,7 +104,7 @@ jobs: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - - task: MicroBuildSigningPlugin@2 + - task: MicroBuildSigningPlugin@3 displayName: Install MicroBuild plugin inputs: signType: $(_SignType) @@ -136,6 +137,10 @@ jobs: richNavLogOutputDirectory: $(Build.SourcesDirectory)/artifacts/bin continueOnError: true + - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest'), ne(parameters.disableComponentGovernance, 'true')) }}: + - task: ComponentGovernanceComponentDetection@0 + continueOnError: true + - ${{ if eq(parameters.enableMicrobuild, 'true') }}: - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: MicroBuildCleanup@1 diff --git a/eng/common/templates/job/onelocbuild.yml b/eng/common/templates/job/onelocbuild.yml index e8bc77d2ebbe39..9d1e3042d8a6c0 100644 --- a/eng/common/templates/job/onelocbuild.yml +++ b/eng/common/templates/job/onelocbuild.yml @@ -3,15 +3,15 @@ parameters: dependsOn: '' # Optional: A defined YAML pool - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#pool - pool: - vmImage: vs2017-win2016 - + pool: '' + CeapexPat: $(dn-bot-ceapex-package-r) # PAT for the loc AzDO instance https://dev.azure.com/ceapex GithubPat: $(BotAccount-dotnet-bot-repo-PAT) SourcesDirectory: $(Build.SourcesDirectory) CreatePr: true AutoCompletePr: false + ReusePr: true UseLfLineEndings: true UseCheckedInLocProjectJson: false LanguageSet: VS_Main_Languages @@ -30,7 +30,18 @@ jobs: displayName: OneLocBuild - pool: ${{ parameters.pool }} + ${{ if ne(parameters.pool, '') }}: + pool: ${{ parameters.pool }} + ${{ if eq(parameters.pool, '') }}: + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 variables: - group: OneLocBuildVariables # Contains the CeapexPat and GithubPat @@ -64,6 +75,8 @@ jobs: ${{ if eq(parameters.CreatePr, true) }}: isAutoCompletePrSelected: ${{ parameters.AutoCompletePr }} isUseLfLineEndingsSelected: ${{ parameters.UseLfLineEndings }} + ${{ if eq(parameters.RepoType, 'gitHub') }}: + isShouldReusePrSelected: ${{ parameters.ReusePr }} packageSourceAuth: patAuth patVariable: ${{ parameters.CeapexPat }} ${{ if eq(parameters.RepoType, 'gitHub') }}: diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index fe9dfdf720cf8a..d91bf9147116f0 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -38,10 +38,6 @@ jobs: value: ${{ parameters.configuration }} - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - # Skip component governance and codesign validation for SDL. These jobs - # create no content. - - name: skipComponentGovernanceDetection - value: true - name: runCodesignValidationInjection value: false diff --git a/eng/common/templates/job/source-build.yml b/eng/common/templates/job/source-build.yml index 5023d36dcb3c5b..5cd5325d7b4e6b 100644 --- a/eng/common/templates/job/source-build.yml +++ b/eng/common/templates/job/source-build.yml @@ -31,11 +31,6 @@ parameters: # container and pool. platform: {} - # The default VM host AzDO pool. This should be capable of running Docker containers: almost all - # source-build builds run in Docker, including the default managed platform. - defaultContainerHostPool: - vmImage: ubuntu-20.04 - jobs: - job: ${{ parameters.jobNamePrefix }}_${{ parameters.platform.name }} displayName: Source-Build (${{ parameters.platform.name }}) @@ -47,7 +42,15 @@ jobs: container: ${{ parameters.platform.container }} ${{ if eq(parameters.platform.pool, '') }}: - pool: ${{ parameters.defaultContainerHostPool }} + # The default VM host AzDO pool. This should be capable of running Docker containers: almost all + # source-build builds run in Docker, including the default managed platform. + pool: + ${{ if eq(variables['System.TeamProject'], 'public') }}: + name: NetCore1ESPool-Public + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open + ${{ if eq(variables['System.TeamProject'], 'internal') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 ${{ if ne(parameters.platform.pool, '') }}: pool: ${{ parameters.platform.pool }} diff --git a/eng/common/templates/job/source-index-stage1.yml b/eng/common/templates/job/source-index-stage1.yml index e60fdbccc9ec18..d8990549e8097e 100644 --- a/eng/common/templates/job/source-index-stage1.yml +++ b/eng/common/templates/job/source-index-stage1.yml @@ -6,7 +6,7 @@ parameters: preSteps: [] binlogPath: artifacts/log/Debug/Build.binlog pool: - vmImage: vs2017-win2016 + vmImage: windows-2019 condition: '' dependsOn: '' @@ -34,24 +34,24 @@ jobs: inputs: packageType: sdk version: 3.1.x - - - script: ${{ parameters.sourceIndexBuildCommand }} - displayName: Build Repository + installationPath: $(Agent.TempDirectory)/dotnet + workingDirectory: $(Agent.TempDirectory) - script: | - dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path .source-index/tools - dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path .source-index/tools - echo ##vso[task.prependpath]$(Build.SourcesDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools + $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version $(SourceIndexPackageVersion) --add-source $(SourceIndexPackageSource) --tool-path $(Agent.TempDirectory)/.source-index/tools displayName: Download Tools + # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. + workingDirectory: $(Agent.TempDirectory) + + - script: ${{ parameters.sourceIndexBuildCommand }} + displayName: Build Repository - - script: BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output + - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i $(BinlogPath) -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output displayName: Process Binlog into indexable sln - env: - DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 - ${{ if and(eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) + - script: $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) displayName: Upload stage1 artifacts to source index env: BLOB_CONTAINER_URL: $(source-dot-net-stage1-blob-container-url) - DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 diff --git a/eng/common/templates/jobs/codeql-build.yml b/eng/common/templates/jobs/codeql-build.yml new file mode 100644 index 00000000000000..f7dc5ea4aaa63c --- /dev/null +++ b/eng/common/templates/jobs/codeql-build.yml @@ -0,0 +1,31 @@ +parameters: + # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md + continueOnError: false + # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job + jobs: [] + # Optional: if specified, restore and use this version of Guardian instead of the default. + overrideGuardianVersion: '' + +jobs: +- template: /eng/common/templates/jobs/jobs.yml + parameters: + enableMicrobuild: false + enablePublishBuildArtifacts: false + enablePublishTestResults: false + enablePublishBuildAssets: false + enablePublishUsingPipelines: false + enableTelemetry: true + + variables: + - group: Publish-Build-Assets + # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in + # sync with the packages.config file. + - name: DefaultGuardianVersion + value: 0.109.0 + - name: GuardianPackagesConfigFile + value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config + - name: GuardianVersion + value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} + + jobs: ${{ parameters.jobs }} + diff --git a/eng/common/templates/jobs/jobs.yml b/eng/common/templates/jobs/jobs.yml index a1f8fce96ca81d..70d44735ace4a9 100644 --- a/eng/common/templates/jobs/jobs.yml +++ b/eng/common/templates/jobs/jobs.yml @@ -8,6 +8,10 @@ parameters: # Optional: Enable publishing using release pipelines enablePublishUsingPipelines: false + # Optional: Disable component governance detection. In general, component governance + # should be on for all jobs. Use only in the event of issues. + disableComponentGovernance: false + # Optional: Enable running the source-build jobs to build repo from source enableSourceBuild: false @@ -83,17 +87,15 @@ jobs: - ${{ if eq(parameters.enableSourceBuild, true) }}: - Source_Build_Complete pool: - vmImage: vs2017-win2016 + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + runAsPublic: ${{ parameters.runAsPublic }} publishUsingPipelines: ${{ parameters.enablePublishUsingPipelines }} enablePublishBuildArtifacts: ${{ parameters.enablePublishBuildArtifacts }} - - - ${{ if eq(parameters.graphFileGeneration.enabled, true) }}: - - template: ../job/generate-graph-files.yml - parameters: - continueOnError: ${{ parameters.continueOnError }} - includeToolset: ${{ parameters.graphFileGeneration.includeToolset }} - dependsOn: - - Asset_Registry_Publish - pool: - vmImage: vs2017-win2016 diff --git a/eng/common/templates/post-build/channels/generic-internal-channel.yml b/eng/common/templates/post-build/channels/generic-internal-channel.yml deleted file mode 100644 index 8990dfc8c87cc3..00000000000000 --- a/eng/common/templates/post-build/channels/generic-internal-channel.yml +++ /dev/null @@ -1,190 +0,0 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate - publishInstallersAndChecksums: true - symbolPublishingAdditionalParameters: '' - stageName: '' - channelName: '' - channelId: '' - transportFeed: '' - shippingFeed: '' - symbolsFeed: '' - -stages: -- stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} - variables: - - template: ../common-variables.yml - displayName: ${{ parameters.channelName }} Publishing - jobs: - - template: ../setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - job: publish_symbols - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - variables: - - group: DotNet-Symbol-Server-Pats - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PdbArtifacts/** - BlobArtifacts/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - /p:PublishToMSDL=false - ${{ parameters.symbolPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PackageArtifacts/** - BlobArtifacts/** - AssetManifests/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:PublishingInfraVersion=2 - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:ChecksumsTargetStaticFeed=$(InternalChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(InternalChecksumsBlobFeedKey) - /p:InstallersTargetStaticFeed=$(InternalInstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(InternalInstallersBlobFeedKey) - /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:PublishToMSDL=false - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - - template: ../../steps/add-build-to-channel.yml - parameters: - ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/channels/generic-public-channel.yml b/eng/common/templates/post-build/channels/generic-public-channel.yml deleted file mode 100644 index 3220c6a4f92ffb..00000000000000 --- a/eng/common/templates/post-build/channels/generic-public-channel.yml +++ /dev/null @@ -1,192 +0,0 @@ -parameters: - BARBuildId: '' - PromoteToChannelIds: '' - artifactsPublishingAdditionalParameters: '' - dependsOn: - - Validate - publishInstallersAndChecksums: true - symbolPublishingAdditionalParameters: '' - stageName: '' - channelName: '' - channelId: '' - transportFeed: '' - shippingFeed: '' - symbolsFeed: '' - # If the channel name is empty, no links will be generated - akaMSChannelName: '' - -stages: -- stage: ${{ parameters.stageName }} - dependsOn: ${{ parameters.dependsOn }} - variables: - - template: ../common-variables.yml - displayName: ${{ parameters.channelName }} Publishing - jobs: - - template: ../setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - job: publish_symbols - displayName: Symbol Publishing - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - variables: - - group: DotNet-Symbol-Server-Pats - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PdbArtifacts/** - BlobArtifacts/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - # This is necessary whenever we want to publish/restore to an AzDO private feed - # Since sdk-task.ps1 tries to restore packages we need to do this authentication here - # otherwise it'll complain about accessing a private feed. - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet - /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) - /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) - /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:SymbolPublishingExclusionsFile='$(Build.SourcesDirectory)/eng/SymbolPublishingExclusionsFile.txt' - /p:Configuration=Release - ${{ parameters.symbolPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'SymbolPublishing' - - - job: publish_assets - displayName: Publish Assets - dependsOn: setupMaestroVars - timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - name: IsStableBuild - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] - - name: ArtifactsCategory - value: ${{ coalesce(variables._DotNetArtifactsCategory, '.NETCore') }} - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'], format('[{0}]', ${{ parameters.channelId }} )) - pool: - vmImage: 'windows-2019' - steps: - - script: echo "##vso[task.logissue type=warning]Going forward, v2 Arcade publishing is no longer supported. Please read https://github.com/dotnet/arcade/blob/main/Documentation/CorePackages/Publishing.md for details, then contact dnceng if you have further questions." - displayName: Warn about v2 Arcade Publishing Usage - - - task: DownloadBuildArtifacts@0 - displayName: Download Build Assets - continueOnError: true - inputs: - buildType: specific - buildVersionToDownload: specific - project: $(AzDOProjectName) - pipeline: $(AzDOPipelineId) - buildId: $(AzDOBuildId) - downloadType: 'specific' - itemPattern: | - PackageArtifacts/** - BlobArtifacts/** - AssetManifests/** - downloadPath: '$(Build.ArtifactStagingDirectory)' - checkDownloadedFiles: true - - - task: NuGetToolInstaller@1 - displayName: 'Install NuGet.exe' - - # This is necessary whenever we want to publish/restore to an AzDO private feed - - task: NuGetAuthenticate@0 - displayName: 'Authenticate to AzDO Feeds' - - - task: PowerShell@2 - displayName: Enable cross-org publishing - inputs: - filePath: eng\common\enable-cross-org-publishing.ps1 - arguments: -token $(dn-bot-dnceng-artifact-feeds-rw) - - - task: PowerShell@2 - displayName: Publish Assets - inputs: - filePath: eng\common\sdk-task.ps1 - arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet - /p:PublishingInfraVersion=2 - /p:ArtifactsCategory=$(ArtifactsCategory) - /p:IsStableBuild=$(IsStableBuild) - /p:IsInternalBuild=$(IsInternalBuild) - /p:RepositoryName=$(Build.Repository.Name) - /p:CommitSha=$(Build.SourceVersion) - /p:NugetPath=$(NuGetExeToolPath) - /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-universal-packages-rw)' - /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' - /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' - /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' - /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' - /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' - /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' - /p:Configuration=Release - /p:PublishInstallersAndChecksums=${{ parameters.publishInstallersAndChecksums }} - /p:InstallersTargetStaticFeed=$(InstallersBlobFeedUrl) - /p:InstallersAzureAccountKey=$(dotnetcli-storage-key) - /p:ChecksumsTargetStaticFeed=$(ChecksumsBlobFeedUrl) - /p:ChecksumsAzureAccountKey=$(dotnetclichecksums-storage-key) - /p:AzureDevOpsStaticShippingFeed='${{ parameters.shippingFeed }}' - /p:AzureDevOpsStaticShippingFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticTransportFeed='${{ parameters.transportFeed }}' - /p:AzureDevOpsStaticTransportFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:AzureDevOpsStaticSymbolsFeed='${{ parameters.symbolsFeed }}' - /p:AzureDevOpsStaticSymbolsFeedKey='$(dn-bot-dnceng-artifact-feeds-rw)' - /p:LatestLinkShortUrlPrefix=dotnet/'${{ parameters.akaMSChannelName }}' - /p:AkaMSClientId=$(akams-client-id) - /p:AkaMSClientSecret=$(akams-client-secret) - ${{ parameters.artifactsPublishingAdditionalParameters }} - - - template: ../../steps/publish-logs.yml - parameters: - StageLabel: '${{ parameters.stageName }}' - JobLabel: 'AssetsPublishing' - - - template: ../../steps/add-build-to-channel.yml - parameters: - ChannelId: ${{ parameters.channelId }} diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index c99fd7503767cd..1ac7f49a43ca87 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -4,54 +4,6 @@ variables: - group: DotNet-DotNetCli-Storage - group: DotNet-MSRC-Storage - group: Publish-Build-Assets - - # .NET Core 3.1 Dev - - name: PublicDevRelease_31_Channel_Id - value: 128 - - # .NET 5 Dev - - name: Net_5_Dev_Channel_Id - value: 131 - - # .NET Eng - Validation - - name: Net_Eng_Validation_Channel_Id - value: 9 - - # .NET Eng - Latest - - name: Net_Eng_Latest_Channel_Id - value: 2 - - # .NET 3 Eng - Validation - - name: NET_3_Eng_Validation_Channel_Id - value: 390 - - # .NET 3 Eng - - name: NetCore_3_Tools_Channel_Id - value: 344 - - # .NET Core 3.0 Internal Servicing - - name: InternalServicing_30_Channel_Id - value: 184 - - # .NET Core 3.0 Release - - name: PublicRelease_30_Channel_Id - value: 19 - - # .NET Core 3.1 Release - - name: PublicRelease_31_Channel_Id - value: 129 - - # General Testing - - name: GeneralTesting_Channel_Id - value: 529 - - # .NET Core 3.1 Blazor Features - - name: NetCore_31_Blazor_Features_Channel_Id - value: 531 - - # .NET Core Experimental - - name: NetCore_Experimental_Channel_Id - value: 562 # Whether the build is internal or not - name: IsInternalBuild @@ -70,30 +22,5 @@ variables: - name: SymbolToolVersion value: 1.0.1 - # Feed Configurations - # These should include the suffix "/index.json" - - # Default locations for Installers and checksums - # Public Locations - - name: ChecksumsBlobFeedUrl - value: https://dotnetclichecksums.blob.core.windows.net/dotnet/index.json - - name: InstallersBlobFeedUrl - value: https://dotnetcli.blob.core.windows.net/dotnet/index.json - - # Private Locations - - name: InternalChecksumsBlobFeedUrl - value: https://dotnetclichecksumsmsrc.blob.core.windows.net/dotnet/index.json - - name: InternalChecksumsBlobFeedKey - value: $(dotnetclichecksumsmsrc-storage-key) - - - name: InternalInstallersBlobFeedUrl - value: https://dotnetclimsrc.blob.core.windows.net/dotnet/index.json - - name: InternalInstallersBlobFeedKey - value: $(dotnetclimsrc-access-key) - - # Skip component governance and codesign validation for SDL. These jobs - # create no content. - - name: skipComponentGovernanceDetection - value: true - name: runCodesignValidationInjection value: false diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 4f79cf0f33703f..24e92a275a4fb0 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -1,113 +1,114 @@ parameters: - # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. - # Publishing V2 accepts optionally outlining the publishing stages - default is inline. - # Publishing V3 DOES NOT accept inlining the publishing stages. - publishingInfraVersion: 2 - # When set to true the publishing templates from the repo will be used - # otherwise Darc add-build-to-channel will be used to trigger the promotion pipeline - inline: true - - # Only used if inline==false. When set to true will stall the current build until - # the Promotion Pipeline build finishes. Otherwise, the current build will continue - # execution concurrently with the promotion build. - waitPublishingFinish: true - - BARBuildId: '' - PromoteToChannelIds: '' - - enableSourceLinkValidation: false - enableSigningValidation: true - enableSymbolValidation: false - enableNugetValidation: true - publishInstallersAndChecksums: true - SDLValidationParameters: - enable: false - continueOnError: false - params: '' - artifactNames: '' - downloadArtifacts: true + # Which publishing infra should be used. THIS SHOULD MATCH THE VERSION ON THE BUILD MANIFEST. + # Publishing V1 is no longer supported + # Publishing V2 is no longer supported + # Publishing V3 is the default + - name: publishingInfraVersion + displayName: Which version of publishing should be used to promote the build definition? + type: number + default: 3 + values: + - 3 + + - name: BARBuildId + displayName: BAR Build Id + type: number + default: 0 + + - name: PromoteToChannelIds + displayName: Channel to promote BARBuildId to + type: string + default: '' + + - name: enableSourceLinkValidation + displayName: Enable SourceLink validation + type: boolean + default: false + + - name: enableSigningValidation + displayName: Enable signing validation + type: boolean + default: true + + - name: enableSymbolValidation + displayName: Enable symbol validation + type: boolean + default: false + + - name: enableNugetValidation + displayName: Enable NuGet validation + type: boolean + default: true + + - name: publishInstallersAndChecksums + displayName: Publish installers and checksums + type: boolean + default: true + + - name: SDLValidationParameters + type: object + default: + enable: false + continueOnError: false + params: '' + artifactNames: '' + downloadArtifacts: true # These parameters let the user customize the call to sdk-task.ps1 for publishing # symbols & general artifacts as well as for signing validation - symbolPublishingAdditionalParameters: '' - artifactsPublishingAdditionalParameters: '' - signingValidationAdditionalParameters: '' + - name: symbolPublishingAdditionalParameters + displayName: Symbol publishing additional parameters + type: string + default: '' + + - name: artifactsPublishingAdditionalParameters + displayName: Artifact publishing additional parameters + type: string + default: '' + + - name: signingValidationAdditionalParameters + displayName: Signing validation additional parameters + type: string + default: '' # Which stages should finish execution before post-build stages start - validateDependsOn: - - build - publishDependsOn: - - Validate + - name: validateDependsOn + type: object + default: + - build - # Channel ID's instantiated in this file. - # When adding a new channel implementation the call to `check-channel-consistency.ps1` - # needs to be updated with the new channel ID - NetEngLatestChannelId: 2 - NetEngValidationChannelId: 9 - NetDev5ChannelId: 131 - NetDev6ChannelId: 1296 - GeneralTestingChannelId: 529 - NETCoreToolingDevChannelId: 548 - NETCoreToolingReleaseChannelId: 549 - NETInternalToolingChannelId: 551 - NETCoreExperimentalChannelId: 562 - NetEngServicesIntChannelId: 678 - NetEngServicesProdChannelId: 679 - NetCoreSDK313xxChannelId: 759 - NetCoreSDK313xxInternalChannelId: 760 - NetCoreSDK314xxChannelId: 921 - NetCoreSDK314xxInternalChannelId: 922 - VS166ChannelId: 1010 - VS167ChannelId: 1011 - VS168ChannelId: 1154 - VSMasterChannelId: 1012 - VS169ChannelId: 1473 - VS1610ChannelId: 1692 + - name: publishDependsOn + type: object + default: + - Validate stages: -- ${{ if or(and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')), eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: +- ${{ if or(eq( parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - stage: Validate dependsOn: ${{ parameters.validateDependsOn }} displayName: Validate Build Assets variables: - template: common-variables.yml jobs: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}: - - job: - displayName: Post-build Checks - dependsOn: setupMaestroVars - variables: - - name: TargetChannels - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.TargetChannels'] ] - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Maestro Channels Consistency - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/check-channel-consistency.ps1 - arguments: -PromoteToChannels "$(TargetChannels)" - -AvailableChannelIds ${{parameters.NetEngLatestChannelId}},${{parameters.NetEngValidationChannelId}},${{parameters.NetDev5ChannelId}},${{parameters.NetDev6ChannelId}},${{parameters.GeneralTestingChannelId}},${{parameters.NETCoreToolingDevChannelId}},${{parameters.NETCoreToolingReleaseChannelId}},${{parameters.NETInternalToolingChannelId}},${{parameters.NETCoreExperimentalChannelId}},${{parameters.NetEngServicesIntChannelId}},${{parameters.NetEngServicesProdChannelId}},${{parameters.NetCoreSDK313xxChannelId}},${{parameters.NetCoreSDK313xxInternalChannelId}},${{parameters.NetCoreSDK314xxChannelId}},${{parameters.NetCoreSDK314xxInternalChannelId}},${{parameters.VS166ChannelId}},${{parameters.VS167ChannelId}},${{parameters.VS168ChannelId}},${{parameters.VSMasterChannelId}},${{parameters.VS169ChannelId}},${{parameters.VS1610ChannelId}} - - job: displayName: NuGet Validation - dependsOn: setupMaestroVars condition: eq( ${{ parameters.enableNugetValidation }}, 'true') pool: - vmImage: 'windows-2019' - variables: - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Package Artifacts inputs: @@ -128,19 +129,22 @@ stages: - job: displayName: Signing Validation - dependsOn: setupMaestroVars condition: and( eq( ${{ parameters.enableSigningValidation }}, 'true'), ne( variables['PostBuildSign'], 'true')) - variables: - - template: common-variables.yml - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Package Artifacts inputs: @@ -185,19 +189,22 @@ stages: - job: displayName: SourceLink Validation - dependsOn: setupMaestroVars condition: eq( ${{ parameters.enableSourceLinkValidation }}, 'true') - variables: - - template: common-variables.yml - - name: AzDOProjectName - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOProjectName'] ] - - name: AzDOPipelineId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOPipelineId'] ] - - name: AzDOBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.AzDOBuildId'] ] pool: - vmImage: 'windows-2019' + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + - task: DownloadBuildArtifacts@0 displayName: Download Blob Artifacts inputs: @@ -223,367 +230,46 @@ stages: - template: /eng/common/templates/job/execute-sdl.yml parameters: enable: ${{ parameters.SDLValidationParameters.enable }} - dependsOn: setupMaestroVars additionalParameters: ${{ parameters.SDLValidationParameters.params }} continueOnError: ${{ parameters.SDLValidationParameters.continueOnError }} artifactNames: ${{ parameters.SDLValidationParameters.artifactNames }} downloadArtifacts: ${{ parameters.SDLValidationParameters.downloadArtifacts }} -- ${{ if or(ge(parameters.publishingInfraVersion, 3), eq(parameters.inline, 'false')) }}: - - stage: publish_using_darc - ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.publishDependsOn }} - ${{ if and(ne(parameters.enableNugetValidation, 'true'), ne(parameters.enableSigningValidation, 'true'), ne(parameters.enableSourceLinkValidation, 'true'), ne(parameters.SDLValidationParameters.enable, 'true')) }}: - dependsOn: ${{ parameters.validateDependsOn }} - displayName: Publish using Darc - variables: - - template: common-variables.yml - jobs: - - template: setup-maestro-vars.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - - - job: - displayName: Publish Using Darc - dependsOn: setupMaestroVars - timeoutInMinutes: 120 - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Publish Using Darc - inputs: - filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 - arguments: -BuildId $(BARBuildId) - -PublishingInfraVersion ${{ parameters.PublishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' - -MaestroToken '$(MaestroApiAccessToken)' - -WaitPublishingFinish ${{ parameters.waitPublishingFinish }} - -PublishInstallersAndChecksums ${{ parameters.publishInstallersAndChecksums }} - -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' - -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' - -- ${{ if and(le(parameters.publishingInfraVersion, 2), eq(parameters.inline, 'true')) }}: - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Dev5_Publish' - channelName: '.NET 5 Dev' - akaMSChannelName: 'net5/dev' - channelId: ${{ parameters.NetDev5ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NetCore_Dev6_Publish' - channelName: '.NET 6 Dev' - akaMSChannelName: 'net6/dev' - channelId: ${{ parameters.NetDev6ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Latest_Publish' - channelName: '.NET Eng - Latest' - akaMSChannelName: 'eng/daily' - channelId: ${{ parameters.NetEngLatestChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Validation_Publish' - channelName: '.NET Eng - Validation' - akaMSChannelName: 'eng/validation' - channelId: ${{ parameters.NetEngValidationChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'General_Testing_Publish' - channelName: 'General Testing' - akaMSChannelName: 'generaltesting' - channelId: ${{ parameters.GeneralTestingChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/general-testing-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Tooling_Dev_Publishing' - channelName: '.NET Core Tooling Dev' - channelId: ${{ parameters.NETCoreToolingDevChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Tooling_Release_Publishing' - channelName: '.NET Core Tooling Release' - channelId: ${{ parameters.NETCoreToolingReleaseChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NET_Internal_Tooling_Publishing' - channelName: '.NET Internal Tooling' - channelId: ${{ parameters.NETInternalToolingChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet-tools-internal-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_Experimental_Publishing' - channelName: '.NET Core Experimental' - channelId: ${{ parameters.NETCoreExperimentalChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-experimental-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Services_Int_Publish' - channelName: '.NET Eng Services - Int' - channelId: ${{ parameters.NetEngServicesIntChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'Net_Eng_Services_Prod_Publish' - channelName: '.NET Eng Services - Prod' - channelId: ${{ parameters.NetEngServicesProdChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_314xx_Publishing' - channelName: '.NET Core SDK 3.1.4xx' - channelId: ${{ parameters.NetCoreSDK314xxChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_314xx_Internal_Publishing' - channelName: '.NET Core SDK 3.1.4xx Internal' - channelId: ${{ parameters.NetCoreSDK314xxInternalChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_313xx_Publishing' - channelName: '.NET Core SDK 3.1.3xx' - channelId: ${{ parameters.NetCoreSDK313xxChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet3.1-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-internal-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'NETCore_SDK_313xx_Internal_Publishing' - channelName: '.NET Core SDK 3.1.3xx Internal' - channelId: ${{ parameters.NetCoreSDK313xxInternalChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS16_6_Publishing' - channelName: 'VS 16.6' - channelId: ${{ parameters.VS166ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS16_7_Publishing' - channelName: 'VS 16.7' - channelId: ${{ parameters.VS167ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS16_8_Publishing' - channelName: 'VS 16.8' - channelId: ${{ parameters.VS168ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS_Master_Publishing' - channelName: 'VS Master' - channelId: ${{ parameters.VSMasterChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS_16_9_Publishing' - channelName: 'VS 16.9' - channelId: ${{ parameters.VS169ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' - - - template: \eng\common\templates\post-build\channels\generic-public-channel.yml - parameters: - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} - artifactsPublishingAdditionalParameters: ${{ parameters.artifactsPublishingAdditionalParameters }} - dependsOn: ${{ parameters.publishDependsOn }} - publishInstallersAndChecksums: ${{ parameters.publishInstallersAndChecksums }} - symbolPublishingAdditionalParameters: ${{ parameters.symbolPublishingAdditionalParameters }} - stageName: 'VS_16_10_Publishing' - channelName: 'VS 16.10' - channelId: ${{ parameters.VS1610ChannelId }} - transportFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-transport/nuget/v3/index.json' - shippingFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json' - symbolsFeed: 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools-symbols/nuget/v3/index.json' +- stage: publish_using_darc + ${{ if or(eq(parameters.enableNugetValidation, 'true'), eq(parameters.enableSigningValidation, 'true'), eq(parameters.enableSourceLinkValidation, 'true'), eq(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.publishDependsOn }} + ${{ if and(ne(parameters.enableNugetValidation, 'true'), ne(parameters.enableSigningValidation, 'true'), ne(parameters.enableSourceLinkValidation, 'true'), ne(parameters.SDLValidationParameters.enable, 'true')) }}: + dependsOn: ${{ parameters.validateDependsOn }} + displayName: Publish using Darc + variables: + - template: common-variables.yml + jobs: + - job: + displayName: Publish Using Darc + timeoutInMinutes: 120 + pool: + # We don't use the collection uri here because it might vary (.visualstudio.com vs. dev.azure.com) + ${{ if eq(variables['System.TeamProject'], 'DevDiv') }}: + name: VSEngSS-MicroBuild2022-1ES + demands: Cmd + # If it's not devdiv, it's dnceng + ${{ if ne(variables['System.TeamProject'], 'DevDiv') }}: + name: NetCore1ESPool-Internal + demands: ImageOverride -equals Build.Server.Amd64.VS2019 + steps: + - template: setup-maestro-vars.yml + parameters: + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToChannelIds: ${{ parameters.PromoteToChannelIds }} + + - task: PowerShell@2 + displayName: Publish Using Darc + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 + arguments: -BuildId $(BARBuildId) + -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} + -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -MaestroToken '$(MaestroApiAccessToken)' + -WaitPublishingFinish true + -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' + -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' \ No newline at end of file diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index 4a22b2e6f6de79..0c87f149a4ad77 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -2,77 +2,69 @@ parameters: BARBuildId: '' PromoteToChannelIds: '' -jobs: -- job: setupMaestroVars - displayName: Setup Maestro Vars - variables: - - template: common-variables.yml - pool: - vmImage: 'windows-2019' - steps: - - checkout: none - - - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: - - task: DownloadBuildArtifacts@0 - displayName: Download Release Configs - inputs: - buildType: current - artifactName: ReleaseConfigs - checkDownloadedFiles: true - - - task: PowerShell@2 - name: setReleaseVars - displayName: Set Release Configs Vars +steps: + - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: + - task: DownloadBuildArtifacts@0 + displayName: Download Release Configs inputs: - targetType: inline - script: | - try { - if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { - $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt + buildType: current + artifactName: ReleaseConfigs + checkDownloadedFiles: true - $BarId = $Content | Select -Index 0 - $Channels = $Content | Select -Index 1 - $IsStableBuild = $Content | Select -Index 2 + - task: PowerShell@2 + name: setReleaseVars + displayName: Set Release Configs Vars + inputs: + targetType: inline + pwsh: true + script: | + try { + if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { + $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt - $AzureDevOpsProject = $Env:System_TeamProject - $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId - $AzureDevOpsBuildId = $Env:Build_BuildId - } - else { - $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" + $BarId = $Content | Select -Index 0 + $Channels = $Content | Select -Index 1 + $IsStableBuild = $Content | Select -Index 2 - $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $apiHeaders.Add('Accept', 'application/json') - $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - - $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } - - $BarId = $Env:BARBuildId - $Channels = $Env:PromoteToMaestroChannels -split "," - $Channels = $Channels -join "][" - $Channels = "[$Channels]" + $AzureDevOpsProject = $Env:System_TeamProject + $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId + $AzureDevOpsBuildId = $Env:Build_BuildId + } + else { + $buildApiEndpoint = "${Env:MaestroApiEndPoint}/api/builds/${Env:BARBuildId}?api-version=${Env:MaestroApiVersion}" - $IsStableBuild = $buildInfo.stable - $AzureDevOpsProject = $buildInfo.azureDevOpsProject - $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId - $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId - } + $apiHeaders = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $apiHeaders.Add('Accept', 'application/json') + $apiHeaders.Add('Authorization',"Bearer ${Env:MAESTRO_API_TOKEN}") - Write-Host "##vso[task.setvariable variable=BARBuildId;isOutput=true]$BarId" - Write-Host "##vso[task.setvariable variable=TargetChannels;isOutput=true]$Channels" - Write-Host "##vso[task.setvariable variable=IsStableBuild;isOutput=true]$IsStableBuild" + $buildInfo = try { Invoke-WebRequest -Method Get -Uri $buildApiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + + $BarId = $Env:BARBuildId + $Channels = $Env:PromoteToMaestroChannels -split "," + $Channels = $Channels -join "][" + $Channels = "[$Channels]" - Write-Host "##vso[task.setvariable variable=AzDOProjectName;isOutput=true]$AzureDevOpsProject" - Write-Host "##vso[task.setvariable variable=AzDOPipelineId;isOutput=true]$AzureDevOpsBuildDefinitionId" - Write-Host "##vso[task.setvariable variable=AzDOBuildId;isOutput=true]$AzureDevOpsBuildId" + $IsStableBuild = $buildInfo.stable + $AzureDevOpsProject = $buildInfo.azureDevOpsProject + $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId + $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId } - catch { - Write-Host $_ - Write-Host $_.Exception - Write-Host $_.ScriptStackTrace - exit 1 - } - env: - MAESTRO_API_TOKEN: $(MaestroApiAccessToken) - BARBuildId: ${{ parameters.BARBuildId }} - PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} + + Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" + Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" + Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" + + Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" + Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" + Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" + } + catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + exit 1 + } + env: + MAESTRO_API_TOKEN: $(MaestroApiAccessToken) + BARBuildId: ${{ parameters.BARBuildId }} + PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} diff --git a/eng/common/templates/steps/execute-codeql.yml b/eng/common/templates/steps/execute-codeql.yml new file mode 100644 index 00000000000000..3930b1630214b3 --- /dev/null +++ b/eng/common/templates/steps/execute-codeql.yml @@ -0,0 +1,32 @@ +parameters: + # Language that should be analyzed. Defaults to csharp + language: csharp + # Build Commands + buildCommands: '' + overrideParameters: '' # Optional: to override values for parameters. + additionalParameters: '' # Optional: parameters that need user specific values eg: '-SourceToolsList @("abc","def") -ArtifactToolsList @("ghi","jkl")' + # Optional: if specified, restore and use this version of Guardian instead of the default. + overrideGuardianVersion: '' + # Optional: if true, publish the '.gdn' folder as a pipeline artifact. This can help with in-depth + # diagnosis of problems with specific tool configurations. + publishGuardianDirectoryToPipeline: false + # The script to run to execute all SDL tools. Use this if you want to use a script to define SDL + # parameters rather than relying on YAML. It may be better to use a local script, because you can + # reproduce results locally without piecing together a command based on the YAML. + executeAllSdlToolsScript: 'eng/common/sdl/execute-all-sdl-tools.ps1' + # There is some sort of bug (has been reported) in Azure DevOps where if this parameter is named + # 'continueOnError', the parameter value is not correctly picked up. + # This can also be remedied by the caller (post-build.yml) if it does not use a nested parameter + # optional: determines whether to continue the build if the step errors; + sdlContinueOnError: false + +steps: +- template: /eng/common/templates/steps/execute-sdl.yml + parameters: + overrideGuardianVersion: ${{ parameters.overrideGuardianVersion }} + executeAllSdlToolsScript: ${{ parameters.executeAllSdlToolsScript }} + overrideParameters: ${{ parameters.overrideParameters }} + additionalParameters: '${{ parameters.additionalParameters }} + -CodeQLAdditionalRunConfigParams @("BuildCommands < ${{ parameters.buildCommands }}", "Language < ${{ parameters.language }}")' + publishGuardianDirectoryToPipeline: ${{ parameters.publishGuardianDirectoryToPipeline }} + sdlContinueOnError: ${{ parameters.sdlContinueOnError }} \ No newline at end of file diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 5d526c74d518ce..f1e1cb53953bcc 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -298,31 +298,44 @@ function InstallDotNet([string] $dotnetRoot, if ($skipNonVersionedFiles) { $installParameters.SkipNonVersionedFiles = $skipNonVersionedFiles } if ($noPath) { $installParameters.NoPath = $True } - try { - & $installScript @installParameters - } - catch { - if ($runtimeSourceFeed -or $runtimeSourceFeedKey) { - Write-Host "Failed to install dotnet from public location. Trying from '$runtimeSourceFeed'" - if ($runtimeSourceFeed) { $installParameters.AzureFeed = $runtimeSourceFeed } + $variations = @() + $variations += @($installParameters) - if ($runtimeSourceFeedKey) { - $decodedBytes = [System.Convert]::FromBase64String($runtimeSourceFeedKey) - $decodedString = [System.Text.Encoding]::UTF8.GetString($decodedBytes) - $installParameters.FeedCredential = $decodedString - } + $dotnetBuilds = $installParameters.Clone() + $dotnetbuilds.AzureFeed = "https://dotnetbuilds.azureedge.net/public" + $variations += @($dotnetBuilds) - try { - & $installScript @installParameters - } - catch { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet from custom location '$runtimeSourceFeed'." - ExitWithExitCode 1 - } + if ($runtimeSourceFeed) { + $runtimeSource = $installParameters.Clone() + $runtimeSource.AzureFeed = $runtimeSourceFeed + if ($runtimeSourceFeedKey) { + $decodedBytes = [System.Convert]::FromBase64String($runtimeSourceFeedKey) + $decodedString = [System.Text.Encoding]::UTF8.GetString($decodedBytes) + $runtimeSource.FeedCredential = $decodedString + } + $variations += @($runtimeSource) + } + + $installSuccess = $false + foreach ($variation in $variations) { + if ($variation | Get-Member AzureFeed) { + $location = $variation.AzureFeed } else { - Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet from public location." - ExitWithExitCode 1 + $location = "public location"; + } + Write-Host "Attempting to install dotnet from $location." + try { + & $installScript @variation + $installSuccess = $true + break } + catch { + Write-Host "Failed to install dotnet from $location." + } + } + if (-not $installSuccess) { + Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet from any of the specified locations." + ExitWithExitCode 1 } } @@ -706,6 +719,8 @@ function MSBuild() { Write-PipelineSetVariable -Name 'NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS' -Value '20' } + Enable-Nuget-EnhancedRetry + $toolsetBuildProject = InitializeToolset $basePath = Split-Path -parent $toolsetBuildProject $possiblePaths = @( @@ -714,6 +729,8 @@ function MSBuild() { (Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll')), (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.ArcadeLogging.dll')), (Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.Arcade.Sdk.dll')) + (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.ArcadeLogging.dll')), + (Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.Arcade.Sdk.dll')) ) $selectedPath = $null foreach ($path in $possiblePaths) { @@ -750,6 +767,8 @@ function MSBuild-Core() { } } + Enable-Nuget-EnhancedRetry + $buildTool = InitializeBuildTool $cmdArgs = "$($buildTool.Command) /m /nologo /clp:Summary /v:$verbosity /nr:$nodeReuse /p:ContinuousIntegrationBuild=$ci" @@ -872,3 +891,18 @@ if (!$disableConfigureToolsetImport) { } } } + +# +# If $ci flag is set, turn on (and log that we did) special environment variables for improved Nuget client retry logic. +# +function Enable-Nuget-EnhancedRetry() { + if ($ci) { + Write-Host "Setting NUGET enhanced retry environment variables" + $env:NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY = 'true' + $env:NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT = 6 + $env:NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS = 1000 + Write-PipelineSetVariable -Name 'NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY' -Value 'true' + Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT' -Value '6' + Write-PipelineSetVariable -Name 'NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS' -Value '1000' + } +} diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 828119be411b3d..e555c34269f6e8 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -188,28 +188,29 @@ function InstallDotNet { GetDotNetInstallScript "$root" local install_script=$_GetDotNetInstallScript - local archArg='' + local installParameters=(--version $version --install-dir "$root") + if [[ -n "${3:-}" ]] && [ "$3" != 'unset' ]; then - archArg="--architecture $3" + installParameters+=(--architecture $3) fi - local runtimeArg='' if [[ -n "${4:-}" ]] && [ "$4" != 'sdk' ]; then - runtimeArg="--runtime $4" + installParameters+=(--runtime $4) fi - local skipNonVersionedFilesArg="" if [[ "$#" -ge "5" ]] && [[ "$5" != 'false' ]]; then - skipNonVersionedFilesArg="--skip-non-versioned-files" + installParameters+=(--skip-non-versioned-files) fi - bash "$install_script" --version $version --install-dir "$root" $archArg $runtimeArg $skipNonVersionedFilesArg || { - local exit_code=$? - echo "Failed to install dotnet SDK from public location (exit code '$exit_code')." - local runtimeSourceFeed='' - if [[ -n "${6:-}" ]]; then - runtimeSourceFeed="--azure-feed $6" - fi + local variations=() # list of variable names with parameter arrays in them + + local public_location=("${installParameters[@]}") + variations+=(public_location) - local runtimeSourceFeedKey='' + local dotnetbuilds=("${installParameters[@]}" --azure-feed "https://dotnetbuilds.azureedge.net/public") + variations+=(dotnetbuilds) + + if [[ -n "${6:-}" ]]; then + variations+=(private_feed) + local private_feed=("${installParameters[@]}" --azure-feed $6) if [[ -n "${7:-}" ]]; then # The 'base64' binary on alpine uses '-d' and doesn't support '--decode' # '-d'. To work around this, do a simple detection and switch the parameter @@ -219,22 +220,27 @@ function InstallDotNet { decodeArg="-d" fi decodedFeedKey=`echo $7 | base64 $decodeArg` - runtimeSourceFeedKey="--feed-credential $decodedFeedKey" + private_feed+=(--feed-credential $decodedFeedKey) fi + fi - if [[ -n "$runtimeSourceFeed" || -n "$runtimeSourceFeedKey" ]]; then - bash "$install_script" --version $version --install-dir "$root" $archArg $runtimeArg $skipNonVersionedFilesArg $runtimeSourceFeed $runtimeSourceFeedKey || { - local exit_code=$? - Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK from custom location '$runtimeSourceFeed' (exit code '$exit_code')." - ExitWithExitCode $exit_code - } - else - if [[ $exit_code != 0 ]]; then - Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK from public location (exit code '$exit_code')." - fi - ExitWithExitCode $exit_code + local installSuccess=0 + for variationName in "${variations[@]}"; do + local name="$variationName[@]" + local variation=("${!name}") + echo "Attempting to install dotnet from $variationName." + bash "$install_script" "${variation[@]}" && installSuccess=1 + if [[ "$installSuccess" -eq 1 ]]; then + break fi - } + + echo "Failed to install dotnet from $variationName." + done + + if [[ "$installSuccess" -eq 0 ]]; then + Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK from any of the specified locations." + ExitWithExitCode 1 + fi } function with_retries { @@ -410,6 +416,13 @@ function MSBuild { export NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS=20 Write-PipelineSetVariable -name "NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS" -value "20" Write-PipelineSetVariable -name "NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS" -value "20" + + export NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY=true + export NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT=6 + export NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS=1000 + Write-PipelineSetVariable -name "NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY" -value "true" + Write-PipelineSetVariable -name "NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT" -value "6" + Write-PipelineSetVariable -name "NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS" -value "1000" fi local toolset_dir="${_InitializeToolset%/*}" @@ -420,6 +433,8 @@ function MSBuild { possiblePaths+=( "$toolset_dir/$_InitializeBuildToolFramework/Microsoft.DotNet.Arcade.Sdk.dll" ) possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.ArcadeLogging.dll" ) possiblePaths+=( "$toolset_dir/netcoreapp2.1/Microsoft.DotNet.Arcade.Sdk.dll" ) + possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.ArcadeLogging.dll" ) + possiblePaths+=( "$toolset_dir/netcoreapp3.1/Microsoft.DotNet.Arcade.Sdk.dll" ) for path in "${possiblePaths[@]}"; do if [[ -f $path ]]; then selectedPath=$path diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index e07b5e0048cf14..9600e346b36133 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -27,7 +27,7 @@ isMSBuildOnNETCoreSupported() return fi - if [[ ( "$__HostOS" == "Linux" ) && ( "$__HostArch" == "x64" || "$__HostArch" == "arm" || "$__HostArch" == "armel" || "$__HostArch" == "arm64" ) ]]; then + if [[ ( "$__HostOS" == "Linux" ) && ( "$__HostArch" == "x64" || "$__HostArch" == "arm" || "$__HostArch" == "armel" || "$__HostArch" == "arm64" || "$__HostArch" == "s390x" ) ]]; then __IsMSBuildOnNETCoreSupported=1 elif [[ ( "$__HostOS" == "OSX" || "$__HostOS" == "FreeBSD" ) && "$__HostArch" == "x64" ]]; then __IsMSBuildOnNETCoreSupported=1 @@ -230,7 +230,7 @@ usage() echo "" echo "Common Options:" echo "" - echo "BuildArch can be: -arm, -armel, -arm64, x64, x86, -wasm" + echo "BuildArch can be: -arm, -armel, -arm64, -s390x, x64, x86, -wasm" echo "BuildType can be: -debug, -checked, -release" echo "-os: target OS (defaults to running OS)" echo "-bindir: output directory (defaults to $__ProjectRoot/artifacts)" diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 496384c35a70ea..c6f4a6a5627542 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -68,12 +68,14 @@ if (MSVC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /PDBCOMPRESS") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUGTYPE:CV,FIXUP") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4197,4013,4254,4070,4221") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /SUBSYSTEM:WINDOWS,${WINDOWS_SUBSYSTEM_VERSION}") set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /IGNORE:4221") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUGTYPE:CV,FIXUP") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /PDBCOMPRESS") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:1572864") @@ -338,15 +340,17 @@ if (CLR_CMAKE_HOST_UNIX) #These seem to indicate real issues add_compile_options($<$:-Wno-invalid-offsetof>) - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-unused-but-set-variable) + + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wno-unknown-warning-option) + # The -ferror-limit is helpful during the porting, it makes sure the compiler doesn't stop # after hitting just about 20 errors. add_compile_options(-ferror-limit=4096) # Disabled warnings add_compile_options(-Wno-unused-private-field) - # Explicit constructor calls are not supported by clang (this->ClassName::ClassName()) - add_compile_options(-Wno-microsoft) # There are constants of type BOOL used in a condition. But BOOL is defined as int # and so the compiler thinks that there is a mistake. add_compile_options(-Wno-constant-logical-operand) @@ -361,8 +365,9 @@ if (CLR_CMAKE_HOST_UNIX) # to a struct or a class that has virtual members or a base class. In that case, clang # may not generate the same object layout as MSVC. add_compile_options(-Wno-incompatible-ms-struct) + + add_compile_options(-Wno-reserved-identifier) else() - add_compile_options(-Wno-unused-but-set-variable) add_compile_options(-Wno-unknown-pragmas) add_compile_options(-Wno-uninitialized) add_compile_options(-Wno-strict-aliasing) @@ -415,7 +420,7 @@ if (CLR_CMAKE_HOST_UNIX) set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") add_compile_options(-arch arm64) elseif(CLR_CMAKE_HOST_ARCH_AMD64) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") add_compile_options(-arch x86_64) else() clr_unknown_arch() @@ -573,7 +578,7 @@ if (MSVC) set(CMAKE_ASM_MASM_FLAGS "${CMAKE_ASM_MASM_FLAGS} /guard:ehcont") add_linker_flag(/guard:ehcont) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /CETCOMPAT") - endif (CLR_CMAKE_HOST_ARCH_AMD64) + endif (CLR_CMAKE_HOST_ARCH_AMD64 AND NOT CLR_CMAKE_RUNTIME_MONO) # Statically linked CRT (libcmt[d].lib, libvcruntime[d].lib and libucrt[d].lib) by default. This is done to avoid # linking in VCRUNTIME140.DLL for a simplified xcopy experience by reducing the dependency on VC REDIST. diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index 5194317720045f..af1c88bce5b643 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -2,7 +2,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/functions.cmake) # If set, indicates that this is not an officially supported release # Keep in sync with IsPrerelease in Directory.Build.props -set(PRERELEASE 1) +set(PRERELEASE 0) #---------------------------------------- # Detect and set platform variable names diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index 0d03cc3d2d46eb..66a91ca0af81da 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -89,6 +89,10 @@ function(find_unwind_libs UnwindLibs) find_library(UNWIND_ARCH NAMES unwind-x86_64) endif() + if(CLR_CMAKE_HOST_ARCH_S390X) + find_library(UNWIND_ARCH NAMES unwind-s390x) + endif() + if(NOT UNWIND_ARCH STREQUAL UNWIND_ARCH-NOTFOUND) set(UNWIND_LIBS ${UNWIND_ARCH}) endif() diff --git a/eng/packaging.targets b/eng/packaging.targets index f450f05adc55c9..32b96187eed747 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -1,18 +1,24 @@ - true + + true true - $([MSBuild]::Subtract($(MajorVersion), 1)).0.0 + 6.0.0 + BeforePack must be used. Setting both to ensure that we are always running before other targets. --> AddNETStandardCompatErrorFileForPackaging;IncludeAnalyzersInPackage;$(PackDependsOn) AddNETStandardCompatErrorFileForPackaging;IncludeAnalyzersInPackage;$(BeforePack) $(PackageOutputPath) $(TargetsForTfmSpecificContentInPackage);AddRuntimeSpecificFilesToPackage;IncludePrivateProjectReferencesWithPackAttributeInPackage $(TargetsForTfmSpecificDebugSymbolsInPackage);AddRuntimeSpecificSymbolToPackage - false + false true $(MSBuildThisFileDirectory)useSharedDesignerContext.txt @@ -24,23 +30,37 @@ '$(IsRIDSpecificProject)' == 'true') and '$(PreReleaseVersionLabel)' != 'servicing' and '$(GitHubRepositoryName)' != 'runtimelab'">true + false + + true $(XmlDocFileRoot)1033\$(AssemblyName).xml true - + + + 0 + - $(MajorVersion).$(MinorVersion).$(ServicingVersion) + $(MajorVersion).$(MinorVersion).$(ServicingVersion) + $(Version)-$(VersionSuffix) <_IsWindowsDesktopApp Condition="$(WindowsDesktopCoreAppLibrary.Contains('$(AssemblyName);'))">true <_IsAspNetCoreApp Condition="$(AspNetCoreAppLibrary.Contains('$(AssemblyName);'))">true - <_AssemblyInTargetingPack Condition="'$(IsNETCoreAppSrc)' == 'true' or '$(_IsAspNetCoreApp)' == 'true' or '$(_IsWindowsDesktopApp)' == 'true'">true + <_AssemblyInTargetingPack Condition="('$(IsNETCoreAppSrc)' == 'true' or '$(IsNetCoreAppRef)' == 'true' or '$(_IsAspNetCoreApp)' == 'true' or '$(_IsWindowsDesktopApp)' == 'true') and '$(TargetFrameworkIdentifier)' != '.NETFramework'">true - $(MajorVersion).$(MinorVersion).0.$(ServicingVersion) + $(MajorVersion).$(MinorVersion).0.$(ServicingVersion) - + @@ -150,6 +170,41 @@ + + <_MultiTargetRoslynComponentTargetsTemplate>$(MSBuildThisFileDirectory)MultiTargetRoslynComponent.targets.template + $(IntermediateOutputPath)MultiTargetRoslynComponent.targets + true + + + + + + + + + + + + <_MultiTargetRoslynComponentTargetPrefix>$(PackageId.Replace('.', '_')) + <_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName>Disable$(PackageId.Replace('.', ''))SourceGenerator + <_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName>$(_MultiTargetRoslynComponentDisableSourceGeneratorPropertyName.Replace('Abstractions', '')) + + + + + @@ -221,4 +276,16 @@ + + + + + + + + diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 84f1786bd2171d..7db10e91e68b3c 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -119,6 +119,13 @@ jobs: inputs: artifact: Mono_Offsets_${{monoCrossAOTTargetOS}} path: '$(Build.SourcesDirectory)/artifacts/obj/mono/offsetfiles' + + - ${{ if eq(parameters.buildingOnSourceBuildImage, true) }}: + - template: /eng/common/templates/steps/source-build.yml + parameters: + platform: + buildScript: $(_sclEnableCommand) $(Build.SourcesDirectory)$(dir)build$(scriptExt) + nonPortable: true - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS', 'MacCatalyst') }}: - script: $(Build.SourcesDirectory)/eng/install-native-dependencies.sh ${{ parameters.osGroup }} ${{ parameters.archType }} azDO @@ -140,10 +147,11 @@ jobs: displayName: Install native dependencies # Build - - script: $(_sclEnableCommand) $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) ${{ parameters.buildArgs }} $(_officialBuildParameter) $(_crossBuildPropertyArg) $(_cxx11Parameter) $(_richCodeNavigationParam) $(_buildDarwinFrameworksParameter) - displayName: Build product - ${{ if eq(parameters.useContinueOnErrorDuringBuild, true) }}: - continueOnError: ${{ parameters.shouldContinueOnError }} + - ${{ if eq(parameters.buildingOnSourceBuildImage, false) }}: + - script: $(_sclEnableCommand) $(Build.SourcesDirectory)$(dir)build$(scriptExt) -ci -arch ${{ parameters.archType }} $(_osParameter) ${{ parameters.buildArgs }} $(_officialBuildParameter) $(_crossBuildPropertyArg) $(_cxx11Parameter) $(_richCodeNavigationParam) $(_buildDarwinFrameworksParameter) + displayName: Build product + ${{ if eq(parameters.useContinueOnErrorDuringBuild, true) }}: + continueOnError: ${{ parameters.shouldContinueOnError }} - ${{ if in(parameters.osGroup, 'OSX', 'iOS', 'tvOS', 'Android') }}: - script: | diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 15fe948e92967e..fbc12a81b5abc6 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -91,7 +91,7 @@ jobs: targetRid: linux-musl-x64 platform: Linux_musl_x64 container: - image: alpine-3.9-WithNode-20210714125437-9b5bbc2 + image: alpine-3.13-WithNode-20210910135845-c401c85 registry: mcr jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} @@ -205,6 +205,32 @@ jobs: ${{ insert }}: ${{ parameters.jobParameters }} buildingOnSourceBuildImage: true +# Linux s390x + +- ${{ if containsValue(parameters.platforms, 'Linux_s390x') }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: Linux + archType: s390x + targetRid: linux-s390x + platform: Linux_s390x + container: + image: ubuntu-18.04-cross-s390x-20201102145728-d6e0352 + registry: mcr + jobParameters: + runtimeFlavor: ${{ parameters.runtimeFlavor }} + stagedBuild: ${{ parameters.stagedBuild }} + buildConfig: ${{ parameters.buildConfig }} + ${{ if eq(parameters.passPlatforms, true) }}: + platforms: ${{ parameters.platforms }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + crossBuild: true + crossrootfsDir: '/crossrootfs/s390x' + ${{ insert }}: ${{ parameters.jobParameters }} + # WebAssembly - ${{ if containsValue(parameters.platforms, 'Browser_wasm') }}: diff --git a/eng/pipelines/common/variables.yml b/eng/pipelines/common/variables.yml index 760543475a7519..e2ed01f836cf55 100644 --- a/eng/pipelines/common/variables.yml +++ b/eng/pipelines/common/variables.yml @@ -1,12 +1,23 @@ variables: + +# These values enable longer delays, configurable number of retries, and special understanding of TCP hang-up +# See https://github.com/NuGet/Home/issues/11027 for details +- name: NUGET_ENABLE_EXPERIMENTAL_HTTP_RETRY + value: true +- name: NUGET_EXPERIMENTAL_MAX_NETWORK_TRY_COUNT + value: 6 +- name: NUGET_EXPERIMENTAL_NETWORK_RETRY_DELAY_MILLISECONDS + value: 1000 + - name: isOfficialBuild value: ${{ and(ne(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }} - name: isFullMatrix value: ${{ and(eq(variables['System.TeamProject'], 'public'), ne(variables['Build.Reason'], 'PullRequest')) }} -# We only run evaluate paths on runtime and runtime-staging pipelines on PRs +# We only run evaluate paths on runtime, runtime-staging and runtime-community pipelines on PRs +# keep in sync with /eng/pipelines/common/xplat-setup.yml - name: dependOnEvaluatePaths - value: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging')) }} + value: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community')) }} - name: debugOnPrReleaseOnRolling ${{ if ne(variables['Build.Reason'], 'PullRequest') }}: value: Release diff --git a/eng/pipelines/common/xplat-setup.yml b/eng/pipelines/common/xplat-setup.yml index 74441b1168913b..9c9861e3a963f1 100644 --- a/eng/pipelines/common/xplat-setup.yml +++ b/eng/pipelines/common/xplat-setup.yml @@ -22,7 +22,7 @@ jobs: shouldContinueOnError: ${{ and(endsWith(variables['Build.DefinitionName'], 'staging'), eq(variables['Build.Reason'], 'PullRequest')) }} # keep in sync with /eng/pipelines/common/variables.yml - dependOnEvaluatePaths: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging')) }} + dependOnEvaluatePaths: ${{ and(eq(variables['Build.Reason'], 'PullRequest'), in(variables['Build.DefinitionName'], 'runtime', 'runtime-staging', 'runtime-community')) }} variables: # Disable component governance in our CI builds. These builds are not shipping nor @@ -111,13 +111,13 @@ jobs: pool: # Public Linux Build Pool ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Android'), eq(parameters.hostedOs, 'Linux')), eq(variables['System.TeamProject'], 'public')) }}: - name: NetCorePublic-Pool - queue: BuildPool.Ubuntu.1804.Amd64.Open + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open # Official Build Linux Pool ${{ if and(or(in(parameters.osGroup, 'Linux', 'FreeBSD', 'Browser', 'Android'), eq(parameters.hostedOs, 'Linux')), ne(variables['System.TeamProject'], 'public')) }}: - name: NetCoreInternal-Pool - queue: BuildPool.Ubuntu.1804.Amd64 + name: NetCore1ESPool-Svc-Internal + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64 # OSX Build Pool (we don't have on-prem OSX BuildPool ${{ if in(parameters.osGroup, 'OSX', 'MacCatalyst', 'iOS', 'iOSSimulator', 'tvOS', 'tvOSSimulator') }}: @@ -125,13 +125,13 @@ jobs: # Official Build Windows Pool ${{ if and(eq(parameters.osGroup, 'windows'), ne(variables['System.TeamProject'], 'public')) }}: - name: NetCoreInternal-Pool - queue: BuildPool.Windows.10.Amd64.VS2019 + name: NetCore1ESPool-Svc-Internal + demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019 # Public Windows Build Pool ${{ if and(or(eq(parameters.osGroup, 'windows'), eq(parameters.hostedOs, 'windows')), eq(variables['System.TeamProject'], 'public')) }}: - name: NetCorePublic-Pool - queue: BuildPool.Windows.10.Amd64.VS2019.Open + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019.Open ${{ if eq(parameters.helixQueuesTemplate, '') }}: diff --git a/eng/pipelines/coreclr/ci.yml b/eng/pipelines/coreclr/ci.yml index c4cbf06a14bde6..282d83d4030e54 100644 --- a/eng/pipelines/coreclr/ci.yml +++ b/eng/pipelines/coreclr/ci.yml @@ -150,13 +150,3 @@ jobs: crossgen2: true displayNameArgs: R2R_CG2 liveLibrariesBuildConfig: Release - -# -# Formatting -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/coreclr/templates/format-job.yml - platforms: - - Linux_x64 - - windows_x64 diff --git a/eng/pipelines/coreclr/perf.yml b/eng/pipelines/coreclr/perf.yml index 5726e5ac7c0de6..e073ca745eda08 100644 --- a/eng/pipelines/coreclr/perf.yml +++ b/eng/pipelines/coreclr/perf.yml @@ -3,7 +3,7 @@ trigger: branches: include: - main - - release/* + - release/6.0 paths: include: - '*' diff --git a/eng/pipelines/coreclr/perf_slow.yml b/eng/pipelines/coreclr/perf_slow.yml index 1ad80465846984..eae5255cfed4a3 100644 --- a/eng/pipelines/coreclr/perf_slow.yml +++ b/eng/pipelines/coreclr/perf_slow.yml @@ -1,23 +1,4 @@ -trigger: - batch: true - branches: - include: - - main - - release/* - paths: - include: - - '*' - - src/libraries/System.Private.CoreLib/* - exclude: - - .github/* - - docs/* - - CODE-OF-CONDUCT.md - - CONTRIBUTING.md - - LICENSE.TXT - - PATENTS.TXT - - README.md - - SECURITY.md - - THIRD-PARTY-NOTICES.TXT +trigger: none variables: - template: /eng/pipelines/common/variables.yml @@ -195,5 +176,37 @@ jobs: projectFile: microbenchmarks.proj runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml - logicalmachine: 'perfsurf' + logicalmachine: 'perfsurf' + +# Uncomment once we fix https://github.com/dotnet/performance/issues/1950 +# # run coreclr linux crossgen perf job +# - template: /eng/pipelines/common/platform-matrix.yml +# parameters: +# jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml +# buildConfig: release +# runtimeFlavor: coreclr +# platforms: +# - Linux_arm64 +# jobParameters: +# testGroup: perf +# liveLibrariesBuildConfig: Release +# projectFile: crossgen_perf.proj +# runKind: crossgen_scenarios +# runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml +# logicalmachine: 'perfa64' +# # run coreclr windows crossgen perf job +# - template: /eng/pipelines/common/platform-matrix.yml +# parameters: +# jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml +# buildConfig: release +# runtimeFlavor: coreclr +# platforms: +# - windows_arm64 +# jobParameters: +# testGroup: perf +# liveLibrariesBuildConfig: Release +# projectFile: crossgen_perf.proj +# runKind: crossgen_scenarios +# runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml +# logicalmachine: 'perfsurf' \ No newline at end of file diff --git a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml index 65b6226093a10f..3d5d83b6dadc88 100644 --- a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml +++ b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml @@ -24,7 +24,7 @@ steps: workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/Android displayName: Build HelloAndroid sample app - ${{ if eq(parameters.osGroup, 'iOS') }}: - - script: make build-appbundle TARGET=iOS MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=False + - script: make build-appbundle TARGET=iOS MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false env: DevTeamProvisioning: '-' workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS @@ -47,7 +47,7 @@ steps: - script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS displayName: Clean bindir - - script: make build-appbundle TARGET=iOS MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=True + - script: make build-appbundle TARGET=iOS MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false env: DevTeamProvisioning: '-' workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml index 2b3a80ce94349c..be38b2b327da18 100644 --- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml +++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml @@ -36,7 +36,7 @@ jobs: # Android x64 - ${{ if in(parameters.platform, 'Android_x64') }}: - - Ubuntu.1804.Amd64.Android.Open + - Ubuntu.1804.Amd64.Android.29.Open # Browser wasm - ${{ if eq(parameters.platform, 'Browser_wasm') }}: @@ -47,7 +47,8 @@ jobs: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - (Ubuntu.1804.Arm32.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Debian.9.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm32v7-bfcd90a-20200121150037 + - (Debian.10.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 + - (Debian.11.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 - (Ubuntu.1804.Arm32)Ubuntu.1804.Armarch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm32v7-bfcd90a-20200121150440 # Linux arm64 @@ -55,45 +56,47 @@ jobs: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - (Ubuntu.1804.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652 - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - (Debian.9.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm64v8-bfcd90a-20200121150055 + - (Debian.10.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20210304164340-56c6673 + - (Debian.11.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20210304164340-5a7c380 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Debian.9.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm64v8-bfcd90a-20200121150055 + - (Debian.10.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20210304164340-56c6673 + - (Debian.11.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20210304164340-5a7c380 - (Ubuntu.1804.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20210531091519-97d8652 # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.312.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-20200602002622-e06dc59 + - (Alpine.314.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.312.Amd64)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-20200602002622-e06dc59 + - (Alpine.314.Amd64)ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 # Linux musl arm32 - ${{ if eq(parameters.platform, 'Linux_musl_arm') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.313.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm32v7-20210414141857-1ea6b0a + - (Alpine.314.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20210910135806-8a6f4f3 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.313.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm32v7-20210414141857-1ea6b0a + - (Alpine.314.Arm32)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm32v7-20210910135806-8a6f4f3 # Linux musl arm64 - ${{ if eq(parameters.platform, 'Linux_musl_arm64') }}: - ${{ if eq(variables['System.TeamProject'], 'public') }}: - - (Alpine.312.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-arm64v8-20200602002604-25f8a3e + - (Alpine.314.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - (Alpine.312.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-arm64v8-20200602002604-25f8a3e + - (Alpine.314.Arm64)Ubuntu.1804.ArmArch@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 # Linux x64 - ${{ if eq(parameters.platform, 'Linux_x64') }}: - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - Ubuntu.1804.Amd64.Open - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - Debian.9.Amd64.Open - - Ubuntu.1604.Amd64.Open + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20210304164428-5a7c380 - Ubuntu.1804.Amd64.Open - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - RedHat.7.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - Debian.9.Amd64 - - Ubuntu.1604.Amd64 + - (Debian.10.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + - (Debian.11.Amd64)Ubuntu.1804.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20210304164428-5a7c380 - Ubuntu.1804.Amd64 - (Centos.8.Amd64)Ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - (Fedora.34.Amd64)Ubuntu.1604.amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210728124700-4f64125 @@ -108,14 +111,9 @@ jobs: # OSX x64 - ${{ if eq(parameters.platform, 'OSX_x64') }}: - - ${{ if and(eq(variables['System.TeamProject'], 'public'), in(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - OSX.1013.Amd64.Open - - ${{ if and(eq(variables['System.TeamProject'], 'public'), notIn(parameters.jobParameters.helixQueueGroup, 'pr', 'ci', 'libraries')) }}: - - OSX.1013.Amd64.Open - - OSX.1014.Amd64.Open + - ${{ if eq(variables['System.TeamProject'], 'public') }}: + - OSX.1015.Amd64.Open - ${{ if eq(variables['System.TeamProject'], 'internal') }}: - - OSX.1013.Amd64 - - OSX.1014.Amd64 - OSX.1015.Amd64 # windows x64 diff --git a/eng/pipelines/coreclr/templates/run-performance-job.yml b/eng/pipelines/coreclr/templates/run-performance-job.yml index de523bb2d99e61..596339fc05c182 100644 --- a/eng/pipelines/coreclr/templates/run-performance-job.yml +++ b/eng/pipelines/coreclr/templates/run-performance-job.yml @@ -23,7 +23,7 @@ parameters: runKind: '' # required -- test category logicalMachine: '' # required -- Used to specify a which pool of machines the test should run against javascriptEngine: 'NoJS' - + jobs: - template: xplat-pipeline-job.yml parameters: @@ -36,7 +36,7 @@ jobs: enableTelemetry: ${{ parameters.enableTelemetry }} enablePublishBuildArtifacts: true continueOnError: ${{ parameters.continueOnError }} - + ${{ if ne(parameters.displayName, '') }}: displayName: '${{ parameters.displayName }}' ${{ if eq(parameters.displayName, '') }}: @@ -55,9 +55,9 @@ jobs: - IsInternal: '' - HelixApiAccessToken: '' - - HelixPreCommandStemWindows: 'py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' - - HelixPreCommandStemLinux: 'python3 -m pip install -U pip;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.0.0;pip3 install azure.storage.queue==12.0.0;sudo apt-get update;sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates;curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -;sudo apt-get -y install nodejs;sudo apt-get -y install npm;npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g;$HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - - HelixPreCommandStemMsul: 'sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib;sudo apk add cargo --repository http://dl-cdn.alpinelinux.org/alpine/v3.12/community ;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - HelixPreCommandStemWindows: 'set ORIGPYPATH=%PYTHONPATH%;py -m pip install -U pip;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install azure.storage.blob==12.0.0;py -3 -m pip install azure.storage.queue==12.0.0;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - HelixPreCommandStemLinux: 'export ORIGPYPATH=$PYTHONPATH;python3 -m pip install -U pip;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.0.0;pip3 install azure.storage.queue==12.0.0;sudo apt-get update;sudo apt -y install curl dirmngr apt-transport-https lsb-release ca-certificates;curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -;sudo apt-get -y install nodejs;sudo apt-get -y install npm;npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g;$HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - HelixPreCommandStemMusl: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add icu-libs krb5-libs libgcc libintl libssl1.1 libstdc++ zlib cargo;sudo apk add libgdiplus --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing; python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install azure.storage.blob==12.7.1;pip3 install azure.storage.queue==12.1.5;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' - ExtraMSBuildLogsWindows: 'set MSBUILDDEBUGCOMM=1;set "MSBUILDDEBUGPATH=%HELIX_WORKITEM_UPLOAD_ROOT%"' - ExtraMSBuildLogsLinux: 'export MSBUILDDEBUGCOMM=1;export "MSBUILDDEBUGPATH=$HELIX_WORKITEM_UPLOAD_ROOT"' - HelixPreCommand: '' @@ -66,13 +66,16 @@ jobs: - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - ${{ if eq( parameters.osGroup, 'windows') }}: - HelixPreCommand: $(HelixPreCommandStemWindows);$(ExtraMSBuildLogsWindows) + - HelixPostCommand: 'set PYTHONPATH=%ORIGPYPATH%' - IsInternal: -Internal - ${{ if ne(parameters.osGroup, 'windows') }}: - ${{ if eq(parameters.osSubGroup, '_musl') }}: - - HelixPreCommand: $(HelixPreCommandStemMsul);$(ExtraMSBuildLogsLinux) + - HelixPreCommand: $(HelixPreCommandStemMusl);$(ExtraMSBuildLogsLinux) + - HelixPostCommand: 'export PYTHONPATH=$ORIGPYPATH' - IsInternal: --internal - ${{ if ne(parameters.osSubGroup, '_musl') }}: - HelixPreCommand: $(HelixPreCommandStemLinux);$(ExtraMSBuildLogsLinux) + - HelixPostCommand: 'export PYTHONPATH=$ORIGPYPATH' - IsInternal: --internal - group: DotNet-HelixApi-Access - group: dotnet-benchview @@ -82,7 +85,7 @@ jobs: - HelixPreCommand: $(ExtraMSBuildLogsWindows) - ${{ if ne(parameters.osGroup, 'windows') }}: - HelixPreCommand: $(ExtraMSBuildLogsLinux);npm install --prefix $HELIX_WORKITEM_PAYLOAD jsvu -g;$HELIX_WORKITEM_PAYLOAD/bin/jsvu --os=linux64 --engines=v8,javascriptcore - + - ${{ if and(eq(parameters.codeGenType, 'Interpreter'), eq(parameters.runtimeType, 'mono')) }}: - ${{ if eq( parameters.osGroup, 'windows') }}: @@ -132,6 +135,7 @@ jobs: HelixAccessToken: $(HelixApiAccessToken) HelixTargetQueues: $(Queue) HelixPreCommands: $(HelixPreCommand) + HelixPostCommands: $(HelixPostCommand) Creator: $(Creator) WorkItemTimeout: 4:00 # 4 hours WorkItemDirectory: '$(WorkItemDirectory)' # WorkItemDirectory can not be empty, so we send it some docs to keep it happy diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index 2fa6822205aa00..50db53d0295b61 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -63,13 +63,16 @@ jobs: # extra private job settings - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - ${{ if eq(parameters.osGroup, 'windows') }}: - - AdditionalHelixPreCommands: 'py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install --user azure.storage.blob==12.0.0 --force-reinstall;py -3 -m pip install --user azure.storage.queue==12.0.0 --force-reinstall;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - AdditionalHelixPreCommands: 'set ORIGPYPATH=%PYTHONPATH%;py -3 -m venv %HELIX_WORKITEM_PAYLOAD%\.venv;call %HELIX_WORKITEM_PAYLOAD%\.venv\Scripts\activate.bat;set PYTHONPATH=;py -3 -m pip install -U pip;py -3 -m pip install --user azure.storage.blob==12.0.0 --force-reinstall;py -3 -m pip install --user azure.storage.queue==12.0.0 --force-reinstall;set "PERFLAB_UPLOAD_TOKEN=$(PerfCommandUploadToken)"' + - AdditionalHelixPostCommands: 'set PYTHONPATH=%ORIGPYPATH%' - IsInternal: -Internal - ${{ if and(ne(parameters.osGroup, 'windows'), ne(parameters.osSubGroup, '_musl')) }}: - - AdditionalHelixPreCommands: 'sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - AdditionalHelixPreCommands: 'export ORIGPYPATH=$PYTHONPATH;sudo apt-get -y install python3-venv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - AdditionalHelixPostCommands: 'export PYTHONPATH=$ORIGPYPATH' - IsInternal: --internal - ${{ if and(ne(parameters.osGroup, 'windows'), eq(parameters.osSubGroup, '_musl')) }}: - - AdditionalHelixPreCommands: 'sudo apk add py3-virtualenv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/Scripts/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - AdditionalHelixPreCommands: 'export ORIGPYPATH=$PYTHONPATH;sudo apk add py3-virtualenv;python3 -m venv $HELIX_WORKITEM_PAYLOAD/.venv;source $HELIX_WORKITEM_PAYLOAD/.venv/bin/activate;export PYTHONPATH=;python3 -m pip install -U pip;pip3 install --user azure.storage.blob==12.0.0 --force-reinstall;pip3 install --user azure.storage.queue==12.0.0 --force-reinstall;export PERFLAB_UPLOAD_TOKEN="$(PerfCommandUploadTokenLinux)"' + - AdditionalHelixPostCommands: 'export PYTHONPATH=$ORIGPYPATH' - IsInternal: --internal - group: DotNet-HelixApi-Access - group: dotnet-benchview @@ -145,6 +148,7 @@ jobs: HelixAccessToken: $(HelixApiAccessToken) HelixTargetQueues: $(Queue) HelixPreCommands: '$(AdditionalHelixPreCommands);$(SharedHelixPreCommands)' # $(HelixPreCommands) should follow $(AdditionalHelixPreCommands) because PYTHONPATH is cleared by the former + HelixPostCommands: $(AdditionalHelixPostCommands) Creator: $(Creator) WorkItemTimeout: 4:00 # 4 hours WorkItemDirectory: '$(WorkItemDirectory)' # contains scenario tools, shared python scripts, dotnet tool diff --git a/eng/pipelines/global-build.yml b/eng/pipelines/global-build.yml index 289f7d0033e9c2..420ba301ad12ee 100644 --- a/eng/pipelines/global-build.yml +++ b/eng/pipelines/global-build.yml @@ -133,5 +133,4 @@ jobs: - SourceBuild_Linux_x64 jobParameters: nameSuffix: SourceBuild - buildArgs: -subset clr+libs+host+packs /p:DotNetBuildFromSource=true --portableBuild false timeoutInMinutes: 90 diff --git a/eng/pipelines/libraries/enterprise/linux.yml b/eng/pipelines/libraries/enterprise/linux.yml index 754b533564e3f4..904dc4c87c73cb 100644 --- a/eng/pipelines/libraries/enterprise/linux.yml +++ b/eng/pipelines/libraries/enterprise/linux.yml @@ -19,7 +19,8 @@ pr: - src/libraries/System.Net.Security/* pool: - vmImage: 'ubuntu-16.04' + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open variables: - template: ../variables.yml @@ -50,7 +51,7 @@ steps: displayName: Test linuxclient connection to web server - bash: | - docker exec linuxclient bash -c '/repo/build.sh -subset clr+libs -runtimeconfiguration release -ci' + docker exec linuxclient bash -c '/repo/build.sh -subset clr+libs -runtimeconfiguration release -ci /p:NoPgoOptimize=true' displayName: Build product sources - bash: | diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index b7690e833d2d25..adf90c06f55c9e 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -29,7 +29,8 @@ jobs: # Linux arm - ${{ if eq(parameters.platform, 'Linux_arm') }}: - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - (Debian.9.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-9-helix-arm32v7-bfcd90a-20200121150037 + - (Debian.10.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm32v7-20210304164340-6616c63 + - (Debian.11.Arm32.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm32v7-20210304164347-5a7c380 # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: @@ -40,15 +41,14 @@ jobs: # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: - - (Alpine.312.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-20200602002622-e06dc59 + - (Alpine.314.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-amd64-20210910135833-1848e19 - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - (Alpine.312.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-20200601195603-e06dc59 + - (Alpine.313.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-amd64-20210910135845-8a6f4f3 # Linux musl arm64 - - ${{ if eq(parameters.platform, 'Linux_musl_arm64') }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - (Alpine.312.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.12-helix-arm64v8-20200602002604-25f8a3e + - ${{ if and(eq(parameters.platform, 'Linux_musl_arm64'), eq(parameters.jobParameters.isFullMatrix, true)) }}: + - (Alpine.313.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.13-helix-arm64v8-20210910135808-8a6f4f3 + - (Alpine.314.Arm64.Open)ubuntu.1804.armarch.open@mcr.microsoft.com/dotnet-buildtools/prereqs:alpine-3.14-helix-arm64v8-20210910135810-8a6f4f3 # Linux x64 - ${{ if eq(parameters.platform, 'Linux_x64') }}: @@ -57,33 +57,34 @@ jobs: - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - RedHat.7.Amd64.Open - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210728124700-4f64125 + - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210913123654-4f64125 - (Ubuntu.1910.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-19.10-helix-amd64-cfcfd50-20191030180623 - (Debian.10.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-bfcd90a-20200121150006 - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: + - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 - RedHat.7.Amd64.Open - - Debian.9.Amd64.Open - - Ubuntu.1604.Amd64.Open - Ubuntu.1804.Amd64.Open - SLES.12.Amd64.Open - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210728124700-4f64125 + - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210913123654-4f64125 - (Ubuntu.1910.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-19.10-helix-amd64-cfcfd50-20191030180623 - - (Debian.10.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-bfcd90a-20200121150006 + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + - (Debian.11.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-amd64-20210304164428-5a7c380 - (Mariner.1.0.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-1.0-helix-20210528192219-92bf620 - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: - - (Centos.8.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-helix-20201229003624-c1bf759 + - (Centos.7.Amd64.Open)Ubuntu.1604.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-mlnet-helix-20210714125435-dde38af - RedHat.7.Amd64.Open - - (Debian.10.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-bfcd90a-20200121150006 - - Ubuntu.1604.Amd64.Open + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 - Ubuntu.1804.Amd64.Open - - SLES.15.Amd64.Open - - (Fedora.34.Amd64.Open)ubuntu.1604.amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-34-helix-20210728124700-4f64125 - ${{ if or(eq(parameters.jobParameters.interpreter, 'true'), eq(parameters.jobParameters.isSingleFile, true)) }}: # Limiting interp runs as we don't need as much coverage. - - Debian.9.Amd64.Open + - (Debian.10.Amd64.Open)Ubuntu.1804.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-amd64-20210304164434-56c6673 + + # Linux s390x + - ${{ if eq(parameters.platform, 'Linux_s390x') }}: + - Ubuntu.2004.S390X.Experimental.Open # OSX arm64 - ${{ if eq(parameters.platform, 'OSX_arm64') }}: @@ -91,17 +92,11 @@ jobs: # OSX x64 - ${{ if eq(parameters.platform, 'OSX_x64') }}: - - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - - OSX.1013.Amd64.Open - - OSX.1014.Amd64.Open - - OSX.1015.Amd64.Open - - ${{ if eq(parameters.jobParameters.isFullMatrix, false) }}: - - OSX.1014.Amd64.Open - OSX.1015.Amd64.Open # Android - ${{ if in(parameters.platform, 'Android_x86', 'Android_x64') }}: - - Ubuntu.1804.Amd64.Android.Open + - Ubuntu.1804.Amd64.Android.29.Open - ${{ if in(parameters.platform, 'Android_arm', 'Android_arm64') }}: - Windows.10.Amd64.Android.Open @@ -127,26 +122,27 @@ jobs: - ${{ if notIn(parameters.jobParameters.framework, 'net48') }}: - ${{ if and(eq(parameters.jobParameters.testScope, 'outerloop'), eq(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - Windows.81.Amd64.Open - - Windows.10.Amd64.Server19H1.Open + - Windows.Amd64.Server2022.Open - ${{ if or(ne(parameters.jobParameters.testScope, 'outerloop'), ne(parameters.jobParameters.runtimeFlavor, 'mono')) }}: - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - Windows.81.Amd64.Open - Windows.10.Amd64.ServerRS5.Open - - Windows.10.Amd64.Server19H1.Open + - Windows.Amd64.Server2022.Open - ${{ if ne(parameters.jobParameters.runtimeFlavor, 'mono') }}: - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 - - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c + - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20H2.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c - ${{ if ne(parameters.jobParameters.isFullMatrix, true) }}: - Windows.81.Amd64.Open - Windows.10.Amd64.Server19H1.ES.Open + - Windows.11.Amd64.ClientPre.Open - ${{ if eq(parameters.jobParameters.testScope, 'outerloop') }}: - - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c + - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20H2.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-amd64-20200904200251-272704c - ${{ if ne(parameters.jobParameters.runtimeFlavor, 'mono') }}: - (Windows.Nano.1809.Amd64.Open)windows.10.amd64.serverrs5.open@mcr.microsoft.com/dotnet-buildtools/prereqs:nanoserver-1809-helix-amd64-08e8e40-20200107182504 # .NETFramework - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: - - Windows.10.Amd64.Client19H1.Open + - Windows.10.Amd64.Client21H1.Open # windows x86 - ${{ if eq(parameters.platform, 'windows_x86') }}: @@ -159,17 +155,17 @@ jobs: - ${{ if eq(parameters.jobParameters.isFullMatrix, true) }}: - Windows.7.Amd64.Open - Windows.10.Amd64.ServerRS5.Open - - Windows.10.Amd64.Server19H1.Open + - Windows.10.Amd64.Server20H2.Open - ${{ if ne(parameters.jobParameters.isFullMatrix, true) }}: - ${{ if eq(parameters.jobParameters.buildConfig, 'Release') }}: - Windows.10.Amd64.Server19H1.ES.Open - ${{ if eq(parameters.jobParameters.buildConfig, 'Debug') }}: - Windows.7.Amd64.Open - - Windows.10.Amd64.Server19H1.Open + - Windows.10.Amd64.Server20H2.Open # .NETFramework - ${{ if eq(parameters.jobParameters.framework, 'net48') }}: - - Windows.10.Amd64.Client19H1.Open + - Windows.10.Amd64.Client21H1.Open # windows arm - ${{ if eq(parameters.platform, 'windows_arm') }}: @@ -185,6 +181,6 @@ jobs: # WebAssembly windows - ${{ if eq(parameters.platform, 'Browser_wasm_win') }}: - - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20h1.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-webassembly-amd64-20210702131541-6837048 + - (Windows.Server.Core.1909.Amd64.Open)windows.10.amd64.server20H2.open@mcr.microsoft.com/dotnet-buildtools/prereqs:windowsservercore-2004-helix-webassembly-amd64-20210702131541-6837048 ${{ insert }}: ${{ parameters.jobParameters }} diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index 3e9d2de85f49fb..48ead48d33a73d 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -55,11 +55,11 @@ jobs: testDisplayName: ${{ parameters.runtimeFlavor }}_interpreter_${{ parameters.liveRuntimeBuildConfig }} # To run the tests we just send to helix and wait, use ubuntu hosted pools for faster providing and to not back up our build pools - ${{ if startsWith(parameters.pool.queue, 'BuildPool.Ubuntu') }}: + ${{ if startsWith(parameters.pool.queue, 'Build.Ubuntu') }}: pool: vmImage: 'ubuntu-latest' - ${{ if not(startsWith(parameters.pool.queue, 'BuildPool.Ubuntu')) }}: + ${{ if not(startsWith(parameters.pool.queue, 'Build.Ubuntu')) }}: pool: ${{ parameters.pool }} dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }} diff --git a/eng/pipelines/libraries/stress/http.yml b/eng/pipelines/libraries/stress/http.yml index ba3a9f875f9e92..41a74be067832e 100644 --- a/eng/pipelines/libraries/stress/http.yml +++ b/eng/pipelines/libraries/stress/http.yml @@ -11,6 +11,7 @@ schedules: branches: include: - main + - release/6.0 variables: - template: ../variables.yml @@ -27,8 +28,8 @@ jobs: displayName: Docker Linux timeoutInMinutes: 180 pool: - name: NetCorePublic-Pool - queue: BuildPool.Ubuntu.1804.Amd64.Open + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open steps: - checkout: self @@ -75,8 +76,8 @@ jobs: displayName: Docker NanoServer timeoutInMinutes: 150 pool: - name: NetCorePublic-Pool - queue: BuildPool.Server.Amd64.VS2019.Open + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Server.Amd64.VS2019.Open steps: - checkout: self diff --git a/eng/pipelines/libraries/stress/ssl.yml b/eng/pipelines/libraries/stress/ssl.yml index b0a654ba4d9dc8..8462acd1292908 100644 --- a/eng/pipelines/libraries/stress/ssl.yml +++ b/eng/pipelines/libraries/stress/ssl.yml @@ -11,6 +11,7 @@ schedules: branches: include: - main + - release/6.0 variables: - template: ../variables.yml @@ -28,8 +29,8 @@ jobs: displayName: Docker Linux timeoutInMinutes: 120 pool: - name: NetCorePublic-Pool - queue: BuildPool.Ubuntu.1804.Amd64.Open + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Ubuntu.1804.Amd64.Open steps: - checkout: self @@ -53,8 +54,8 @@ jobs: displayName: Docker NanoServer timeoutInMinutes: 120 pool: - name: NetCorePublic-Pool - queue: BuildPool.Server.Amd64.VS2019.Open + name: NetCore1ESPool-Svc-Public + demands: ImageOverride -equals Build.Server.Amd64.VS2019.Open steps: - checkout: self diff --git a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml index a5457d751ad03f..5ecfe85f6e4705 100644 --- a/eng/pipelines/official/jobs/prepare-signed-artifacts.yml +++ b/eng/pipelines/official/jobs/prepare-signed-artifacts.yml @@ -9,8 +9,8 @@ jobs: displayName: Prepare Signed Artifacts dependsOn: ${{ parameters.dependsOn }} pool: - name: NetCoreInternal-Pool - queue: buildpool.windows.10.amd64.vs2019 + name: NetCore1ESPool-Svc-Internal + demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019 # Double the default timeout. timeoutInMinutes: 180 workspace: diff --git a/eng/pipelines/official/stages/publish.yml b/eng/pipelines/official/stages/publish.yml index 10c6297566ad5a..6ecc48c3835cf9 100644 --- a/eng/pipelines/official/stages/publish.yml +++ b/eng/pipelines/official/stages/publish.yml @@ -19,7 +19,8 @@ stages: publishUsingPipelines: true dependsOn: PrepareSignedArtifacts pool: - vmImage: vs2017-win2016 + name: NetCore1ESPool-Svc-Internal + demands: ImageOverride -equals Build.Windows.10.Amd64.VS2019 # Stages-based publishing entry point - template: /eng/common/templates/post-build/post-build.yml diff --git a/eng/pipelines/runtime-community.yml b/eng/pipelines/runtime-community.yml new file mode 100644 index 00000000000000..9ecb1f2677ae2d --- /dev/null +++ b/eng/pipelines/runtime-community.yml @@ -0,0 +1,60 @@ +trigger: none + +schedules: + - cron: "0 7,19 * * *" # run at 7:00 and 19:00 (UTC) which is 23:00 and 11:00 (PST). + displayName: Runtime-community default schedule + branches: + include: + - main + - release/*.* + always: false # run only if there were changes since the last successful scheduled run. + +variables: + - template: /eng/pipelines/common/variables.yml + +jobs: +# +# Evaluate paths +# +- ${{ if eq(variables.dependOnEvaluatePaths, true) }}: + - template: /eng/pipelines/common/evaluate-default-paths.yml + +# +# s390x +# Build the whole product using Mono and run libraries tests +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - Linux_s390x + variables: + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isFullMatrix'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isFullMatrix'], true)) diff --git a/eng/pipelines/runtime-official.yml b/eng/pipelines/runtime-official.yml index 5cb49dafbd9eea..217755efa13a7b 100644 --- a/eng/pipelines/runtime-official.yml +++ b/eng/pipelines/runtime-official.yml @@ -54,7 +54,10 @@ stages: # # Source Index Build # - - template: ./source-index.yml + - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: + - template: /eng/common/templates/job/source-index-stage1.yml + parameters: + sourceIndexBuildCommand: build.cmd -subset libs.ref+libs.src -binarylog -os Linux -ci # # Build CoreCLR @@ -318,6 +321,24 @@ stages: isOfficialAllConfigurations: true liveRuntimeBuildConfig: release + # + # Build Sourcebuild leg + # + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: Release + helixQueueGroup: ci + platforms: + - SourceBuild_Linux_x64 + jobParameters: + nameSuffix: SourceBuild + extraStepsTemplate: /eng/pipelines/common/upload-intermediate-artifacts-step.yml + extraStepsParameters: + name: SourceBuildPackages + timeoutInMinutes: 95 + + # # Installer Build # @@ -373,7 +394,7 @@ stages: - Linux_x64 # - # Build Blazor Workload + # Build Workloads # - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -383,6 +404,7 @@ stages: - windows_x64 jobParameters: isOfficialBuild: ${{ variables.isOfficialBuild }} + timeoutInMinutes: 120 dependsOn: - Build_Android_arm_release_AllSubsets_Mono - Build_Android_arm64_release_AllSubsets_Mono diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index 40ca5bf9b2fabe..2a1591a398201b 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -65,12 +65,10 @@ jobs: buildConfig: Release runtimeFlavor: mono platforms: - - MacCatalyst_x64 - iOSSimulator_x64 - tvOSSimulator_x64 # don't run tests on arm64 PRs until we can get significantly more devices - ${{ if eq(variables['isFullMatrix'], true) }}: - - MacCatalyst_arm64 - iOSSimulator_arm64 variables: # map dependencies variables to local variables @@ -101,6 +99,95 @@ jobs: eq(variables['monoContainsChange'], true), eq(variables['isFullMatrix'], true)) +# +# MacCatalyst interp - requires AOT Compilation and Interp flags +# Build the whole product using Mono and run libraries tests +# The test app is built with the App Sandbox entitlement +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - MacCatalyst_x64 + # don't run tests on arm64 PRs until we can get significantly more devices + - ${{ if eq(variables['isFullMatrix'], true) }}: + - MacCatalyst_arm64 + variables: + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono_AppSandbox + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true /p:EnableAppSandbox=true + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isFullMatrix'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + interpreter: true + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isFullMatrix'], true)) + +# +# MacCatalyst interp - requires AOT Compilation and Interp flags +# Build the whole product using Mono and run libraries tests +# +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml + buildConfig: Release + runtimeFlavor: mono + platforms: + - MacCatalyst_x64 + # don't run tests on arm64 PRs until we can get significantly more devices + - ${{ if eq(variables['isFullMatrix'], true) }}: + - MacCatalyst_arm64 + variables: + # map dependencies variables to local variables + - name: librariesContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ] + - name: monoContainsChange + value: $[ dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'] ] + jobParameters: + testGroup: innerloop + nameSuffix: AllSubsets_Mono + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=adhoc /p:RunAOTCompilation=true /p:MonoForceInterpreter=true /p:BuildDarwinFrameworks=true + timeoutInMinutes: 180 + condition: >- + or( + eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_mono.containsChange'], true), + eq(dependencies.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true), + eq(variables['isFullMatrix'], true)) + # extra steps, run tests + extraStepsTemplate: /eng/pipelines/libraries/helix.yml + extraStepsParameters: + creator: dotnet-bot + interpreter: true + testRunNamePrefixSuffix: Mono_$(_BuildConfig) + condition: >- + or( + eq(variables['librariesContainsChange'], true), + eq(variables['monoContainsChange'], true), + eq(variables['isFullMatrix'], true)) + # # Build the whole product using Mono and run libraries tests # diff --git a/eng/pipelines/source-index.yml b/eng/pipelines/source-index.yml deleted file mode 100644 index 201e84d4ef3295..00000000000000 --- a/eng/pipelines/source-index.yml +++ /dev/null @@ -1,10 +0,0 @@ -jobs: -# -# Source Index Build -# -- template: /eng/common/templates/job/source-index-stage1.yml - parameters: - sourceIndexBuildCommand: build.cmd -subset libs.ref+libs.src -binarylog -os Linux -ci - preSteps: - - script: | - rename dotnet.cmd dotnet.cmd.go-away diff --git a/eng/testing/AppleRunnerTemplate.sh b/eng/testing/AppleRunnerTemplate.sh index 47352018d1ac42..42f787af20d884 100644 --- a/eng/testing/AppleRunnerTemplate.sh +++ b/eng/testing/AppleRunnerTemplate.sh @@ -35,6 +35,8 @@ if [[ "$TARGET" == "ios-device" ]]; then SCHEME_SDK=Release-iphoneos; fi if [[ "$TARGET" == "tvos-device" ]]; then SCHEME_SDK=Release-appletvos; fi if [[ "$TARGET" == "maccatalyst" ]]; then SCHEME_SDK=Release-maccatalyst; fi +if [[ "$TARGET" == "ios-device" || "$TARGET" == "tvos-device" ]]; then SIGNAL_APP_END="--signal-app-end"; fi + cd $EXECUTION_DIR # it doesn't support parallel execution yet, so, here is a hand-made semaphore: @@ -62,6 +64,7 @@ $HARNESS_RUNNER apple $XHARNESS_CMD \ --targets="$TARGET" \ --xcode="$XCODE_PATH" \ --output-directory="$XHARNESS_OUT" \ + $SIGNAL_APP_END \ $ADDITIONAL_ARGS _exitCode=$? diff --git a/eng/testing/performance/crossgen_perf.proj b/eng/testing/performance/crossgen_perf.proj index c6599aecfd42f1..923882ea355873 100644 --- a/eng/testing/performance/crossgen_perf.proj +++ b/eng/testing/performance/crossgen_perf.proj @@ -59,7 +59,7 @@ - + $(WorkItemDirectory) $(Python) $(Crossgen2Directory)pre.py crossgen2 --core-root $(CoreRoot) --single %(Identity) $(Python) $(Crossgen2Directory)test.py sod --scenario-name "Crossgen2 %(Identity) Size" --dirs ./crossgen.out/ @@ -69,18 +69,18 @@ - + 4:00 - + 4:00 - + $(WorkItemDirectory) $(Python) $(Crossgen2Directory)test.py crossgen2 --core-root $(CoreRoot) --composite $(Crossgen2Directory)framework-r2r.dll.rsp 1:00 - + 4:00 diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1 index 9ed93d17fbd829..ae30e9bac80ead 100644 --- a/eng/testing/performance/performance-setup.ps1 +++ b/eng/testing/performance/performance-setup.ps1 @@ -97,7 +97,12 @@ if ($iOSMono) { } # FIX ME: This is a workaround until we get this from the actual pipeline -$CommonSetupArguments="--channel main --queue $Queue --build-number $BuildNumber --build-configs $Configurations --architecture $Architecture" +$CleanedBranchName = "main" +if($Branch.Contains("refs/heads/release")) +{ + $CleanedBranchName = $Branch.replace('refs/heads/', '') +} +$CommonSetupArguments="--channel $CleanedBranchName --queue $Queue --build-number $BuildNumber --build-configs $Configurations --architecture $Architecture" $SetupArguments = "--repository https://github.com/$Repository --branch $Branch --get-perf-hash --commit-sha $CommitSha $CommonSetupArguments" if($NoPGO) diff --git a/eng/testing/performance/performance-setup.sh b/eng/testing/performance/performance-setup.sh index c99ad1f48f3fa5..cffd9ca8d6cdb8 100755 --- a/eng/testing/performance/performance-setup.sh +++ b/eng/testing/performance/performance-setup.sh @@ -255,7 +255,11 @@ if [[ "$monoaot" == "true" ]]; then extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoAOT" fi -common_setup_arguments="--channel main --queue $queue --build-number $build_number --build-configs $configurations --architecture $architecture" +cleaned_branch_name="main" +if [[ $branch == *"refs/heads/release"* ]]; then + cleaned_branch_name=${branch/refs\/heads\//} +fi +common_setup_arguments="--channel $cleaned_branch_name --queue $queue --build-number $build_number --build-configs $configurations --architecture $architecture" setup_arguments="--repository https://github.com/$repository --branch $branch --get-perf-hash --commit-sha $commit_sha $common_setup_arguments" if [[ "$run_from_perf_repo" = true ]]; then diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index ba322274dfe62c..8afeea6cdeeb13 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -1,14 +1,19 @@ -BlazorWasmTests -FlagsChangeRebuildTest -InvariantGlobalizationTests -LocalEMSDKTests -MainWithArgsTests -NativeBuildTests -NativeLibraryTests -NoopNativeRebuildTest -RebuildTests -ReferenceNewAssemblyRebuildTest -SatelliteAssembliesTests -SimpleSourceChangeRebuildTest -WasmBuildAppTest -WorkloadTests +Wasm.Build.NativeRebuild.Tests.FlagsChangeRebuildTest +Wasm.Build.NativeRebuild.Tests.NoopNativeRebuildTest +Wasm.Build.NativeRebuild.Tests.ReferenceNewAssemblyRebuildTest +Wasm.Build.NativeRebuild.Tests.SimpleSourceChangeRebuildTest +Wasm.Build.Tests.BlazorWasmBuildPublishTests +Wasm.Build.Tests.BlazorWasmTests +Wasm.Build.Tests.BuildPublishTests +Wasm.Build.Tests.CleanTests +Wasm.Build.Tests.InvariantGlobalizationTests +Wasm.Build.Tests.LocalEMSDKTests +Wasm.Build.Tests.MainWithArgsTests +Wasm.Build.Tests.NativeBuildTests +Wasm.Build.Tests.NativeLibraryTests +Wasm.Build.Tests.PInvokeTableGeneratorTests +Wasm.Build.Tests.RebuildTests +Wasm.Build.Tests.SatelliteAssembliesTests +Wasm.Build.Tests.WasmBuildAppTest +Wasm.Build.Tests.WasmNativeDefaultsTests +Wasm.Build.Tests.WorkloadTests diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index fc196e0053efbf..f48c16f511fe5d 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -2,11 +2,15 @@ $([MSBuild]::NormalizeDirectory('$(OutDir)', 'AppBundle')) + $(AppBundleRoot)tests\$(AssemblyName) + $(AppBundleRoot)runonly\$(AssemblyName) + $([MSBuild]::NormalizeDirectory('$(PublishDir)', 'AppBundle')) $([MSBuild]::NormalizePath('$(BundleDir)', '$(RunScriptOutputName)')) true true BundleTestAppleApp;BundleTestAndroidApp + Publish @@ -104,6 +108,7 @@ OutputType="AsmOnly" Assemblies="@(AotInputAssemblies)" AotModulesTablePath="$(BundleDir)\modules.c" + IntermediateOutputPath="$(IntermediateOutputPath)" UseLLVM="$(MonoEnableLLVM)" LLVMPath="$(MonoAotCrossDir)"> @@ -155,6 +160,10 @@ true AppleTestRunner.dll <_MobileIntermediateOutputPath Condition="'$(RunAOTCompilation)' == 'true'">$(IntermediateOutputPath)mobile + true + false + false + true Full @@ -189,6 +198,7 @@ Assemblies="@(AotInputAssemblies)" AotModulesTablePath="$(BundleDir)\modules.m" AotModulesTableLanguage="ObjC" + IntermediateOutputPath="$(IntermediateOutputPath)" UseLLVM="$(MonoEnableLLVM)" LLVMPath="$(MonoAotCrossDir)"> @@ -209,10 +219,12 @@ MainLibraryFileName="$(MainLibraryFileName)" ForceAOT="$(RunAOTCompilation)" ForceInterpreter="$(MonoForceInterpreter)" + EnableAppSandbox="$(EnableAppSandbox)" InvariantGlobalization="$(InvariantGlobalization)" UseConsoleUITemplate="True" - GenerateXcodeProject="True" - BuildAppBundle="True" + GenerateXcodeProject="$(GenerateXcodeProject)" + GenerateCMakeProject="$(GenerateCMakeProject)" + BuildAppBundle="$(GenerateXcodeProject)" Optimized="$(Optimized)" DevTeamProvisioning="$(DevTeamProvisioning)" OutputDirectory="$(BundleDir)" @@ -220,25 +232,20 @@ - - + + - + <_appFiles Include="$(AppBundlePath)/../**/*" /> - - - - <_removeFiles Include="$(OutDir)*.*" /> - + Condition="'$(ArchiveTests)' == 'true' and '$(IgnoreForCI)' != 'true' and '$(GenerateXcodeProject)' == 'true'" /> - - + + true + true $(BundleTestAppTargets);BundleTestWasmApp true true + + false @@ -55,10 +59,20 @@ Condition="'$(BuildAOTTestsOn)' == 'local'" /> - PrepareForWasmBuildApp;$(WasmBuildAppDependsOn) + WasmTriggerPublishApp + $(BundleTestWasmAppDependsOn);_BundleAOTTestWasmAppForHelix + - WasmBuildApp - $(BundleTestWasmAppDependsOn);_BundleAOTTestWasmAppForHelix + + + + + + true + + + + PrepareForWasmBuildApp;$(WasmNestedPublishAppDependsOn) @@ -80,6 +94,8 @@ $([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json')) + + @@ -154,7 +170,7 @@ - + <_CopyLocalPaths diff --git a/eng/testing/xunit/xunit.targets b/eng/testing/xunit/xunit.targets index 8a950eb58ef383..8d4aa64986e4d5 100644 --- a/eng/testing/xunit/xunit.targets +++ b/eng/testing/xunit/xunit.targets @@ -1,9 +1,7 @@ - + diff --git a/global.json b/global.json index e3425ab9bdd9de..c80ef24ae46481 100644 --- a/global.json +++ b/global.json @@ -1,21 +1,21 @@ { "sdk": { - "version": "6.0.100-rc.1.21411.28", + "version": "6.0.101", "allowPrerelease": true, "rollForward": "major" }, "tools": { - "dotnet": "6.0.100-rc.1.21411.28" + "dotnet": "6.0.101" }, "native-tools": { "cmake": "3.16.4", "python3": "3.7.1" }, "msbuild-sdks": { - "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21413.4", - "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21413.4", - "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21413.4", - "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21413.4", + "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.22107.2", + "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.22107.2", + "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.22107.2", + "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.22107.2", "Microsoft.Build.NoTargets": "3.1.0", "Microsoft.Build.Traversal": "3.0.23", "Microsoft.NET.Sdk.IL": "6.0.0-rc.1.21415.6" diff --git a/src/coreclr/.nuget/Directory.Build.props b/src/coreclr/.nuget/Directory.Build.props index cff00f49e0e561..e9351e6c127a17 100644 --- a/src/coreclr/.nuget/Directory.Build.props +++ b/src/coreclr/.nuget/Directory.Build.props @@ -16,10 +16,10 @@ true + - - 6.0.0 - $(PackageVersion) + + false diff --git a/src/coreclr/.nuget/Directory.Build.targets b/src/coreclr/.nuget/Directory.Build.targets index 365d5ed7a9ca60..687a6f40253106 100644 --- a/src/coreclr/.nuget/Directory.Build.targets +++ b/src/coreclr/.nuget/Directory.Build.targets @@ -1,5 +1,13 @@ + + + + $(ProductVersion) + $(PackageVersion) + + + $(ProductVersion) + $(ProductVersion) true $(NoWarn),0419,0649,CA2249,CA1830 enable diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs index 948ebd2537230d..3cfc7cc193ec1f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using System.Reflection; +using System.Runtime.CompilerServices; namespace System.Diagnostics { @@ -50,5 +52,22 @@ private void BuildStackFrame(int skipFrames, bool needFileInfo) } private static bool AppendStackFrameWithoutMethodBase(StringBuilder sb) => false; + + /// + /// Returns the MethodBase instance for the managed code IP address. + /// + /// Warning: The implementation of this method has race for dynamic and collectible methods. + /// + /// code address + /// MethodBase instance for the method or null if IP not found + internal static MethodBase? GetMethodFromNativeIP(IntPtr ip) + { + RuntimeMethodHandleInternal method = StackTrace.GetMethodDescFromNativeIP(ip); + + if (method.Value == IntPtr.Zero) + return null; + + return RuntimeType.GetMethodBase(null, method); + } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs index 9bef9fb72fae58..d82bbaf7e1e342 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs @@ -1,8 +1,9 @@ // 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; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Diagnostics { @@ -11,6 +12,9 @@ public partial class StackTrace [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception? e); + [DllImport(RuntimeHelpers.QCall)] + internal static extern RuntimeMethodHandleInternal GetMethodDescFromNativeIP(IntPtr ip); + internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames) { int iRetVal = 0; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs index 6ea1f1b444a507..da3cd7f1059e27 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs @@ -34,7 +34,7 @@ internal static bool IsInterfaceImplemented(IDynamicInterfaceCastable castable, if (!implType.IsDefined(typeof(DynamicInterfaceCastableImplementationAttribute), inherit: false)) throw new InvalidOperationException(SR.Format(SR.IDynamicInterfaceCastable_MissingImplementationAttribute, implType, nameof(DynamicInterfaceCastableImplementationAttribute))); - if (!implType.ImplementInterface(interfaceType)) + if (!implType.IsAssignableTo(interfaceType)) throw new InvalidOperationException(SR.Format(SR.IDynamicInterfaceCastable_DoesNotImplementRequested, implType, interfaceType)); return implType; diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h index 0f17ce7290e71c..4bffe52ecb4f63 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/ToolBox/superpmi/superpmi-shared/lwmlist.h @@ -157,6 +157,7 @@ LWM(TryResolveToken, Agnostic_CORINFO_RESOLVED_TOKENin, TryResolveTokenValue) LWM(SatisfiesClassConstraints, DWORDLONG, DWORD) LWM(SatisfiesMethodConstraints, DLDL, DWORD) LWM(GetUnmanagedCallConv, MethodOrSigInfoValue, DD) +LWM(DoesFieldBelongToClass, DLDL, DWORD) DENSELWM(SigInstHandleMap, DWORDLONG) #undef LWM diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index ae87cb1edde826..7d4a191c51cf62 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -6265,6 +6265,40 @@ DWORD MethodContext::repGetExpectedTargetArchitecture() return value; } +void MethodContext::recDoesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls, bool result) +{ + if (DoesFieldBelongToClass == nullptr) + DoesFieldBelongToClass = new LightWeightMap(); + + DLDL key; + ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding + key.A = CastHandle(fld); + key.B = CastHandle(cls); + + DWORD value = (DWORD)result; + DoesFieldBelongToClass->Add(key, value); + DEBUG_REC(dmpDoesFieldBelongToClass(key, result)); +} + +void MethodContext::dmpDoesFieldBelongToClass(DLDL key, bool value) +{ + printf("DoesFieldBelongToClass key fld=%016llX, cls=%016llx, result=%d", key.A, key.B, value); +} + +bool MethodContext::repDoesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls) +{ + DLDL key; + ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding + key.A = CastHandle(fld); + key.B = CastHandle(cls); + + AssertMapAndKeyExist(DoesFieldBelongToClass, key, ": key %016llX %016llX", key.A, key.B); + + bool value = (bool)DoesFieldBelongToClass->Get(key); + DEBUG_REP(dmpDoesFieldBelongToClass(key, value)); + return value; +} + void MethodContext::recIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool result) { if (IsValidToken == nullptr) diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h index b342996b446317..4abbef3faf135d 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -769,6 +769,10 @@ class MethodContext void dmpGetExpectedTargetArchitecture(DWORD key, DWORD result); DWORD repGetExpectedTargetArchitecture(); + void recDoesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls, bool result); + void dmpDoesFieldBelongToClass(DLDL key, bool value); + bool repDoesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls); + void recIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool result); void dmpIsValidToken(DLD key, DWORD value); bool repIsValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK); @@ -1063,7 +1067,7 @@ enum mcPackets Packet_TryResolveToken = 158, // Added 4/26/2016 Packet_SatisfiesClassConstraints = 110, Packet_SatisfiesMethodConstraints = 111, - Packet_ShouldEnforceCallvirtRestriction = 112, // Retired 2/18/2020 + Packet_DoesFieldBelongToClass = 112, // Added 8/12/2021 Packet_SigInstHandleMap = 184, Packet_AllocPgoInstrumentationBySchema = 186, // Added 1/4/2021 Packet_GetPgoInstrumentationResults = 187, // Added 1/4/2021 diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 4390113cf02798..2b802b3eacc311 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -2010,3 +2010,13 @@ bool interceptor_ICJI::notifyInstructionSetUsage(CORINFO_InstructionSet instruct { return original_ICorJitInfo->notifyInstructionSetUsage(instructionSet, supported); } + +bool interceptor_ICJI::doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, + CORINFO_CLASS_HANDLE cls) +{ + mc->cr->AddCall("doesFieldBelongToClass"); + bool result = original_ICorJitInfo->doesFieldBelongToClass(fldHnd, cls); + mc->recDoesFieldBelongToClass(fldHnd, cls, result); + return result; +} diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 445cc2a490e5ba..e967975ae244a8 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1389,3 +1389,11 @@ uint32_t interceptor_ICJI::getJitFlags( return original_ICorJitInfo->getJitFlags(flags, sizeInBytes); } +bool interceptor_ICJI::doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, + CORINFO_CLASS_HANDLE cls) +{ + mcs->AddCall("doesFieldBelongToClass"); + return original_ICorJitInfo->doesFieldBelongToClass(fldHnd, cls); +} + diff --git a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 7b04e139c4d016..8c982934239fe3 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1217,3 +1217,10 @@ uint32_t interceptor_ICJI::getJitFlags( return original_ICorJitInfo->getJitFlags(flags, sizeInBytes); } +bool interceptor_ICJI::doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, + CORINFO_CLASS_HANDLE cls) +{ + return original_ICorJitInfo->doesFieldBelongToClass(fldHnd, cls); +} + diff --git a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp index b2cb35339adcc7..cac9ce2b0f8716 100644 --- a/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -1574,6 +1574,13 @@ uint32_t MyICJI::getJitFlags(CORJIT_FLAGS* jitFlags, uint32_t sizeInBytes) return ret; } +bool MyICJI::doesFieldBelongToClass(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLASS_HANDLE cls) +{ + jitInstance->mc->cr->AddCall("doesFieldBelongToClass"); + bool result = jitInstance->mc->repDoesFieldBelongToClass(fldHnd, cls); + return result; +} + // Runs the given function with the given parameter under an error trap // and returns true if the function completes successfully. We fake this // up a bit for SuperPMI and simply catch all exceptions. diff --git a/src/coreclr/debug/createdump/crashinfo.cpp b/src/coreclr/debug/createdump/crashinfo.cpp index 8ab327eb15578d..779102087260ac 100644 --- a/src/coreclr/debug/createdump/crashinfo.cpp +++ b/src/coreclr/debug/createdump/crashinfo.cpp @@ -13,6 +13,8 @@ CrashInfo::CrashInfo(pid_t pid, bool gatherFrames, pid_t crashThread, uint32_t s m_pid(pid), m_ppid(-1), m_hdac(nullptr), + m_pClrDataEnumRegions(nullptr), + m_pClrDataProcess(nullptr), m_gatherFrames(gatherFrames), m_crashThread(crashThread), m_signal(signal), @@ -44,6 +46,15 @@ CrashInfo::~CrashInfo() } m_moduleInfos.clear(); + // Clean up DAC interfaces + if (m_pClrDataEnumRegions != nullptr) + { + m_pClrDataEnumRegions->Release(); + } + if (m_pClrDataProcess != nullptr) + { + m_pClrDataProcess->Release(); + } // Unload DAC module if (m_hdac != nullptr) { @@ -190,8 +201,16 @@ CrashInfo::GatherCrashInfo(MINIDUMP_TYPE minidumpType) thread->GetThreadStack(); } } - // Gather all the useful memory regions from the DAC - if (!EnumerateMemoryRegionsWithDAC(minidumpType)) + // Load and initialize DAC interfaces + if (!InitializeDAC()) + { + return false; + } + if (!EnumerateManagedModules()) + { + return false; + } + if (!UnwindAllThreads()) { return false; } @@ -204,19 +223,15 @@ CrashInfo::GatherCrashInfo(MINIDUMP_TYPE minidumpType) // Enumerate all the memory regions using the DAC memory region support given a minidump type // bool -CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType) +CrashInfo::InitializeDAC() { ReleaseHolder dataTarget = new DumpDataTarget(*this); PFN_CLRDataCreateInstance pfnCLRDataCreateInstance = nullptr; - ICLRDataEnumMemoryRegions* pClrDataEnumRegions = nullptr; - IXCLRDataProcess* pClrDataProcess = nullptr; - HRESULT hr = S_OK; bool result = false; + HRESULT hr = S_OK; if (!m_coreclrPath.empty()) { - TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration STARTED\n"); - // We assume that the DAC is in the same location as the libcoreclr.so module std::string dacPath; dacPath.append(m_coreclrPath); @@ -235,140 +250,156 @@ CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType) fprintf(stderr, "GetProcAddress(CLRDataCreateInstance) FAILED %d\n", GetLastError()); goto exit; } - if ((minidumpType & MiniDumpWithFullMemory) == 0) - { - hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), dataTarget, (void**)&pClrDataEnumRegions); - if (FAILED(hr)) - { - fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr); - goto exit; - } - // Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC - hr = pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT); - if (FAILED(hr)) - { - fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr); - goto exit; - } - } - hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), dataTarget, (void**)&pClrDataProcess); + hr = pfnCLRDataCreateInstance(__uuidof(ICLRDataEnumMemoryRegions), dataTarget, (void**)&m_pClrDataEnumRegions); if (FAILED(hr)) { - fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr); + fprintf(stderr, "CLRDataCreateInstance(ICLRDataEnumMemoryRegions) FAILED %08x\n", hr); goto exit; } - TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration FINISHED\n"); - if (!EnumerateManagedModules(pClrDataProcess)) + hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), dataTarget, (void**)&m_pClrDataProcess); + if (FAILED(hr)) { + fprintf(stderr, "CLRDataCreateInstance(IXCLRDataProcess) FAILED %08x\n", hr); goto exit; } } - else { - TRACE("EnumerateMemoryRegionsWithDAC: coreclr not found; not using DAC\n"); - } - if (!UnwindAllThreads(pClrDataProcess)) + else { - goto exit; + TRACE("InitializeDAC: coreclr not found; not using DAC\n"); } result = true; exit: - if (pClrDataEnumRegions != nullptr) - { - pClrDataEnumRegions->Release(); - } - if (pClrDataProcess != nullptr) + return result; +} + +// +// Enumerate all the memory regions using the DAC memory region support given a minidump type +// +bool +CrashInfo::EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType) +{ + if (m_pClrDataEnumRegions != nullptr && (minidumpType & MiniDumpWithFullMemory) == 0) { - pClrDataProcess->Release(); + TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration STARTED\n"); + + // Since on both Linux and MacOS all the RW regions will be added for heap + // dumps by createdump, the only thing differentiating a MiniDumpNormal and + // a MiniDumpWithPrivateReadWriteMemory is that the later uses the EnumMemory + // APIs. This is kind of expensive on larger applications (4 minutes, or even + // more), and this should already be in RW pages. Change the dump type to the + // faster normal one. This one already ensures necessary DAC globals, etc. + // without the costly assembly, module, class, type runtime data structures + // enumeration. + if (minidumpType & MiniDumpWithPrivateReadWriteMemory) + { + char* fastHeapDumps = getenv("COMPlus_DbgEnableFastHeapDumps"); + if (fastHeapDumps != nullptr && strcmp(fastHeapDumps, "1") == 0) + { + minidumpType = MiniDumpNormal; + } + } + // Calls CrashInfo::EnumMemoryRegion for each memory region found by the DAC + HRESULT hr = m_pClrDataEnumRegions->EnumMemoryRegions(this, minidumpType, CLRDATA_ENUM_MEM_DEFAULT); + if (FAILED(hr)) + { + fprintf(stderr, "EnumMemoryRegions FAILED %08x\n", hr); + return false; + } + TRACE("EnumerateMemoryRegionsWithDAC: Memory enumeration FINISHED\n"); } - return result; + return true; } // // Enumerate all the managed modules and replace the module mapping with the module name found. // bool -CrashInfo::EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess) +CrashInfo::EnumerateManagedModules() { CLRDATA_ENUM enumModules = 0; - bool result = true; HRESULT hr = S_OK; - if (FAILED(hr = pClrDataProcess->StartEnumModules(&enumModules))) { - fprintf(stderr, "StartEnumModules FAILED %08x\n", hr); - return false; - } - - while (true) + if (m_pClrDataProcess != nullptr) { - ReleaseHolder pClrDataModule; - if ((hr = pClrDataProcess->EnumModule(&enumModules, &pClrDataModule)) != S_OK) { - break; - } + TRACE("EnumerateManagedModules: Module enumeration STARTED\n"); - // Skip any dynamic modules. The Request call below on some DACs crashes on dynamic modules. - ULONG32 flags; - if ((hr = pClrDataModule->GetFlags(&flags)) != S_OK) { - TRACE("MODULE: GetFlags FAILED %08x\n", hr); - continue; - } - if (flags & CLRDATA_MODULE_IS_DYNAMIC) { - TRACE("MODULE: Skipping dynamic module\n"); - continue; + if (FAILED(hr = m_pClrDataProcess->StartEnumModules(&enumModules))) { + fprintf(stderr, "StartEnumModules FAILED %08x\n", hr); + return false; } - DacpGetModuleData moduleData; - if (SUCCEEDED(hr = moduleData.Request(pClrDataModule.GetPtr()))) + while (true) { - TRACE("MODULE: %" PRIA PRIx64 " dyn %d inmem %d file %d pe %" PRIA PRIx64 " pdb %" PRIA PRIx64, (uint64_t)moduleData.LoadedPEAddress, moduleData.IsDynamic, - moduleData.IsInMemory, moduleData.IsFileLayout, (uint64_t)moduleData.PEFile, (uint64_t)moduleData.InMemoryPdbAddress); + ReleaseHolder pClrDataModule; + if ((hr = m_pClrDataProcess->EnumModule(&enumModules, &pClrDataModule)) != S_OK) { + break; + } - if (!moduleData.IsDynamic && moduleData.LoadedPEAddress != 0) + // Skip any dynamic modules. The Request call below on some DACs crashes on dynamic modules. + ULONG32 flags; + if ((hr = pClrDataModule->GetFlags(&flags)) != S_OK) { + TRACE("MODULE: GetFlags FAILED %08x\n", hr); + continue; + } + if (flags & CLRDATA_MODULE_IS_DYNAMIC) { + TRACE("MODULE: Skipping dynamic module\n"); + continue; + } + + DacpGetModuleData moduleData; + if (SUCCEEDED(hr = moduleData.Request(pClrDataModule.GetPtr()))) { - ArrayHolder wszUnicodeName = new WCHAR[MAX_LONGPATH + 1]; - if (SUCCEEDED(hr = pClrDataModule->GetFileName(MAX_LONGPATH, nullptr, wszUnicodeName))) + TRACE("MODULE: %" PRIA PRIx64 " dyn %d inmem %d file %d pe %" PRIA PRIx64 " pdb %" PRIA PRIx64, (uint64_t)moduleData.LoadedPEAddress, moduleData.IsDynamic, + moduleData.IsInMemory, moduleData.IsFileLayout, (uint64_t)moduleData.PEFile, (uint64_t)moduleData.InMemoryPdbAddress); + + if (!moduleData.IsDynamic && moduleData.LoadedPEAddress != 0) { - std::string moduleName = FormatString("%S", wszUnicodeName.GetPtr()); + ArrayHolder wszUnicodeName = new WCHAR[MAX_LONGPATH + 1]; + if (SUCCEEDED(hr = pClrDataModule->GetFileName(MAX_LONGPATH, nullptr, wszUnicodeName))) + { + std::string moduleName = FormatString("%S", wszUnicodeName.GetPtr()); - // Change the module mapping name - ReplaceModuleMapping(moduleData.LoadedPEAddress, moduleData.LoadedPESize, moduleName); + // Change the module mapping name + ReplaceModuleMapping(moduleData.LoadedPEAddress, moduleData.LoadedPESize, moduleName); - // Add managed module info - AddModuleInfo(true, moduleData.LoadedPEAddress, pClrDataModule, moduleName); + // Add managed module info + AddModuleInfo(true, moduleData.LoadedPEAddress, pClrDataModule, moduleName); + } + else { + TRACE("\nModule.GetFileName FAILED %08x\n", hr); + } } else { - TRACE("\nModule.GetFileName FAILED %08x\n", hr); + TRACE("\n"); } } else { - TRACE("\n"); + TRACE("moduleData.Request FAILED %08x\n", hr); } } - else { - TRACE("moduleData.Request FAILED %08x\n", hr); - } - } - if (enumModules != 0) { - pClrDataProcess->EndEnumModules(enumModules); + if (enumModules != 0) { + m_pClrDataProcess->EndEnumModules(enumModules); + } + TRACE("EnumerateManagedModules: Module enumeration FINISHED\n"); } - - return result; + return true; } // // Unwind all the native threads to ensure that the dwarf unwind info is added to the core dump. // bool -CrashInfo::UnwindAllThreads(IXCLRDataProcess* pClrDataProcess) +CrashInfo::UnwindAllThreads() { ReleaseHolder pSos = nullptr; - if (pClrDataProcess != nullptr) { - pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos); + if (m_pClrDataProcess != nullptr) { + m_pClrDataProcess->QueryInterface(__uuidof(ISOSDacInterface), (void**)&pSos); } // For each native and managed thread for (ThreadInfo* thread : m_threads) { - if (!thread->UnwindThread(pClrDataProcess, pSos)) { + if (!thread->UnwindThread(m_pClrDataProcess, pSos)) { return false; } } @@ -827,5 +858,5 @@ FormatGuid(const GUID* guid) { uint8_t* bytes = (uint8_t*)guid; return FormatString("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - bytes[3], bytes[2], bytes[1], bytes[0], bytes[5], bytes[4], bytes[7], bytes[6], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]); + bytes[3], bytes[2], bytes[1], bytes[0], bytes[5], bytes[4], bytes[7], bytes[6], bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]); } diff --git a/src/coreclr/debug/createdump/crashinfo.h b/src/coreclr/debug/createdump/crashinfo.h index ca8f77994ac751..e100b7f216102a 100644 --- a/src/coreclr/debug/createdump/crashinfo.h +++ b/src/coreclr/debug/createdump/crashinfo.h @@ -47,6 +47,8 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, pid_t m_ppid; // parent pid pid_t m_tgid; // process group HMODULE m_hdac; // dac module handle when loaded + ICLRDataEnumMemoryRegions* m_pClrDataEnumRegions; // dac enumerate memory interface instance + IXCLRDataProcess* m_pClrDataProcess; // dac process interface instance bool m_gatherFrames; // if true, add the native and managed stack frames to the thread info pid_t m_crashThread; // crashing thread id or 0 if none uint32_t m_signal; // crash signal code or 0 if none @@ -84,6 +86,7 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, void CleanupAndResumeProcess(); bool EnumerateAndSuspendThreads(); bool GatherCrashInfo(MINIDUMP_TYPE minidumpType); + bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType); bool ReadMemory(void* address, void* buffer, size_t size); // read memory and add to dump bool ReadProcessMemory(void* address, void* buffer, size_t size, size_t* read); // read raw memory uint64_t GetBaseAddressFromAddress(uint64_t address); @@ -137,9 +140,9 @@ class CrashInfo : public ICLRDataEnumMemoryRegionsCallback, void VisitProgramHeader(uint64_t loadbias, uint64_t baseAddress, ElfW(Phdr)* phdr); bool EnumerateModuleMappings(); #endif - bool EnumerateMemoryRegionsWithDAC(MINIDUMP_TYPE minidumpType); - bool EnumerateManagedModules(IXCLRDataProcess* pClrDataProcess); - bool UnwindAllThreads(IXCLRDataProcess* pClrDataProcess); + bool InitializeDAC(); + bool EnumerateManagedModules(); + bool UnwindAllThreads(); void ReplaceModuleMapping(CLRDATA_ADDRESS baseAddress, ULONG64 size, const std::string& pszName); void InsertMemoryBackedRegion(const MemoryRegion& region); void InsertMemoryRegion(const MemoryRegion& region); diff --git a/src/coreclr/debug/createdump/crashinfomac.cpp b/src/coreclr/debug/createdump/crashinfomac.cpp index ad9c247e37dfdc..3ada3bd767c964 100644 --- a/src/coreclr/debug/createdump/crashinfomac.cpp +++ b/src/coreclr/debug/createdump/crashinfomac.cpp @@ -277,6 +277,9 @@ void CrashInfo::VisitSegment(MachOModule& module, const segment_command_64& segm uint64_t start = segment.vmaddr + module.LoadBias(); uint64_t end = start + segment.vmsize; + // Add this module segment to the set used by the thread unwinding to lookup the module base address for an ip. + AddModuleAddressRange(start, end, module.BaseAddress()); + // Round to page boundary start = start & PAGE_MASK; _ASSERTE(start > 0); @@ -297,9 +300,6 @@ void CrashInfo::VisitSegment(MachOModule& module, const segment_command_64& segm } // Add this module segment to the module mappings list m_moduleMappings.insert(moduleRegion); - - // Add this module segment to the set used by the thread unwinding to lookup the module base address for an ip. - AddModuleAddressRange(start, end, module.BaseAddress()); } else { diff --git a/src/coreclr/debug/createdump/crashreportwriter.cpp b/src/coreclr/debug/createdump/crashreportwriter.cpp index 1fb0865cf5d5f7..4e9382f65f115f 100644 --- a/src/coreclr/debug/createdump/crashreportwriter.cpp +++ b/src/coreclr/debug/createdump/crashreportwriter.cpp @@ -84,18 +84,20 @@ CrashReportWriter::WriteCrashReport() { OpenObject(); bool crashed = false; - if (thread->ManagedExceptionObject() != 0) + if (thread->Tid() == m_crashInfo.CrashThread()) { crashed = true; - exceptionType = "0x05000000"; // ManagedException - } - else - { - if (thread->Tid() == m_crashInfo.CrashThread()) + if (thread->ManagedExceptionObject() != 0) + { + exceptionType = "0x05000000"; // ManagedException + } + else { - crashed = true; switch (m_crashInfo.Signal()) { + case 0: + break; + case SIGILL: exceptionType = "0x50000000"; break; @@ -121,9 +123,12 @@ CrashReportWriter::WriteCrashReport() break; case SIGABRT: - default: exceptionType = "0x30000000"; break; + + default: + exceptionType = "0x00000000"; + break; } } } diff --git a/src/coreclr/debug/createdump/createdumpunix.cpp b/src/coreclr/debug/createdump/createdumpunix.cpp index b789c98b820f14..6107adc625efc3 100644 --- a/src/coreclr/debug/createdump/createdumpunix.cpp +++ b/src/coreclr/debug/createdump/createdumpunix.cpp @@ -47,7 +47,12 @@ CreateDump(const char* dumpPathTemplate, int pid, const char* dumpType, MINIDUMP CrashReportWriter crashReportWriter(*crashInfo); crashReportWriter.WriteCrashReport(dumpPath); } - printf("Writing %s to file %s\n", dumpType, dumpPath.c_str()); + // Gather all the useful memory regions from the DAC + if (!crashInfo->EnumerateMemoryRegionsWithDAC(minidumpType)) + { + goto exit; + } + fprintf(stdout, "Writing %s to file %s\n", dumpType, dumpPath.c_str()); // Write the actual dump file if (!dumpWriter.OpenDump(dumpPath.c_str())) diff --git a/src/coreclr/debug/createdump/stackframe.h b/src/coreclr/debug/createdump/stackframe.h index 75e20d93120c0c..00c3a1cfb7fd8f 100644 --- a/src/coreclr/debug/createdump/stackframe.h +++ b/src/coreclr/debug/createdump/stackframe.h @@ -66,9 +66,16 @@ struct StackFrame } } +// See comment in threadinfo.cpp UnwindNativeFrames function +#if defined(__aarch64__) + #define STACK_POINTER_MASK ~0x7 +#else + #define STACK_POINTER_MASK ~0x0 +#endif + inline uint64_t ModuleAddress() const { return m_moduleAddress; } inline uint64_t InstructionPointer() const { return m_instructionPointer; } - inline uint64_t StackPointer() const { return m_stackPointer; } + inline uint64_t StackPointer() const { return m_stackPointer & STACK_POINTER_MASK; } inline uint32_t NativeOffset() const { return m_nativeOffset; } inline uint32_t Token() const { return m_token; } inline uint32_t ILOffset() const { return m_ilOffset; } diff --git a/src/coreclr/debug/createdump/threadinfo.cpp b/src/coreclr/debug/createdump/threadinfo.cpp index 82509f52750653..e64eafc8d29a96 100644 --- a/src/coreclr/debug/createdump/threadinfo.cpp +++ b/src/coreclr/debug/createdump/threadinfo.cpp @@ -53,6 +53,16 @@ ThreadInfo::UnwindNativeFrames(CONTEXT* pContext) uint64_t ip = 0, sp = 0; GetFrameLocation(pContext, &ip, &sp); +#if defined(__aarch64__) + // ARM64 can have frames with the same SP but different IPs. Increment sp so it gets added to the stack + // frames in the correct order and to prevent the below loop termination on non-increasing sp. Since stack + // pointers are always 8 byte align, this increase is masked off in StackFrame::StackPointer() to get the + // original stack pointer. + if (sp == previousSp && ip != previousIp) + { + sp++; + } +#endif if (ip == 0 || sp <= previousSp) { TRACE_VERBOSE("Unwind: sp not increasing or ip == 0 sp %p ip %p\n", (void*)sp, (void*)ip); break; diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 61f0d827e60f19..dee4fe132fa74c 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -6077,13 +6077,20 @@ ClrDataAccess::GetMethodVarInfo(MethodDesc* methodDesc, SUPPORTS_DAC; COUNT_T countNativeVarInfo; NewHolder nativeVars(NULL); - - NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address); - if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL) + TADDR nativeCodeStartAddr; + if (address != NULL) { - return E_INVALIDARG; + NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address); + if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL) + { + return E_INVALIDARG; + } + nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode()); + } + else + { + nativeCodeStartAddr = PCODEToPINSTR(methodDesc->GetNativeCode()); } - TADDR nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode()); DebugInfoRequest request; request.InitFromStartingAddr(methodDesc, nativeCodeStartAddr); @@ -6128,13 +6135,20 @@ ClrDataAccess::GetMethodNativeMap(MethodDesc* methodDesc, // Use the DebugInfoStore to get IL->Native maps. // It doesn't matter whether we're jitted, ngenned etc. - - NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address); - if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL) + TADDR nativeCodeStartAddr; + if (address != NULL) { - return E_INVALIDARG; + NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address); + if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL) + { + return E_INVALIDARG; + } + nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode()); + } + else + { + nativeCodeStartAddr = PCODEToPINSTR(methodDesc->GetNativeCode()); } - TADDR nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode()); DebugInfoRequest request; request.InitFromStartingAddr(methodDesc, nativeCodeStartAddr); diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 2924be33c049de..8e587b8d1e5c26 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -4771,15 +4771,15 @@ VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetThreadObject(VMPTR_Thread vmThread) } } -void DacDbiInterfaceImpl::GetThreadAllocInfo(VMPTR_Thread vmThread, +void DacDbiInterfaceImpl::GetThreadAllocInfo(VMPTR_Thread vmThread, DacThreadAllocInfo* threadAllocInfo) { DD_ENTER_MAY_THROW; Thread * pThread = vmThread.GetDacPtr(); gc_alloc_context* allocContext = pThread->GetAllocContext(); - threadAllocInfo->m_allocBytesSOH = (ULONG)(allocContext->alloc_bytes - (allocContext->alloc_limit - allocContext->alloc_ptr)); - threadAllocInfo->m_allocBytesUOH = (ULONG)allocContext->alloc_bytes_uoh; + threadAllocInfo->m_allocBytesSOH = allocContext->alloc_bytes - (allocContext->alloc_limit - allocContext->alloc_ptr); + threadAllocInfo->m_allocBytesUOH = allocContext->alloc_bytes_uoh; } // Set and reset the TSNC_DebuggerUserSuspend bit on the state of the specified thread @@ -4939,6 +4939,10 @@ VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr) OBJECTHANDLE ohCCW = NULL; +#ifdef FEATURE_COMWRAPPERS + if (DACTryGetComWrappersHandleFromCCW(ccwPtr, &ohCCW) != S_OK) + { +#endif #ifdef FEATURE_COMINTEROP ComCallWrapper *pCCW = DACGetCCWFromAddress(ccwPtr); if (pCCW) @@ -4946,6 +4950,9 @@ VMPTR_OBJECTHANDLE DacDbiInterfaceImpl::GetObjectForCCW(CORDB_ADDRESS ccwPtr) ohCCW = pCCW->GetObjectHandle(); } #endif +#ifdef FEATURE_COMWRAPPERS + } +#endif VMPTR_OBJECTHANDLE vmObjHandle; vmObjHandle.SetDacTargetPtr(ohCCW); @@ -5462,6 +5469,12 @@ GENERICS_TYPE_TOKEN DacDbiInterfaceImpl::ResolveExactGenericArgsToken(DWORD if (dwExactGenericArgsTokenIndex == 0) { + // In a rare case of VS4Mac debugging VS4Mac ARM64 optimized code we get a null generics argument token. This workaround + // should only cause us to degrade generic types from exact type parameters to approximate or canonical type parameters. + if (rawToken == 0) + { + return rawToken; + } // In this case the real generics type token is the MethodTable of the "this" object. // Note that we want the target address here. diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 62d99ec574929d..6e0001cf5c1acf 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -1498,6 +1498,11 @@ class ClrDataAccess static LONG s_procInit; +protected: +#ifdef FEATURE_COMWRAPPERS + HRESULT DACTryGetComWrappersHandleFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTHANDLE* objHandle); +#endif + public: // APIs for picking up the info needed for a debugger to look up an ngen image or IL image // from it's search path. diff --git a/src/coreclr/debug/daccess/enummem.cpp b/src/coreclr/debug/daccess/enummem.cpp index 577fdcbc6b2e44..403260bed5dfdf 100644 --- a/src/coreclr/debug/daccess/enummem.cpp +++ b/src/coreclr/debug/daccess/enummem.cpp @@ -1624,6 +1624,7 @@ HRESULT ClrDataAccess::EnumMemoryRegionsWorkerSkinny(IN CLRDataEnumMemoryFlags f // // collect CLR static CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( status = EnumMemCLRStatic(flags); ) + CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( status = EnumMemCLRHeapCrticalStatic(flags); ); // Dump AppDomain-specific info needed for MiniDumpNormal. CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED( status = EnumMemDumpAppDomainInfo(flags); ) diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index f075dbe29c4e2e..18b775d609ecd0 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -3780,24 +3780,24 @@ ClrDataAccess::EnumWksGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) Dereference(g_gcDacGlobals->finalize_queue).EnumMem(); // Enumerate the entire generation table, which has variable size - size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2); - DacEnumMemoryRegion(dac_cast(g_gcDacGlobals->generation_table), gen_table_size); + EnumGenerationTable(dac_cast(g_gcDacGlobals->generation_table)); if (g_gcDacGlobals->generation_table.IsValid()) { - // enumerating the generations from max (which is normally gen2) to max+1 gives you - // the segment list for all the normal segements plus the large heap segment (max+1) - // this is the convention in the GC so it is repeated here - for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++) + ULONG first = IsRegion() ? 0 : (*g_gcDacGlobals->max_gen); + // enumerating the first to max + 2 gives you + // the segment list for all the normal segments plus the pinned heap segment (max + 2) + // this is the convention in the GC so it is repeated here + for (ULONG i = first; i <= *g_gcDacGlobals->max_gen + 2; i++) + { + dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i); + __DPtr seg = dac_cast(gen.start_segment); + while (seg) { - dac_generation gen = GenerationTableIndex(g_gcDacGlobals->generation_table, i); - __DPtr seg = dac_cast(gen.start_segment); - while (seg) - { - DacEnumMemoryRegion(dac_cast(seg), sizeof(dac_heap_segment)); - seg = seg->next; - } + DacEnumMemoryRegion(dac_cast(seg), sizeof(dac_heap_segment)); + seg = seg->next; } + } } } @@ -3842,11 +3842,11 @@ HRESULT ClrDataAccess::GetClrWatsonBucketsWorker(Thread * pThread, GenericModeBl if (oThrowable != NULL) { // Does the throwable have buckets? - if (((EXCEPTIONREF)oThrowable)->AreWatsonBucketsPresent()) + U1ARRAYREF refWatsonBucketArray = ((EXCEPTIONREF)oThrowable)->GetWatsonBucketReference(); + if (refWatsonBucketArray != NULL) { // Get the watson buckets from the throwable for non-preallocated // exceptions - U1ARRAYREF refWatsonBucketArray = ((EXCEPTIONREF)oThrowable)->GetWatsonBucketReference(); pBuckets = dac_cast(refWatsonBucketArray->GetDataPtr()); } else @@ -4176,12 +4176,18 @@ TADDR ClrDataAccess::DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr) return managedObjectWrapperPtr; } -HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef) +HRESULT ClrDataAccess::DACTryGetComWrappersHandleFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTHANDLE* objHandle) { - if (ccwPtr == 0 || objRef == NULL) - return E_INVALIDARG; + HRESULT hr = E_FAIL; + TADDR ccw, managedObjectWrapperPtr; + ULONG32 bytesRead = 0; + OBJECTHANDLE handle; - SOSDacEnter(); + if (ccwPtr == 0 || objHandle == NULL) + { + hr = E_INVALIDARG; + goto ErrExit; + } if (!DACIsComWrappersCCW(ccwPtr)) { @@ -4189,18 +4195,16 @@ HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, goto ErrExit; } - TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr); + ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr); // Return ManagedObjectWrapper as an OBJECTHANDLE. (The OBJECTHANDLE is guaranteed to live at offset 0). - TADDR managedObjectWrapperPtr = DACGetManagedObjectWrapperFromCCW(ccwPtr); + managedObjectWrapperPtr = DACGetManagedObjectWrapperFromCCW(ccwPtr); if (managedObjectWrapperPtr == NULL) { hr = E_FAIL; goto ErrExit; } - ULONG32 bytesRead = 0; - OBJECTHANDLE handle; IfFailGo(m_pTarget->ReadVirtual(managedObjectWrapperPtr, (PBYTE)&handle, sizeof(OBJECTHANDLE), &bytesRead)); if (bytesRead != sizeof(OBJECTHANDLE)) { @@ -4208,9 +4212,31 @@ HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, goto ErrExit; } - *objRef = ObjectFromHandle(handle); + *objHandle = handle; - SOSDacLeave(); + return S_OK; + +ErrExit: return hr; +} + +HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef) +{ + HRESULT hr = E_FAIL; + + if (ccwPtr == 0 || objRef == NULL) + { + hr = E_INVALIDARG; + goto ErrExit; + } + + OBJECTHANDLE handle; + if (DACTryGetComWrappersHandleFromCCW(ccwPtr, &handle) != S_OK) + { + hr = E_FAIL; + goto ErrExit; + } + + *objRef = ObjectFromHandle(handle); return S_OK; diff --git a/src/coreclr/debug/daccess/request_common.h b/src/coreclr/debug/daccess/request_common.h index e6c976f16ffa67..742d24fb3d391f 100644 --- a/src/coreclr/debug/daccess/request_common.h +++ b/src/coreclr/debug/daccess/request_common.h @@ -62,6 +62,15 @@ HeapTableIndex(DPTR(unused_gc_heap**) heaps, size_t index) result.field_name = field_name; \ } +// if (field_offset != -1) +// p_field.EnumMem(); +#define ENUM(field_name, field_type) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + p_##field_name.EnumMem(); \ + } + // if (field_offset != -1) // result.field = DPTR(field_type)field_name #define LOAD_DPTR(field_name, field_type) \ @@ -87,6 +96,13 @@ HeapTableIndex(DPTR(unused_gc_heap**) heaps, size_t index) } \ } +#define ENUM_ARRAY(field_name, field_type, array_length) \ + LOAD_BASE(field_name, field_type) \ + if (field_name##_offset != -1) \ + { \ + DacEnumMemoryRegion(p_##field_name.GetAddr(), sizeof(field_type) * array_length); \ + } + inline bool IsRegion() { return (g_gcDacGlobals->minor_version_number & 1) != 0; @@ -121,6 +137,26 @@ LoadGcHeapData(TADDR heap) return result; } +inline void EnumGcHeap(TADDR heap) +{ + DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; + int field_index = 0; + +#define BASE heap +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) ENUM_ARRAY(field_name, field_type, array_length) + +#include "../../gc/dac_gcheap_fields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS +#undef BASE +} + // Load an instance of dac_generation for the generation pointed by generation. // Fields that does not exist in the current generation instance is zero initialized. // Return the dac_generation object. @@ -148,6 +184,26 @@ LoadGeneration(TADDR generation) return result; } +inline void EnumGeneration(TADDR generation) +{ + DPTR(int) field_offsets = g_gcDacGlobals->generation_field_offsets; + int field_index = 0; + +#define BASE generation +#define ALL_FIELDS +#define DEFINE_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_DPTR_FIELD(field_name, field_type) ENUM(field_name, field_type) +#define DEFINE_ARRAY_FIELD(field_name, field_type, array_length) ENUM_ARRAY(field_name, field_type, array_length) + +#include "../../gc/dac_generation_fields.h" + +#undef DEFINE_ARRAY_FIELD +#undef DEFINE_DPTR_FIELD +#undef DEFINE_FIELD +#undef ALL_FIELDS +#undef BASE +} + // Indexes into a given generation table, returning a dac_generation inline dac_generation GenerationTableIndex(DPTR(unused_generation) base, size_t index) @@ -155,10 +211,7 @@ GenerationTableIndex(DPTR(unused_generation) base, size_t index) return LoadGeneration(TableIndex(base, index, g_gcDacGlobals->generation_size).GetAddr()); } -// Indexes into a heap's generation table, given the heap instance -// and the desired index. Returns a dac_generation -inline dac_generation -ServerGenerationTableIndex(TADDR heap, size_t index) +inline TADDR ServerGenerationTableAddress(TADDR heap) { DPTR(int) field_offsets = g_gcDacGlobals->gc_heap_field_offsets; int field_index = GENERATION_TABLE_FIELD_INDEX; @@ -166,9 +219,27 @@ ServerGenerationTableIndex(TADDR heap, size_t index) LOAD_BASE (generation_table, unused_generation); #undef BASE assert (generation_table_offset != -1); + return p_generation_table.GetAddr(); +} + +// Indexes into a heap's generation table, given the heap instance +// and the desired index. Returns a dac_generation +inline dac_generation +ServerGenerationTableIndex(TADDR heap, size_t index) +{ + DPTR(unused_generation) p_generation_table = ServerGenerationTableAddress(heap); return LoadGeneration(TableIndex(p_generation_table, index, g_gcDacGlobals->generation_size).GetAddr()); } +inline void EnumGenerationTable(TADDR generation_table) +{ + DPTR(unused_generation) p_generation_table = generation_table; + for (unsigned int i = 0; i < *g_gcDacGlobals->max_gen + 2; i++) + { + EnumGeneration(TableIndex(p_generation_table, i, g_gcDacGlobals->generation_size).GetAddr()); + } +} + #undef LOAD_ARRAY #undef LOAD_DPTR #undef LOAD diff --git a/src/coreclr/debug/daccess/request_svr.cpp b/src/coreclr/debug/daccess/request_svr.cpp index 5ff14b0adb56a3..b265fc2aef9a95 100644 --- a/src/coreclr/debug/daccess/request_svr.cpp +++ b/src/coreclr/debug/daccess/request_svr.cpp @@ -122,8 +122,11 @@ ClrDataAccess::ServerGCHeapDetails(CLRDATA_ADDRESS heapAddr, DacpGcHeapDetails * detailsData->lowest_address = PTR_CDADDR(g_lowest_address); detailsData->highest_address = PTR_CDADDR(g_highest_address); - detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; - + detailsData->current_c_gc_state = c_gc_state_free; + if (g_gcDacGlobals->current_c_gc_state != NULL) + { + detailsData->current_c_gc_state = (CLRDATA_ADDRESS)*g_gcDacGlobals->current_c_gc_state; + } // now get information specific to this heap (server mode gives us several heaps; we're getting // information about only one of them. detailsData->alloc_allocated = (CLRDATA_ADDRESS)pHeap->alloc_allocated; @@ -252,21 +255,19 @@ ClrDataAccess::EnumSvrGlobalMemoryRegions(CLRDataEnumMemoryFlags flags) for (int i = 0; i < heaps; i++) { - TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); + TADDR heapAddress = HeapTableIndex(g_gcDacGlobals->g_heaps, i); dac_gc_heap heap = LoadGcHeapData(heapAddress); dac_gc_heap* pHeap = &heap; - - size_t gen_table_size = g_gcDacGlobals->generation_size * (*g_gcDacGlobals->max_gen + 2); - DacEnumMemoryRegion(dac_cast(pHeap), sizeof(dac_gc_heap)); + EnumGcHeap(heapAddress); + TADDR generationTable = ServerGenerationTableAddress(heapAddress); + EnumGenerationTable(generationTable); DacEnumMemoryRegion(dac_cast(pHeap->finalize_queue), sizeof(dac_finalize_queue)); - TADDR taddrTable = dac_cast(pHeap) + offsetof(dac_gc_heap, generation_table); - DacEnumMemoryRegion(taddrTable, gen_table_size); - - // enumerating the generations from max (which is normally gen2) to max+1 gives you - // the segment list for all the normal segements plus the large heap segment (max+1) + ULONG first = IsRegion() ? 0 : (*g_gcDacGlobals->max_gen); + // enumerating the first to max + 2 gives you + // the segment list for all the normal segments plus the pinned heap segment (max + 2) // this is the convention in the GC so it is repeated here - for (ULONG i = *g_gcDacGlobals->max_gen; i <= *g_gcDacGlobals->max_gen +1; i++) + for (ULONG i = first; i <= *g_gcDacGlobals->max_gen + 2; i++) { dac_generation generation = ServerGenerationTableIndex(heapAddress, i); DPTR(dac_heap_segment) seg = generation.start_segment; diff --git a/src/coreclr/debug/dbgutil/machoreader.cpp b/src/coreclr/debug/dbgutil/machoreader.cpp index a19c01b94b3736..7fef34e1afb16d 100644 --- a/src/coreclr/debug/dbgutil/machoreader.cpp +++ b/src/coreclr/debug/dbgutil/machoreader.cpp @@ -126,19 +126,41 @@ MachOModule::TryLookupSymbol(const char* symbolName, uint64_t* symbolValue) _ASSERTE(m_nlists != nullptr); _ASSERTE(m_strtabAddress != 0); - for (int i = 0; i < m_dysymtabCommand->nextdefsym; i++) + // First, search just the "external" export symbols + if (TryLookupSymbol(m_dysymtabCommand->iextdefsym, m_dysymtabCommand->nextdefsym, symbolName, symbolValue)) { - std::string name = GetSymbolName(i); - // Skip the leading underscores to match Linux externs - if (name[0] == '_') - { - name.erase(0, 1); - } - if (strcmp(name.c_str(), symbolName) == 0) - { - *symbolValue = m_loadBias + m_nlists[i].n_value; - return true; - } + m_reader.Trace("SYM: Found '%s' in external symbols\n", symbolName); + return true; + } + m_reader.Trace("SYM: Missed '%s' in external symbols\n", symbolName); + + // If not found in external symbols, search all of them + if (TryLookupSymbol(0, m_symtabCommand->nsyms, symbolName, symbolValue)) + { + m_reader.Trace("SYM: Found '%s' in all symbols\n", symbolName); + return true; + } + m_reader.Trace("SYM: Missed '%s' in all symbols\n", symbolName); + } + *symbolValue = 0; + return false; +} + +bool +MachOModule::TryLookupSymbol(int start, int nsyms, const char* symbolName, uint64_t* symbolValue) +{ + for (int i = 0; i < nsyms; i++) + { + std::string name = GetSymbolName(start + i); + + // Skip the leading underscores to match Linux externs + const char* currentName = name.length() > 0 && name[0] == '_' ? name.c_str() + 1 : name.c_str(); + + // Does this symbol match? + if (strcmp(currentName, symbolName) == 0) + { + *symbolValue = m_loadBias + m_nlists[start + i].n_value; + return true; } } *symbolValue = 0; @@ -207,11 +229,10 @@ MachOModule::ReadLoadCommands() m_segments.push_back(segment); // Calculate the load bias for the module. This is the value to add to the vmaddr of a - // segment to get the actual address. + // segment to get the actual address. if (strcmp(segment->segname, SEG_TEXT) == 0) { m_loadBias = m_baseAddress - segment->vmaddr; - m_reader.TraceVerbose("CMD: load bias %016llx\n", m_loadBias); } m_reader.TraceVerbose("CMD: vmaddr %016llx vmsize %016llx fileoff %016llx filesize %016llx nsects %d max %c%c%c init %c%c%c %02x %s\n", @@ -245,6 +266,7 @@ MachOModule::ReadLoadCommands() // Get next load command command = (load_command*)((char*)command + command->cmdsize); } + m_reader.TraceVerbose("CMD: load bias %016llx\n", m_loadBias); } return true; @@ -262,26 +284,30 @@ MachOModule::ReadSymbolTable() _ASSERTE(m_symtabCommand != nullptr); _ASSERTE(m_strtabAddress == 0); - m_reader.TraceVerbose("SYM: symoff %08x nsyms %d stroff %08x strsize %d iext %d next %d\n", + m_reader.TraceVerbose("SYM: symoff %08x nsyms %d stroff %08x strsize %d iext %d next %d iundef %d nundef %d extref %d nextref %d\n", m_symtabCommand->symoff, m_symtabCommand->nsyms, m_symtabCommand->stroff, m_symtabCommand->strsize, m_dysymtabCommand->iextdefsym, - m_dysymtabCommand->nextdefsym); - - // Read the external symbol part of symbol table. An array of "nlist" structs. - void* extSymbolTableAddress = (void*)(GetAddressFromFileOffset(m_symtabCommand->symoff) + (m_dysymtabCommand->iextdefsym * sizeof(nlist_64))); - size_t symtabSize = sizeof(nlist_64) * m_dysymtabCommand->nextdefsym; + m_dysymtabCommand->nextdefsym, + m_dysymtabCommand->iundefsym, + m_dysymtabCommand->nundefsym, + m_dysymtabCommand->extrefsymoff, + m_dysymtabCommand->nextrefsyms); + + // Read the entire symbol part of symbol table. An array of "nlist" structs. + void* symbolTableAddress = (void*)GetAddressFromFileOffset(m_symtabCommand->symoff); + size_t symtabSize = sizeof(nlist_64) * m_symtabCommand->nsyms; m_nlists = (nlist_64*)malloc(symtabSize); if (m_nlists == nullptr) { - m_reader.Trace("ERROR: Failed to allocate %zu byte external symbol table\n", symtabSize); + m_reader.Trace("ERROR: Failed to allocate %zu byte symtab\n", symtabSize); return false; } - if (!m_reader.ReadMemory(extSymbolTableAddress, m_nlists, symtabSize)) + if (!m_reader.ReadMemory(symbolTableAddress, m_nlists, symtabSize)) { - m_reader.Trace("ERROR: Failed to read external symtab at %p of %zu\n", extSymbolTableAddress, symtabSize); + m_reader.Trace("ERROR: Failed to read symtab at %p of %zu\n", symbolTableAddress, symtabSize); return false; } diff --git a/src/coreclr/debug/dbgutil/machoreader.h b/src/coreclr/debug/dbgutil/machoreader.h index bb9ffe0fdd7ceb..a5f458b17ff2d5 100644 --- a/src/coreclr/debug/dbgutil/machoreader.h +++ b/src/coreclr/debug/dbgutil/machoreader.h @@ -37,6 +37,7 @@ class MachOModule bool ReadHeader(); bool TryLookupSymbol(const char* symbolName, uint64_t* symbolValue); + bool TryLookupSymbol(int start, int nsyms, const char* symbolName, uint64_t* symbolValue); bool EnumerateSegments(); private: diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index f4e3077938b720..98654ffc107edd 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -6045,7 +6045,8 @@ struct GetActiveInternalFramesData class CordbThread : public CordbBase, public ICorDebugThread, public ICorDebugThread2, public ICorDebugThread3, - public ICorDebugThread4 + public ICorDebugThread4, + public ICorDebugThread5 { public: CordbThread(CordbProcess * pProcess, VMPTR_Thread); @@ -6116,6 +6117,10 @@ class CordbThread : public CordbBase, public ICorDebugThread, // ICorDebugThread4 COM_METHOD HasUnhandledException(); + // ICorDebugThread5 + COM_METHOD GetBytesAllocated(ULONG64 *pSohAllocatedBytes, + ULONG64 *pUohAllocatedBytes); + COM_METHOD GetBlockingObjects(ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); // Gets the current CustomNotification object from the thread or NULL if no such object exists diff --git a/src/coreclr/debug/di/rsthread.cpp b/src/coreclr/debug/di/rsthread.cpp index 04a7fa21a1db4d..577574b796019c 100644 --- a/src/coreclr/debug/di/rsthread.cpp +++ b/src/coreclr/debug/di/rsthread.cpp @@ -186,6 +186,10 @@ HRESULT CordbThread::QueryInterface(REFIID id, void ** ppInterface) { *ppInterface = static_cast(this); } + else if (id == IID_ICorDebugThread5) + { + *ppInterface = static_cast(this); + } else if (id == IID_IUnknown) { *ppInterface = static_cast(static_cast(this)); @@ -2457,6 +2461,42 @@ HRESULT CordbThread::GetCurrentCustomDebuggerNotification(ICorDebugValue ** ppNo return hr; } +// ICorDebugThread5 + +/* + * GetBytesAllocated + * + * Returns S_OK if it was possible to obtain the allocation information for the thread + * and sets the corresponding SOH and UOH allocations. + */ +HRESULT CordbThread::GetBytesAllocated(ULONG64 *pSohAllocatedBytes, + ULONG64 *pUohAllocatedBytes) +{ + PUBLIC_API_ENTRY(this); + FAIL_IF_NEUTERED(this); + ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess()); + + HRESULT hr = S_OK; + EX_TRY + { + DacThreadAllocInfo threadAllocInfo = { 0 }; + + if (pSohAllocatedBytes == NULL || pUohAllocatedBytes == NULL) + { + ThrowHR(E_INVALIDARG); + } + + IDacDbiInterface * pDAC = GetProcess()->GetDAC(); + pDAC->GetThreadAllocInfo(m_vmThreadToken, &threadAllocInfo); + + *pSohAllocatedBytes = threadAllocInfo.m_allocBytesSOH; + *pUohAllocatedBytes = threadAllocInfo.m_allocBytesUOH; + } + EX_CATCH_HRESULT(hr); + + return hr; +} // CordbThread::GetBytesAllocated + /* * * SetRemapIP @@ -10775,4 +10815,3 @@ HRESULT CordbCodeEnum::Next(ULONG celt, ICorDebugCode *values[], ULONG *pceltFet return hr; } - diff --git a/src/coreclr/debug/inc/dacdbistructures.h b/src/coreclr/debug/inc/dacdbistructures.h index 2dabaa48e2c23d..19c788edb297f6 100644 --- a/src/coreclr/debug/inc/dacdbistructures.h +++ b/src/coreclr/debug/inc/dacdbistructures.h @@ -787,8 +787,8 @@ struct MSLAYOUT DacSharedReJitInfo // These represent the allocated bytes so far on the thread. struct MSLAYOUT DacThreadAllocInfo { - ULONG m_allocBytesSOH; - ULONG m_allocBytesUOH; + ULONG64 m_allocBytesSOH; + ULONG64 m_allocBytesUOH; }; #include "dacdbistructures.inl" diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 161f6e1e6c8c4c..7f83466b055e44 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -496,6 +496,7 @@ BEGIN IDS_EE_ARRAY_DIMENSIONS_EXCEEDED "Array dimensions exceeded supported range." + IDS_EE_OUT_OF_SYNCBLOCKS "Internal limitation: attempt to create more than 2^26 SyncBlocks." IDS_EE_THREAD_NOTSTARTED "Thread has not been started." IDS_EE_STRING_TOOLONG "Marshaler restriction: Excessively long string." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index 0e39c27f0c88cf..7acb390b640a60 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -369,6 +369,7 @@ #define IDS_EE_COMIMPORT_METHOD_NO_INTERFACE 0x1aab #define IDS_EE_OUT_OF_MEMORY_WITHIN_RANGE 0x1aac #define IDS_EE_ARRAY_DIMENSIONS_EXCEEDED 0x1aad +#define IDS_EE_OUT_OF_SYNCBLOCKS 0x1aae #define IDS_CLASSLOAD_MI_CANNOT_OVERRIDE 0x1ab3 #define IDS_CLASSLOAD_COLLECTIBLEFIXEDVTATTR 0x1ab6 diff --git a/src/coreclr/gc/env/gcenv.ee.h b/src/coreclr/gc/env/gcenv.ee.h index 7ecbfdda4f21ad..472679736a538d 100644 --- a/src/coreclr/gc/env/gcenv.ee.h +++ b/src/coreclr/gc/env/gcenv.ee.h @@ -92,6 +92,8 @@ class GCToEEInterface static void UpdateGCEventStatus(int publicLevel, int publicKeywords, int privateLevel, int privateKeywords); static void LogStressMsg(unsigned level, unsigned facility, const StressLogMsg &msg); static uint32_t GetCurrentProcessCpuCount(); + + static void DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved); }; #endif // __GCENV_EE_H__ diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 47ff77df3f49f8..016c1849b24436 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -2243,6 +2243,7 @@ double gc_heap::short_plugs_pad_ratio = 0; #endif //SHORT_PLUGS int gc_heap::generation_skip_ratio_threshold = 0; +int gc_heap::conserve_mem_setting = 0; uint64_t gc_heap::suspended_start_time = 0; uint64_t gc_heap::end_gc_time = 0; @@ -2724,7 +2725,7 @@ alloc_list gc_heap::poh_alloc_list [NUM_POH_ALIST-1]; #ifdef DOUBLY_LINKED_FL // size we removed with no undo; only for recording purpose size_t gc_heap::gen2_removed_no_undo = 0; -size_t gc_heap::saved_pinned_plug_index = 0; +size_t gc_heap::saved_pinned_plug_index = INVALID_SAVED_PINNED_PLUG_INDEX; #endif //DOUBLY_LINKED_FL #ifdef FEATURE_EVENT_TRACE @@ -3255,6 +3256,12 @@ gc_heap::dt_low_card_table_efficiency_p (gc_tuning_point tp) return ret; } +inline BOOL +gc_heap::dt_high_memory_load_p() +{ + return ((settings.entry_memory_load >= high_memory_load_th) || g_low_memory_status); +} + inline BOOL in_range_for_segment(uint8_t* add, heap_segment* seg) { @@ -5807,8 +5814,6 @@ heap_segment* gc_heap::get_segment_for_uoh (int gen_number, size_t size gc_etw_segment_pinned_object_heap : gc_etw_segment_large_object_heap); - GCToEEInterface::DiagUpdateGenerationBounds(); - #ifndef USE_REGIONS #ifdef MULTIPLE_HEAPS hp->thread_uoh_segment (gen_number, res); @@ -5816,6 +5821,12 @@ heap_segment* gc_heap::get_segment_for_uoh (int gen_number, size_t size thread_uoh_segment (gen_number, res); #endif //MULTIPLE_HEAPS #endif //!USE_REGIONS + GCToEEInterface::DiagAddNewRegion( + gen_number, + heap_segment_mem (res), + heap_segment_allocated (res), + heap_segment_reserved (res) + ); } return res; @@ -10913,7 +10924,7 @@ void gc_heap::clear_region_info (heap_segment* region) settings.gc_index, current_bgc_state, seg_deleted); - if (settings.entry_memory_load >= high_memory_load_th || g_low_memory_status) + if (dt_high_memory_load_p()) { decommit_mark_array_by_seg (region); } @@ -11372,7 +11383,7 @@ size_t gc_heap::decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t* new_committed) { #ifdef USE_REGIONS - if (settings.entry_memory_load < high_memory_load_th && !g_low_memory_status) + if (!dt_high_memory_load_p()) { return 0; } @@ -11407,7 +11418,7 @@ size_t gc_heap::decommit_heap_segment_pages_worker (heap_segment* seg, void gc_heap::decommit_heap_segment (heap_segment* seg) { #ifdef USE_REGIONS - if (settings.entry_memory_load < high_memory_load_th && !g_low_memory_status) + if (!dt_high_memory_load_p()) { return; } @@ -12357,9 +12368,9 @@ void gc_heap::make_generation (int gen_num, heap_segment* seg, uint8_t* start) #endif //DOUBLY_LINKED_FL #ifdef FREE_USAGE_STATS - memset (gen->gen_free_spaces, 0, sizeof (gen.gen_free_spaces)); - memset (gen->gen_current_pinned_free_spaces, 0, sizeof (gen.gen_current_pinned_free_spaces)); - memset (gen->gen_plugs, 0, sizeof (gen.gen_plugs)); + memset (gen->gen_free_spaces, 0, sizeof (gen->gen_free_spaces)); + memset (gen->gen_current_pinned_free_spaces, 0, sizeof (gen->gen_current_pinned_free_spaces)); + memset (gen->gen_plugs, 0, sizeof (gen->gen_plugs)); #endif //FREE_USAGE_STATS } @@ -12954,6 +12965,14 @@ gc_heap::init_semi_shared() #endif //FEATURE_LOH_COMPACTION #endif //FEATURE_EVENT_TRACE + conserve_mem_setting = (int)GCConfig::GetGCConserveMem(); + if (conserve_mem_setting < 0) + conserve_mem_setting = 0; + if (conserve_mem_setting > 9) + conserve_mem_setting = 9; + + dprintf (1, ("conserve_mem_setting = %d", conserve_mem_setting)); + ret = 1; cleanup: @@ -13884,7 +13903,20 @@ void gc_heap::adjust_limit (uint8_t* start, size_t limit_size, generation* gen) uint8_t* old_loc = generation_last_free_list_allocated (gen); // check if old_loc happens to be in a saved plug_and_gap with a pinned plug after it - uint8_t* saved_plug_and_gap = pinned_plug (pinned_plug_of (saved_pinned_plug_index)) - sizeof(plug_and_gap); + uint8_t* saved_plug_and_gap = nullptr; + if (saved_pinned_plug_index != INVALID_SAVED_PINNED_PLUG_INDEX) + { + saved_plug_and_gap = pinned_plug (pinned_plug_of (saved_pinned_plug_index)) - sizeof(plug_and_gap); + + dprintf (3333, ("[h%d] sppi: %Id mtos: %Id old_loc: %Ix pp: %Ix(%Id) offs: %Id", + heap_number, + saved_pinned_plug_index, + mark_stack_tos, + old_loc, + pinned_plug (pinned_plug_of (saved_pinned_plug_index)), + pinned_len (pinned_plug_of (saved_pinned_plug_index)), + old_loc - saved_plug_and_gap)); + } size_t offset = old_loc - saved_plug_and_gap; if (offset < sizeof(gap_reloc_pair)) { @@ -15904,11 +15936,13 @@ BOOL gc_heap::soh_try_fit (int gen_number, fix_youngest_allocation_area(); heap_segment* next_seg = heap_segment_next (ephemeral_heap_segment); + bool new_seg = false; if (!next_seg) { assert (ephemeral_heap_segment == generation_tail_region (generation_of (gen_number))); next_seg = get_new_region (gen_number); + new_seg = true; } if (next_seg) @@ -15916,6 +15950,15 @@ BOOL gc_heap::soh_try_fit (int gen_number, dprintf (REGIONS_LOG, ("eph seg %Ix -> next %Ix", heap_segment_mem (ephemeral_heap_segment), heap_segment_mem (next_seg))); ephemeral_heap_segment = next_seg; + if (new_seg) + { + GCToEEInterface::DiagAddNewRegion( + heap_segment_gen_num (next_seg), + heap_segment_mem (next_seg), + heap_segment_allocated (next_seg), + heap_segment_reserved (next_seg) + ); + } } else { @@ -17462,7 +17505,6 @@ void gc_heap::init_free_and_plug() #else memset (gen->gen_free_spaces, 0, sizeof (gen->gen_free_spaces)); #endif //DOUBLY_LINKED_FL - memset (gen->gen_plugs_allocated_in_free, 0, sizeof (gen->gen_plugs_allocated_in_free)); memset (gen->gen_plugs, 0, sizeof (gen->gen_plugs)); memset (gen->gen_current_pinned_free_spaces, 0, sizeof (gen->gen_current_pinned_free_spaces)); } @@ -17480,7 +17522,7 @@ void gc_heap::init_free_and_plug() void gc_heap::print_free_and_plug (const char* msg) { -#if defined(FREE_USAGE_STATS) && defined(SIMPLE_DPRINTF) +#ifdef FREE_USAGE_STATS int older_gen = ((settings.condemned_generation == max_generation) ? max_generation : (settings.condemned_generation + 1)); for (int i = 0; i <= older_gen; i++) { @@ -17501,7 +17543,7 @@ void gc_heap::print_free_and_plug (const char* msg) } #else UNREFERENCED_PARAMETER(msg); -#endif //FREE_USAGE_STATS && SIMPLE_DPRINTF +#endif //FREE_USAGE_STATS } // replace with allocator::first_suitable_bucket @@ -17573,8 +17615,8 @@ void gc_heap::add_gen_free (int gen_number, size_t free_size) (gen->gen_free_spaces[i])++; if (gen_number == max_generation) { - dprintf (3, ("Mb b%d: f+ %Id (%Id->%Id)", - i, free_size, (gen->gen_free_spaces[i]).num_items, (gen->gen_free_spaces[i]).total_size)); + dprintf (3, ("Mb b%d: f+ %Id (%Id)", + i, free_size, gen->gen_free_spaces[i])); } #else UNREFERENCED_PARAMETER(gen_number); @@ -17596,8 +17638,8 @@ void gc_heap::remove_gen_free (int gen_number, size_t free_size) (gen->gen_free_spaces[i])--; if (gen_number == max_generation) { - dprintf (3, ("Mb b%d: f- %Id (%Id->%Id)", - i, free_size, (gen->gen_free_spaces[i]).num_items, (gen->gen_free_spaces[i]).total_size)); + dprintf (3, ("Mb b%d: f- %Id (%Id)", + i, free_size, gen->gen_free_spaces[i])); } #else UNREFERENCED_PARAMETER(gen_number); @@ -18794,6 +18836,37 @@ int gc_heap::joined_generation_to_condemn (BOOL should_evaluate_elevation, } } + if ((conserve_mem_setting != 0) && (n == max_generation)) + { + float frag_limit = 1.0f - conserve_mem_setting / 10.0f; + + size_t loh_size = get_total_gen_size (loh_generation); + size_t gen2_size = get_total_gen_size (max_generation); + float loh_frag_ratio = 0.0f; + float combined_frag_ratio = 0.0f; + if (loh_size != 0) + { + size_t loh_frag = get_total_gen_fragmentation (loh_generation); + size_t gen2_frag = get_total_gen_fragmentation (max_generation); + loh_frag_ratio = (float)loh_frag / (float)loh_size; + combined_frag_ratio = (float)(gen2_frag + loh_frag) / (float)(gen2_size + loh_size); + } + if (combined_frag_ratio > frag_limit) + { + dprintf (GTC_LOG, ("combined frag: %f > limit %f, loh frag: %f", combined_frag_ratio, frag_limit, loh_frag_ratio)); + gc_data_global.gen_to_condemn_reasons.set_condition (gen_max_high_frag_p); + + n = max_generation; + *blocking_collection_p = TRUE; + if (loh_frag_ratio > frag_limit) + { + settings.loh_compaction = TRUE; + + dprintf (GTC_LOG, ("compacting LOH due to GCConserveMem setting")); + } + } + } + #ifdef BGC_SERVO_TUNING if (bgc_tuning::should_trigger_ngc2()) { @@ -20996,9 +21069,22 @@ bool gc_heap::extend_soh_for_no_gc() } region = heap_segment_next (region); - if ((region == nullptr) && !(region = get_new_region (0))) + if (region == nullptr) { - break; + region = get_new_region (0); + if (region == nullptr) + { + break; + } + else + { + GCToEEInterface::DiagAddNewRegion( + 0, + heap_segment_mem (region), + heap_segment_allocated (region), + heap_segment_reserved (region) + ); + } } } else @@ -23939,6 +24025,21 @@ size_t gc_heap::get_total_gen_estimated_reclaim (int gen_number) return total_estimated_reclaim; } +size_t gc_heap::get_total_gen_size (int gen_number) +{ +#ifdef MULTIPLE_HEAPS + size_t size = 0; + for (int hn = 0; hn < gc_heap::n_heaps; hn++) + { + gc_heap* hp = gc_heap::g_heaps[hn]; + size += hp->generation_size (gen_number); + } +#else + size_t size = generation_size (gen_number); +#endif //MULTIPLE_HEAPS + return size; +} + size_t gc_heap::committed_size() { size_t total_committed = 0; @@ -26100,7 +26201,7 @@ BOOL gc_heap::plan_loh() void gc_heap::compact_loh() { - assert (loh_compaction_requested() || heap_hard_limit); + assert (loh_compaction_requested() || heap_hard_limit || conserve_mem_setting); #ifdef FEATURE_EVENT_TRACE uint64_t start_time, end_time; @@ -27431,7 +27532,7 @@ void gc_heap::plan_phase (int condemned_gen_number) #ifdef DOUBLY_LINKED_FL gen2_removed_no_undo = 0; - saved_pinned_plug_index = 0; + saved_pinned_plug_index = INVALID_SAVED_PINNED_PLUG_INDEX; #endif //DOUBLY_LINKED_FL while (1) @@ -33021,8 +33122,6 @@ void gc_heap::background_mark_phase () #endif //MULTIPLE_HEAPS } - gen0_bricks_cleared = FALSE; - dprintf (2, ("end of bgc mark: loh: %d, poh: %d, soh: %d", generation_size (loh_generation), generation_size (poh_generation), @@ -37881,6 +37980,19 @@ size_t gc_heap::desired_new_allocation (dynamic_data* dd, cst = min (1.0f, float (out) / float (dd_begin_data_size (dd))); f = surv_to_growth (cst, limit, max_limit); + if (conserve_mem_setting != 0) + { + // if this is set, compute a growth factor based on it. + // example: a setting of 6 means we have a goal of 60% live data + // this means we allow 40% fragmentation + // to keep heap size stable, we only use half of that (20%) for new allocation + // f is (live data + new allocation)/(live data), so would be (60% + 20%) / 60% or 1.33 + float f_conserve = ((10.0f / conserve_mem_setting) - 1) * 0.5f + 1.0f; + + // use the smaller one + f = min (f, f_conserve); + } + size_t max_growth_size = (size_t)(max_size / f); if (current_size >= max_growth_size) { @@ -37904,6 +38016,7 @@ size_t gc_heap::desired_new_allocation (dynamic_data* dd, #ifdef BGC_SERVO_TUNING !bgc_tuning::fl_tuning_triggered && #endif //BGC_SERVO_TUNING + (conserve_mem_setting == 0) && (dd_fragmentation (dd) > ((size_t)((f-1)*current_size)))) { //reducing allocation in case of fragmentation @@ -38163,7 +38276,8 @@ size_t gc_heap::trim_youngest_desired (uint32_t memory_load, } else { - return max (mem_one_percent, total_min_allocation); + size_t total_max_allocation = max (mem_one_percent, total_min_allocation); + return min (total_new_allocation, total_max_allocation); } } @@ -38395,7 +38509,7 @@ void gc_heap::decommit_ephemeral_segment_pages() dynamic_data* dd0 = dynamic_data_of (0); - ptrdiff_t desired_allocation = estimate_gen_growth (soh_gen0) + + ptrdiff_t desired_allocation = dd_new_allocation (dd0) + estimate_gen_growth (soh_gen1) + loh_size_threshold; @@ -39326,7 +39440,7 @@ void reset_memory (uint8_t* o, size_t sizeo) size_t size = align_lower_page ((size_t)o + sizeo - size_to_skip - plug_skew) - page_start; // Note we need to compensate for an OS bug here. This bug would cause the MEM_RESET to fail // on write watched memory. - if (reset_mm_p && gc_heap::g_low_memory_status) + if (reset_mm_p && gc_heap::dt_high_memory_load_p()) { #ifdef MULTIPLE_HEAPS bool unlock_p = true; @@ -42941,6 +43055,76 @@ unsigned int GCHeap::WhichGeneration (Object* object) return g; } +unsigned int GCHeap::GetGenerationWithRange (Object* object, uint8_t** ppStart, uint8_t** ppAllocated, uint8_t** ppReserved) +{ + int generation = -1; + heap_segment * hs = gc_heap::find_segment ((uint8_t*)object, FALSE); +#ifdef USE_REGIONS + generation = heap_segment_gen_num (hs); + if (generation == max_generation) + { + if (heap_segment_loh_p (hs)) + { + generation = loh_generation; + } + else if (heap_segment_poh_p (hs)) + { + generation = poh_generation; + } + } + + *ppStart = heap_segment_mem (hs); + *ppAllocated = heap_segment_allocated (hs); + *ppReserved = heap_segment_reserved (hs); +#else +#ifdef MULTIPLE_HEAPS + gc_heap* hp = heap_segment_heap (hs); +#else + gc_heap* hp = __this; +#endif //MULTIPLE_HEAPS + if (hs == hp->ephemeral_heap_segment) + { + uint8_t* reserved = heap_segment_reserved (hs); + uint8_t* end = heap_segment_allocated(hs); + for (int gen = 0; gen < max_generation; gen++) + { + uint8_t* start = generation_allocation_start (hp->generation_of (gen)); + if ((uint8_t*)object >= start) + { + generation = gen; + *ppStart = start; + *ppAllocated = end; + *ppReserved = reserved; + break; + } + end = reserved = start; + } + if (generation == -1) + { + generation = max_generation; + *ppStart = heap_segment_mem (hs); + *ppAllocated = *ppReserved = generation_allocation_start (hp->generation_of (max_generation - 1)); + } + } + else + { + generation = max_generation; + if (heap_segment_loh_p (hs)) + { + generation = loh_generation; + } + else if (heap_segment_poh_p (hs)) + { + generation = poh_generation; + } + *ppStart = heap_segment_mem (hs); + *ppAllocated = heap_segment_allocated (hs); + *ppReserved = heap_segment_reserved (hs); + } +#endif //USE_REGIONS + return (unsigned int)generation; +} + bool GCHeap::IsEphemeral (Object* object) { uint8_t* o = (uint8_t*)object; diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 8a9112ec480849..886ea17743880d 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -133,6 +133,7 @@ class GCConfigStringHolder INT_CONFIG (GCHeapHardLimitLOHPercent, "GCHeapHardLimitLOHPercent", "System.GC.HeapHardLimitLOHPercent", 0, "Specifies the GC heap LOH usage as a percentage of the total memory") \ INT_CONFIG (GCHeapHardLimitPOHPercent, "GCHeapHardLimitPOHPercent", "System.GC.HeapHardLimitPOHPercent", 0, "Specifies the GC heap POH usage as a percentage of the total memory") \ INT_CONFIG (GCEnabledInstructionSets, "GCEnabledInstructionSets", NULL, -1, "Specifies whether GC can use AVX2 or AVX512F - 0 for neither, 1 for AVX2, 3 for AVX512F")\ + INT_CONFIG (GCConserveMem, "GCConserveMemory", NULL, 0, "Specifies how hard GC should try to conserve memory - values 0-9") \ // This class is responsible for retreiving configuration information // for how the GC should operate. diff --git a/src/coreclr/gc/gcenv.ee.standalone.inl b/src/coreclr/gc/gcenv.ee.standalone.inl index c7e4dc4c98b2f0..c2a023fa5c5eb1 100644 --- a/src/coreclr/gc/gcenv.ee.standalone.inl +++ b/src/coreclr/gc/gcenv.ee.standalone.inl @@ -306,4 +306,9 @@ inline uint32_t GCToEEInterface::GetCurrentProcessCpuCount() return g_theGCToCLR->GetCurrentProcessCpuCount(); } +inline void GCToEEInterface::DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) +{ + g_theGCToCLR->DiagAddNewRegion(generation, rangeStart, rangeEnd, rangeEndReserved); +} + #endif // __GCTOENV_EE_STANDALONE_INL__ diff --git a/src/coreclr/gc/gcimpl.h b/src/coreclr/gc/gcimpl.h index 2c21ceada4fe00..5f631642e11c76 100644 --- a/src/coreclr/gc/gcimpl.h +++ b/src/coreclr/gc/gcimpl.h @@ -309,6 +309,7 @@ class GCHeap : public IGCHeapInternal virtual void DiagGetGCSettings(EtwGCSettingsInfo* etw_settings); + virtual unsigned int GetGenerationWithRange(Object* object, uint8_t** ppStart, uint8_t** ppAllocated, uint8_t** ppReserved); public: Object * NextObj (Object * object); diff --git a/src/coreclr/gc/gcinterface.ee.h b/src/coreclr/gc/gcinterface.ee.h index 6525cc653ef635..e2019c8a1adbe6 100644 --- a/src/coreclr/gc/gcinterface.ee.h +++ b/src/coreclr/gc/gcinterface.ee.h @@ -443,6 +443,9 @@ class IGCToCLR { virtual uint32_t GetCurrentProcessCpuCount() = 0; + + virtual + void DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) = 0; }; #endif // _GCINTERFACE_EE_H_ diff --git a/src/coreclr/gc/gcinterface.h b/src/coreclr/gc/gcinterface.h index 920c321da8ebec..d7c08c44d9adce 100644 --- a/src/coreclr/gc/gcinterface.h +++ b/src/coreclr/gc/gcinterface.h @@ -6,7 +6,7 @@ // The major version of the GC/EE interface. Breaking changes to this interface // require bumps in the major version number. -#define GC_INTERFACE_MAJOR_VERSION 4 +#define GC_INTERFACE_MAJOR_VERSION 5 // The minor version of the GC/EE interface. Non-breaking changes are required // to bump the minor version number. GCs and EEs with minor version number @@ -921,6 +921,8 @@ class IGCHeap { // Enables or disables the given keyword or level on the private event provider. virtual void ControlPrivateEvents(GCEventKeyword keyword, GCEventLevel level) = 0; + virtual unsigned int GetGenerationWithRange(Object* object, uint8_t** ppStart, uint8_t** ppAllocated, uint8_t** ppReserved) = 0; + IGCHeap() {} virtual ~IGCHeap() {} }; diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index cda8e68e0a08f8..a04e24c112a48c 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3187,6 +3187,8 @@ class gc_heap PER_HEAP_ISOLATED size_t get_total_gen_estimated_reclaim (int gen_number); PER_HEAP_ISOLATED + size_t get_total_gen_size (int gen_number); + PER_HEAP_ISOLATED void get_memory_info (uint32_t* memory_load, uint64_t* available_physical=NULL, uint64_t* available_page_file=NULL); @@ -4494,6 +4496,8 @@ class gc_heap PER_HEAP size_t gen2_removed_no_undo; +#define INVALID_SAVED_PINNED_PLUG_INDEX ((size_t)~0) + PER_HEAP size_t saved_pinned_plug_index; #endif //DOUBLY_LINKED_FL @@ -4663,6 +4667,9 @@ class gc_heap PER_HEAP_ISOLATED int generation_skip_ratio_threshold; + PER_HEAP_ISOLATED + int conserve_mem_setting; + PER_HEAP BOOL gen0_bricks_cleared; PER_HEAP @@ -4962,6 +4969,9 @@ class gc_heap PER_HEAP_ISOLATED size_t exponential_smoothing (int gen, size_t collection_count, size_t desired_per_heap); + PER_HEAP_ISOLATED + BOOL dt_high_memory_load_p(); + protected: PER_HEAP void update_collection_counts (); diff --git a/src/coreclr/gc/sample/gcenv.ee.cpp b/src/coreclr/gc/sample/gcenv.ee.cpp index 060a5556e21715..84274f2341c3e4 100644 --- a/src/coreclr/gc/sample/gcenv.ee.cpp +++ b/src/coreclr/gc/sample/gcenv.ee.cpp @@ -354,3 +354,7 @@ uint32_t GCToEEInterface::GetCurrentProcessCpuCount() { return GCToOSInterface::GetTotalProcessorCount(); } + +void GCToEEInterface::DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) +{ +} diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 2a37c17f8c9f81..6319c519727e73 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -67,7 +67,6 @@ #include #include -#if defined(HOST_ARM64) #include #include extern "C" @@ -84,7 +83,6 @@ extern "C" abort(); \ } \ } while (false) -#endif // defined(HOST_ARM64) #endif // __APPLE__ @@ -372,7 +370,7 @@ bool GCToOSInterface::Initialize() { s_flushUsingMemBarrier = TRUE; } -#if !(defined(TARGET_OSX) && defined(HOST_ARM64)) +#ifndef TARGET_OSX else { assert(g_helperPage == 0); @@ -404,7 +402,7 @@ bool GCToOSInterface::Initialize() return false; } } -#endif // !(defined(TARGET_OSX) && defined(HOST_ARM64)) +#endif // !TARGET_OSX InitializeCGroup(); @@ -544,7 +542,7 @@ void GCToOSInterface::FlushProcessWriteBuffers() status = pthread_mutex_unlock(&g_flushProcessWriteBuffersMutex); assert(status == 0 && "Failed to unlock the flushProcessWriteBuffersMutex lock"); } -#if defined(TARGET_OSX) && defined(HOST_ARM64) +#ifdef TARGET_OSX else { mach_msg_type_number_t cThreads; @@ -570,7 +568,7 @@ void GCToOSInterface::FlushProcessWriteBuffers() machret = vm_deallocate(mach_task_self(), (vm_address_t)pThreads, cThreads * sizeof(thread_act_t)); CHECK_MACH("vm_deallocate()", machret); } -#endif // defined(TARGET_OSX) && defined(HOST_ARM64) +#endif // TARGET_OSX } // Break into a debugger. Uses a compiler intrinsic if one is available, diff --git a/src/coreclr/ilasm/writer.cpp b/src/coreclr/ilasm/writer.cpp index c7bc6d56d43674..7b5dd8a74f9eea 100644 --- a/src/coreclr/ilasm/writer.cpp +++ b/src/coreclr/ilasm/writer.cpp @@ -212,26 +212,28 @@ HRESULT Assembler::CreateDebugDirectory() param.debugDirData = NULL; // get module ID - DWORD rsds = 0x53445352; - DWORD pdbAge = 0x1; + DWORD rsds = VAL32(0x53445352); + DWORD pdbAge = VAL32(0x1); + GUID pdbGuid = *m_pPortablePdbWriter->GetGuid(); + SwapGuid(&pdbGuid); DWORD len = sizeof(rsds) + sizeof(GUID) + sizeof(pdbAge) + (DWORD)strlen(m_szPdbFileName) + 1; BYTE* dbgDirData = new BYTE[len]; DWORD offset = 0; memcpy_s(dbgDirData + offset, len, &rsds, sizeof(rsds)); // RSDS offset += sizeof(rsds); - memcpy_s(dbgDirData + offset, len, m_pPortablePdbWriter->GetGuid(), sizeof(GUID)); // PDB GUID + memcpy_s(dbgDirData + offset, len, &pdbGuid, sizeof(GUID)); // PDB GUID offset += sizeof(GUID); memcpy_s(dbgDirData + offset, len, &pdbAge, sizeof(pdbAge)); // PDB AGE offset += sizeof(pdbAge); memcpy_s(dbgDirData + offset, len, m_szPdbFileName, strlen(m_szPdbFileName) + 1); // PDB PATH debugDirIDD.Characteristics = 0; - debugDirIDD.TimeDateStamp = m_pPortablePdbWriter->GetTimestamp(); - debugDirIDD.MajorVersion = 0x100; - debugDirIDD.MinorVersion = 0x504d; - debugDirIDD.Type = IMAGE_DEBUG_TYPE_CODEVIEW; - debugDirIDD.SizeOfData = len; + debugDirIDD.TimeDateStamp = VAL32(m_pPortablePdbWriter->GetTimestamp()); + debugDirIDD.MajorVersion = VAL16(0x100); + debugDirIDD.MinorVersion = VAL16(0x504d); + debugDirIDD.Type = VAL32(IMAGE_DEBUG_TYPE_CODEVIEW); + debugDirIDD.SizeOfData = VAL32(len); debugDirIDD.AddressOfRawData = 0; // will be updated bellow debugDirIDD.PointerToRawData = 0; // will be updated bellow diff --git a/src/coreclr/inc/CrstTypes.def b/src/coreclr/inc/CrstTypes.def index c7266df7dbb012..d6fb713a98a1ec 100644 --- a/src/coreclr/inc/CrstTypes.def +++ b/src/coreclr/inc/CrstTypes.def @@ -381,6 +381,7 @@ End // between the thread executing DetachProfiler(), and the DetachThread // carrying out the evacuation order. Crst ProfilingAPIStatus + AcquiredBefore ThreadStore End Crst RCWCache @@ -496,9 +497,8 @@ End Crst ThreadStore AcquiredBefore AvailableParamTypes DeadlockDetection DebuggerController DebuggerHeapLock DebuggerJitInfo DynamicIL ExecuteManRangeLock HandleTable IbcProfile - JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilingAPIStatus - ProfilerGCRefDataFreeList SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList - ThreadIdDispenser DebuggerMutex + JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilerGCRefDataFreeList + SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList ThreadIdDispenser DebuggerMutex End Crst TypeIDMap diff --git a/src/coreclr/inc/cordebug.idl b/src/coreclr/inc/cordebug.idl index 66862c7c2b8b1c..c52ae26781dc90 100644 --- a/src/coreclr/inc/cordebug.idl +++ b/src/coreclr/inc/cordebug.idl @@ -135,6 +135,7 @@ interface ICorDebugThread; interface ICorDebugThread2; interface ICorDebugThread3; interface ICorDebugThread4; +interface ICorDebugThread5; interface ICorDebugStackWalk; interface ICorDebugChain; interface ICorDebugFrame; @@ -4376,6 +4377,26 @@ interface ICorDebugThread4 : IUnknown HRESULT GetCurrentCustomDebuggerNotification([out] ICorDebugValue ** ppNotificationObject); }; +/* + * ICorDebugThread5 is a logical extension to ICorDebugThread. + */ +[ + object, + local, + uuid(F98421C4-E506-4D24-916F-0237EE853EC6), + pointer_default(unique) +] +interface ICorDebugThread5 : IUnknown +{ + /* + * Returns S_OK if it was possible to obtain the allocation information for the thread + * and sets the corresponding SOH and UOH allocations. + * Returns E_INVALIDARG if any of the pointers for the outputs is null. + * Can return E_FAIL if the process is not properly stopped. + */ + HRESULT GetBytesAllocated([out] ULONG64 *pSohAllocatedBytes, [out] ULONG64 *pUohAllocatedBytes); +}; + /* * The new V3.0 stackwalking API. */ diff --git a/src/coreclr/inc/corhlpr.h b/src/coreclr/inc/corhlpr.h index 450514da95c180..427e8cdc0ff5c5 100644 --- a/src/coreclr/inc/corhlpr.h +++ b/src/coreclr/inc/corhlpr.h @@ -336,7 +336,7 @@ struct COR_ILMETHOD_SECT const COR_ILMETHOD_SECT* Next() const { if (!More()) return(0); - return ((COR_ILMETHOD_SECT*)(((BYTE *)this) + DataSize()))->Align(); + return ((COR_ILMETHOD_SECT*)Align(((BYTE *)this) + DataSize())); } const BYTE* Data() const @@ -374,9 +374,9 @@ struct COR_ILMETHOD_SECT return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0); } - const COR_ILMETHOD_SECT* Align() const + static const void* Align(const void* p) { - return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3)); + return((void*) ((((UINT_PTR) p) + 3) & ~3)); } protected: @@ -579,7 +579,7 @@ typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT const COR_ILMETHOD_SECT* GetSect() const { if (!More()) return (0); - return(((COR_ILMETHOD_SECT*) (GetCode() + GetCodeSize()))->Align()); + return(((COR_ILMETHOD_SECT*) COR_ILMETHOD_SECT::Align(GetCode() + GetCodeSize()))); } } COR_ILMETHOD_FAT; diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index d4a22f2ee3e4de..d679c99ce90270 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -484,6 +484,12 @@ class ICorJitInfo : public ICorDynamicInfo uint32_t sizeInBytes /* IN: The size of the buffer. Note that this is effectively a version number for the CORJIT_FLAGS value. */ ) = 0; + + // Checks if a field belongs to a given class. + virtual bool doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, /* IN: the field that we are checking */ + CORINFO_CLASS_HANDLE cls /* IN: the class that we are checking */ + ) = 0; }; /**********************************************************************************/ diff --git a/src/coreclr/inc/crsttypes.h b/src/coreclr/inc/crsttypes.h index 7be482c48bb551..23070d7820d61d 100644 --- a/src/coreclr/inc/crsttypes.h +++ b/src/coreclr/inc/crsttypes.h @@ -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. +// See the LICENSE file in the project root for more information. // #ifndef __CRST_TYPES_INCLUDED @@ -10,7 +11,7 @@ // This file describes the range of Crst types available and their mapping to a numeric level (used by the // runtime in debug mode to validate we're deadlock free). To modify these settings edit the -// file:CrstTypes.def file and run the clr\artifacts\CrstTypeTool utility to generate a new version of this file. +// file:CrstTypes.def file and run the clr\bin\CrstTypeTool utility to generate a new version of this file. // Each Crst type is declared as a value in the following CrstType enum. enum CrstType @@ -230,7 +231,7 @@ int g_rgCrstLevelMap[] = 4, // CrstPgoData 0, // CrstPinnedByrefValidation 0, // CrstProfilerGCRefDataFreeList - 0, // CrstProfilingAPIStatus + 13, // CrstProfilingAPIStatus 4, // CrstRCWCache 0, // CrstRCWCleanupList 10, // CrstReadyToRunEntryPointToMethodDescMap diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index b3b77ece974a87..1c470cf1fdd51d 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -710,6 +710,10 @@ uint32_t getJitFlags( CORJIT_FLAGS* flags, uint32_t sizeInBytes) override; +bool doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, + CORINFO_CLASS_HANDLE cls) override; + /**********************************************************************************/ // clang-format on /**********************************************************************************/ diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index f2d6921bc76cd7..f78582151fc69a 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,12 +43,12 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* c2e4a466-795d-4e64-a776-0ae7b2eed65b */ - 0xc2e4a466, - 0x795d, - 0x4e64, - {0xa7, 0x76, 0x0a, 0xe7, 0xb2, 0xee, 0xd6, 0x5b} - }; +constexpr GUID JITEEVersionIdentifier = { /* 5ed35c58-857b-48dd-a818-7c0136dc9f73 */ + 0x5ed35c58, + 0x857b, + 0x48dd, + {0xa8, 0x18, 0x7c, 0x01, 0x36, 0xdc, 0x9f, 0x73} +}; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // diff --git a/src/coreclr/inc/profilepriv.h b/src/coreclr/inc/profilepriv.h index 4a77b65e8b24df..4bd3801644002b 100644 --- a/src/coreclr/inc/profilepriv.h +++ b/src/coreclr/inc/profilepriv.h @@ -109,16 +109,10 @@ class ProfilerInfo EventMask eventMask; - //--------------------------------------------------------------- - // dwProfilerEvacuationCounter keeps track of how many profiler - // callback calls remain on the stack - //--------------------------------------------------------------- - // Why volatile? - // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. - Volatile dwProfilerEvacuationCounter; - Volatile inUse; + DWORD slot; + // Reset those variables that is only for the current attach session void ResetPerSessionStatus(); void Init(); @@ -150,19 +144,11 @@ class EvacuationCounterHolder { private: ProfilerInfo *m_pProfilerInfo; + Thread *m_pThread; public: - EvacuationCounterHolder(ProfilerInfo *pProfilerInfo) : - m_pProfilerInfo(pProfilerInfo) - { - _ASSERTE(m_pProfilerInfo != NULL); - InterlockedIncrement((LONG *)(m_pProfilerInfo->dwProfilerEvacuationCounter.GetPointer())); - } - - ~EvacuationCounterHolder() - { - InterlockedDecrement((LONG *)(m_pProfilerInfo->dwProfilerEvacuationCounter.GetPointer())); - } + EvacuationCounterHolder(ProfilerInfo *pProfilerInfo); + ~EvacuationCounterHolder(); }; struct StoredProfilerNode @@ -289,23 +275,26 @@ class ProfControlBlock BOOL IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE); ProfilerInfo *GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE); - template - FORCEINLINE HRESULT DoProfilerCallback(ProfilerCallbackType callbackType, ConditionFunc condition, Data *additionalData, CallbackFunc callback, Args... args) + template + static void DoProfilerCallbackHelper(ProfilerInfo *pProfilerInfo, ConditionFunc condition, CallbackFunc callback, HRESULT *pHR, Args... args) + { + if (condition(pProfilerInfo)) + { + HRESULT innerHR = callback(pProfilerInfo->pProfInterface, args...); + if (FAILED(innerHR)) + { + *pHR = innerHR; + } + } + } + + template + FORCEINLINE HRESULT DoProfilerCallback(ProfilerCallbackType callbackType, ConditionFunc condition, CallbackFunc callback, Args... args) { HRESULT hr = S_OK; IterateProfilers(callbackType, - [](ProfilerInfo *pProfilerInfo, ConditionFunc condition, Data *additionalData, CallbackFunc callback, HRESULT *pHR, Args... args) - { - if (condition(pProfilerInfo)) - { - HRESULT innerHR = callback(additionalData, pProfilerInfo->pProfInterface, args...); - if (FAILED(innerHR)) - { - *pHR = innerHR; - } - } - }, - condition, additionalData, callback, &hr, args...); + &DoProfilerCallbackHelper, + condition, callback, &hr, args...); return hr; } @@ -317,7 +306,6 @@ class ProfControlBlock BOOL IsCallback3Supported(); BOOL IsCallback5Supported(); - BOOL IsDisableTransparencySet(); BOOL RequiresGenericsContextForEnterLeave(); UINT_PTR EEFunctionIDMapper(FunctionID funcId, BOOL * pbHookFunction); diff --git a/src/coreclr/inc/profilepriv.inl b/src/coreclr/inc/profilepriv.inl index cee2dfb36b273d..cd8d7f26b3b774 100644 --- a/src/coreclr/inc/profilepriv.inl +++ b/src/coreclr/inc/profilepriv.inl @@ -84,23 +84,24 @@ inline void ProfilerInfo::ResetPerSessionStatus() inline void ProfilerInfo::Init() { curProfStatus.Init(); - dwProfilerEvacuationCounter = 0; ResetPerSessionStatus(); inUse = FALSE; } +inline HRESULT AnyProfilerPassesConditionHelper(EEToProfInterfaceImpl *profInterface, BOOL *pAnyPassed) +{ + *pAnyPassed = TRUE; + return S_OK; +} + template -inline BOOL AnyProfilerPassesCondition(ConditionFunc condition) +FORCEINLINE BOOL AnyProfilerPassesCondition(ConditionFunc condition) { BOOL anyPassed = FALSE; (&g_profControlBlock)->DoProfilerCallback(ProfilerCallbackType::ActiveOrInitializing, - condition, - &anyPassed, - [](BOOL *pAnyPassed, VolatilePtr profInterface) - { - *pAnyPassed = TRUE; - return S_OK; - }); + condition, + &AnyProfilerPassesConditionHelper, + &anyPassed); return anyPassed; } @@ -120,10 +121,13 @@ inline void ProfControlBlock::Init() CONTRACTL_END; mainProfilerInfo.Init(); + // Special magic value for the main one + mainProfilerInfo.slot = MAX_NOTIFICATION_PROFILERS; for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) { notificationOnlyProfilers[i].Init(); + notificationOnlyProfilers[i].slot = (DWORD)i; } globalEventMask.SetEventMask(COR_PRF_MONITOR_NONE); @@ -165,17 +169,19 @@ inline BOOL ProfControlBlock::IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE) return pProfInterface != NULL && pProfInterface->m_pProfToEE == pProfToEE; } +inline void GetProfilerInfoHelper(ProfilerInfo *pProfilerInfo, ProfToEEInterfaceImpl *pProfToEE, ProfilerInfo **ppFoundProfilerInfo) +{ + if (pProfilerInfo->pProfInterface->GetProfToEE() == pProfToEE) + { + *ppFoundProfilerInfo = pProfilerInfo; + } +} + inline ProfilerInfo *ProfControlBlock::GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE) { ProfilerInfo *pProfilerInfo = NULL; IterateProfilers(ProfilerCallbackType::ActiveOrInitializing, - [](ProfilerInfo *pProfilerInfo, ProfToEEInterfaceImpl *pProfToEE, ProfilerInfo **ppFoundProfilerInfo) - { - if (pProfilerInfo->pProfInterface->m_pProfToEE == pProfToEE) - { - *ppFoundProfilerInfo = pProfilerInfo; - } - }, + &GetProfilerInfoHelper, pProfToEE, &pProfilerInfo); @@ -203,6 +209,16 @@ inline void ProfControlBlock::DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo InterlockedDecrement(notificationProfilerCount.GetPointer()); } +inline void UpdateGlobalEventMaskHelper(ProfilerInfo *pProfilerInfo, DWORD *pEventMask) +{ + *pEventMask |= pProfilerInfo->eventMask.GetEventMask(); +} + +inline void UpdateGlobalEventMaskHighHelper(ProfilerInfo *pProfilerInfo, DWORD *pEventMaskHigh) +{ + *pEventMaskHigh |= pProfilerInfo->eventMask.GetEventMaskHigh(); +} + inline void ProfControlBlock::UpdateGlobalEventMask() { while (true) @@ -227,53 +243,57 @@ inline void ProfControlBlock::UpdateGlobalEventMask() } #endif // DACCESS_COMPILE -inline BOOL ProfControlBlock::IsCallback3Supported() +inline BOOL IsCallback3SupportedHelper(ProfilerInfo *pProfilerInfo) { - return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback3Supported(); }); + return pProfilerInfo->pProfInterface->IsCallback3Supported(); } -inline BOOL ProfControlBlock::IsCallback5Supported() +FORCEINLINE BOOL ProfControlBlock::IsCallback3Supported() { - return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback5Supported(); }); + return AnyProfilerPassesCondition(&IsCallback3SupportedHelper); } -inline BOOL ProfControlBlock::IsDisableTransparencySet() +inline BOOL IsCallback5SupportedHelper(ProfilerInfo *pProfilerInfo) { - return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST); }); + return pProfilerInfo->pProfInterface->IsCallback5Supported(); } -inline BOOL ProfControlBlock::RequiresGenericsContextForEnterLeave() +FORCEINLINE BOOL ProfControlBlock::IsCallback5Supported() { - return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->RequiresGenericsContextForEnterLeave(); }); + return AnyProfilerPassesCondition(&IsCallback5SupportedHelper); } -inline bool DoesProfilerWantEEFunctionIDMapper(ProfilerInfo *pProfilerInfo) +inline BOOL RequiresGenericsContextForEnterLeaveHelper(ProfilerInfo *pProfilerInfo) { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + return pProfilerInfo->pProfInterface->RequiresGenericsContextForEnterLeave(); +} +FORCEINLINE BOOL ProfControlBlock::RequiresGenericsContextForEnterLeave() +{ + return AnyProfilerPassesCondition(&RequiresGenericsContextForEnterLeaveHelper); +} + +inline bool DoesProfilerWantEEFunctionIDMapper(ProfilerInfo *pProfilerInfo) +{ return ((pProfilerInfo->pProfInterface->GetFunctionIDMapper() != NULL) || (pProfilerInfo->pProfInterface->GetFunctionIDMapper2() != NULL)); } +inline void EEFunctionIDMapperHelper(ProfilerInfo *pProfilerInfo, FunctionID funcId, BOOL *pbHookFunction, UINT_PTR *pPtr) +{ + if (DoesProfilerWantEEFunctionIDMapper(pProfilerInfo)) + { + *pPtr = pProfilerInfo->pProfInterface->EEFunctionIDMapper(funcId, pbHookFunction); + } +} + inline UINT_PTR ProfControlBlock::EEFunctionIDMapper(FunctionID funcId, BOOL *pbHookFunction) { LIMITED_METHOD_CONTRACT; UINT_PTR ptr = NULL; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, - [](ProfilerInfo *pProfilerInfo, FunctionID funcId, BOOL *pbHookFunction, UINT_PTR *pPtr) - { - if (DoesProfilerWantEEFunctionIDMapper(pProfilerInfo)) - { - *pPtr = pProfilerInfo->pProfInterface->EEFunctionIDMapper(funcId, pbHookFunction); - } - }, + &EEFunctionIDMapperHelper, funcId, pbHookFunction, &ptr); return ptr; @@ -292,18 +312,24 @@ inline BOOL IsProfilerTrackingThreads(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS); } +inline HRESULT ThreadCreatedHelper(EEToProfInterfaceImpl *profInterface, ThreadID threadID) +{ + return profInterface->ThreadCreated(threadID); +} + inline void ProfControlBlock::ThreadCreated(ThreadID threadID) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ThreadID threadID) - { - return profInterface->ThreadCreated(threadID); - }, - threadID); + &ThreadCreatedHelper, + threadID); +} + +inline HRESULT ThreadDestroyedHelper(EEToProfInterfaceImpl *profInterface, ThreadID threadID) +{ + return profInterface->ThreadDestroyed(threadID); } inline void ProfControlBlock::ThreadDestroyed(ThreadID threadID) @@ -312,12 +338,13 @@ inline void ProfControlBlock::ThreadDestroyed(ThreadID threadID) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ThreadID threadID) - { - return profInterface->ThreadDestroyed(threadID); - }, - threadID); + &ThreadDestroyedHelper, + threadID); +} + +inline HRESULT ThreadAssignedToOSThreadHelper(EEToProfInterfaceImpl *profInterface, ThreadID managedThreadId, DWORD osThreadId) +{ + return profInterface->ThreadAssignedToOSThread(managedThreadId, osThreadId); } inline void ProfControlBlock::ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId) @@ -326,12 +353,13 @@ inline void ProfControlBlock::ThreadAssignedToOSThread(ThreadID managedThreadId, DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ThreadID managedThreadId, DWORD osThreadId) - { - return profInterface->ThreadAssignedToOSThread(managedThreadId, osThreadId); - }, - managedThreadId, osThreadId); + &ThreadAssignedToOSThreadHelper, + managedThreadId, osThreadId); +} + +inline HRESULT ThreadNameChangedHelper(EEToProfInterfaceImpl *profInterface, ThreadID managedThreadId, ULONG cchName, WCHAR name[]) +{ + return profInterface->ThreadNameChanged(managedThreadId, cchName, name); } inline void ProfControlBlock::ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[]) @@ -340,12 +368,13 @@ inline void ProfControlBlock::ThreadNameChanged(ThreadID managedThreadId, ULONG DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ThreadID managedThreadId, ULONG cchName, WCHAR name[]) - { - return profInterface->ThreadNameChanged(managedThreadId, cchName, name); - }, - managedThreadId, cchName, name); + &ThreadNameChangedHelper, + managedThreadId, cchName, name); +} + +inline HRESULT ShutdownHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->Shutdown(); } inline void ProfControlBlock::Shutdown() @@ -354,11 +383,7 @@ inline void ProfControlBlock::Shutdown() DoProfilerCallback(ProfilerCallbackType::Active, [](ProfilerInfo *pProfilerInfo) { return true; }, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->Shutdown(); - }); + &ShutdownHelper); } inline BOOL IsProfilerTrackingJITInfo(ProfilerInfo *pProfilerInfo) @@ -374,18 +399,24 @@ inline BOOL IsProfilerTrackingJITInfo(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION); } +inline HRESULT JITCompilationFinishedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) +{ + return profInterface->JITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); +} + inline void ProfControlBlock::JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) - { - return profInterface->JITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); - }, - functionId, hrStatus, fIsSafeToBlock); + &JITCompilationFinishedHelper, + functionId, hrStatus, fIsSafeToBlock); +} + +inline HRESULT JITCompilationStartedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, BOOL fIsSafeToBlock) +{ + return profInterface->JITCompilationStarted(functionId, fIsSafeToBlock); } inline void ProfControlBlock::JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock) @@ -394,12 +425,13 @@ inline void ProfControlBlock::JITCompilationStarted(FunctionID functionId, BOOL DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, BOOL fIsSafeToBlock) - { - return profInterface->JITCompilationStarted(functionId, fIsSafeToBlock); - }, - functionId, fIsSafeToBlock); + &JITCompilationStartedHelper, + functionId, fIsSafeToBlock); +} + +inline HRESULT DynamicMethodJITCompilationStartedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) +{ + return profInterface->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader); } inline void ProfControlBlock::DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) @@ -408,12 +440,13 @@ inline void ProfControlBlock::DynamicMethodJITCompilationStarted(FunctionID func DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) - { - return profInterface->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader); - }, - functionId, fIsSafeToBlock, pILHeader, cbILHeader); + &DynamicMethodJITCompilationStartedHelper, + functionId, fIsSafeToBlock, pILHeader, cbILHeader); +} + +inline HRESULT DynamicMethodJITCompilationFinishedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) +{ + return profInterface->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); } inline void ProfControlBlock::DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) @@ -422,12 +455,8 @@ inline void ProfControlBlock::DynamicMethodJITCompilationFinished(FunctionID fun DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) - { - return profInterface->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); - }, - functionId, hrStatus, fIsSafeToBlock); + &DynamicMethodJITCompilationFinishedHelper, + functionId, hrStatus, fIsSafeToBlock); } inline BOOL IsProfilerMonitoringDynamicFunctionUnloads(ProfilerInfo *pProfilerInfo) @@ -443,18 +472,19 @@ inline BOOL IsProfilerMonitoringDynamicFunctionUnloads(ProfilerInfo *pProfilerIn return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS); } +inline HRESULT DynamicMethodUnloadedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) +{ + return profInterface->DynamicMethodUnloaded(functionId); +} + inline void ProfControlBlock::DynamicMethodUnloaded(FunctionID functionId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerMonitoringDynamicFunctionUnloads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId) - { - return profInterface->DynamicMethodUnloaded(functionId); - }, - functionId); + &DynamicMethodUnloadedHelper, + functionId); } inline BOOL IsProfilerTrackingCacheSearches(ProfilerInfo *pProfilerInfo) @@ -470,6 +500,14 @@ inline BOOL IsProfilerTrackingCacheSearches(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES); } +inline HRESULT JITCachedFunctionSearchStartedHelper(EEToProfInterfaceImpl *profInterface, BOOL *pAllTrue, FunctionID functionId) +{ + BOOL fUseCachedFunction = TRUE; + HRESULT hr = profInterface->JITCachedFunctionSearchStarted(functionId, &fUseCachedFunction); + *pAllTrue = *pAllTrue && fUseCachedFunction; + return hr; +} + inline void ProfControlBlock::JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction) { LIMITED_METHOD_CONTRACT; @@ -477,48 +515,46 @@ inline void ProfControlBlock::JITCachedFunctionSearchStarted(FunctionID function BOOL allTrue = TRUE; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingCacheSearches, - &allTrue, - [](BOOL *pAllTrue, VolatilePtr profInterface, FunctionID functionId, BOOL *pbUseCachedFunction) - { - HRESULT hr = profInterface->JITCachedFunctionSearchStarted(functionId, pbUseCachedFunction); - *pAllTrue &= *pbUseCachedFunction; - return hr; - }, - functionId, pbUseCachedFunction); + &JITCachedFunctionSearchStartedHelper, + &allTrue, functionId); // If any reject it, consider it rejected. *pbUseCachedFunction = allTrue; } +inline HRESULT JITCachedFunctionSearchFinishedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, COR_PRF_JIT_CACHE result) +{ + return profInterface->JITCachedFunctionSearchFinished(functionId, result); +} + inline void ProfControlBlock::JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingCacheSearches, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, COR_PRF_JIT_CACHE result) - { - return profInterface->JITCachedFunctionSearchFinished(functionId, result); - }, - functionId, result); + &JITCachedFunctionSearchFinishedHelper, + functionId, result); +} + +inline HRESULT JITInliningHelper(EEToProfInterfaceImpl *profInterface, BOOL *pAllTrue, FunctionID callerId, FunctionID calleeId) +{ + BOOL fShouldInline = TRUE; + HRESULT hr = profInterface->JITInlining(callerId, calleeId, &fShouldInline); + *pAllTrue = *pAllTrue && fShouldInline; + return hr; } inline HRESULT ProfControlBlock::JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline) { LIMITED_METHOD_CONTRACT; + *pfShouldInline = TRUE; BOOL allTrue = TRUE; HRESULT hr = DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, - &allTrue, - [](BOOL *pAllTrue, VolatilePtr profInterface, FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline) - { - HRESULT hr = profInterface->JITInlining(callerId, calleeId, pfShouldInline); - *pAllTrue &= *pfShouldInline; - return hr; - }, - callerId, calleeId, pfShouldInline); + &JITInliningHelper, + &allTrue, callerId, calleeId); // If any reject it, consider it rejected. *pfShouldInline = allTrue; @@ -530,65 +566,73 @@ inline BOOL IsRejitEnabled(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT); } +inline void ReJITCompilationStartedHelper(ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) +{ + if (IsRejitEnabled(pProfilerInfo)) + { + pProfilerInfo->pProfInterface->ReJITCompilationStarted(functionId, reJitId, fIsSafeToBlock); + } +} + inline void ProfControlBlock::ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, - [](ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) - { - if (IsRejitEnabled(pProfilerInfo)) - { - pProfilerInfo->pProfInterface->ReJITCompilationStarted(functionId, reJitId, fIsSafeToBlock); - } - }, + &ReJITCompilationStartedHelper, functionId, reJitId, fIsSafeToBlock); } +inline void GetReJITParametersHelper(ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl, HRESULT *pHr) +{ + if (IsRejitEnabled(pProfilerInfo)) + { + *pHr = pProfilerInfo->pProfInterface->GetReJITParameters(moduleId, methodId, pFunctionControl); + } +} + inline HRESULT ProfControlBlock::GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl) { LIMITED_METHOD_CONTRACT; HRESULT hr = S_OK; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, - [](ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl, HRESULT *pHr) - { - if (IsRejitEnabled(pProfilerInfo)) - { - *pHr = pProfilerInfo->pProfInterface->GetReJITParameters(moduleId, methodId, pFunctionControl); - } - }, + &GetReJITParametersHelper, moduleId, methodId, pFunctionControl, &hr); return hr; } +inline void ReJITCompilationFinishedHelper(ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) +{ + if (IsRejitEnabled(pProfilerInfo)) + { + pProfilerInfo->pProfInterface->ReJITCompilationFinished(functionId, reJitId, hrStatus, fIsSafeToBlock); + } +} + inline void ProfControlBlock::ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, - [](ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) - { - if (IsRejitEnabled(pProfilerInfo)) - { - pProfilerInfo->pProfInterface->ReJITCompilationFinished(functionId, reJitId, hrStatus, fIsSafeToBlock); - } - }, + &ReJITCompilationFinishedHelper, functionId, reJitId, hrStatus, fIsSafeToBlock); } +inline void ReJITErrorHelper(ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) +{ + if (IsRejitEnabled(pProfilerInfo)) + { + pProfilerInfo->pProfInterface->ReJITError(moduleId, methodId, functionId, hrStatus); + } +} + inline void ProfControlBlock::ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, - [](ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) - { - if (IsRejitEnabled(pProfilerInfo)) - { - pProfilerInfo->pProfInterface->ReJITError(moduleId, methodId, functionId, hrStatus); - } - }, + &ReJITErrorHelper, moduleId, methodId, functionId, hrStatus); } @@ -605,18 +649,24 @@ inline BOOL IsProfilerTrackingModuleLoads(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS); } +inline HRESULT ModuleLoadStartedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId) +{ + return profInterface->ModuleLoadStarted(moduleId); +} + inline void ProfControlBlock::ModuleLoadStarted(ModuleID moduleId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ModuleID moduleId) - { - return profInterface->ModuleLoadStarted(moduleId); - }, - moduleId); + &ModuleLoadStartedHelper, + moduleId); +} + +inline HRESULT ModuleLoadFinishedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId, HRESULT hrStatus) +{ + return profInterface->ModuleLoadFinished(moduleId, hrStatus); } inline void ProfControlBlock::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) @@ -625,12 +675,13 @@ inline void ProfControlBlock::ModuleLoadFinished(ModuleID moduleId, HRESULT hrSt DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ModuleID moduleId, HRESULT hrStatus) - { - return profInterface->ModuleLoadFinished(moduleId, hrStatus); - }, - moduleId, hrStatus); + &ModuleLoadFinishedHelper, + moduleId, hrStatus); +} + +inline HRESULT ModuleUnloadStartedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId) +{ + return profInterface->ModuleUnloadStarted(moduleId); } inline void ProfControlBlock::ModuleUnloadStarted(ModuleID moduleId) @@ -639,12 +690,13 @@ inline void ProfControlBlock::ModuleUnloadStarted(ModuleID moduleId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ModuleID moduleId) - { - return profInterface->ModuleUnloadStarted(moduleId); - }, - moduleId); + &ModuleUnloadStartedHelper, + moduleId); +} + +inline HRESULT ModuleUnloadFinishedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId, HRESULT hrStatus) +{ + return profInterface->ModuleUnloadFinished(moduleId, hrStatus); } inline void ProfControlBlock::ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) @@ -653,12 +705,13 @@ inline void ProfControlBlock::ModuleUnloadFinished(ModuleID moduleId, HRESULT hr DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ModuleID moduleId, HRESULT hrStatus) - { - return profInterface->ModuleUnloadFinished(moduleId, hrStatus); - }, - moduleId, hrStatus); + &ModuleUnloadFinishedHelper, + moduleId, hrStatus); +} + +inline HRESULT ModuleAttachedToAssemblyHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId, AssemblyID AssemblyId) +{ + return profInterface->ModuleAttachedToAssembly(moduleId, AssemblyId); } inline void ProfControlBlock::ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) @@ -667,12 +720,8 @@ inline void ProfControlBlock::ModuleAttachedToAssembly(ModuleID moduleId, Assemb DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ModuleID moduleId, AssemblyID AssemblyId) - { - return profInterface->ModuleAttachedToAssembly(moduleId, AssemblyId); - }, - moduleId, AssemblyId); + &ModuleAttachedToAssemblyHelper, + moduleId, AssemblyId); } inline BOOL IsProfilerTrackingInMemorySymbolsUpdatesEnabled(ProfilerInfo *pProfilerInfo) @@ -688,18 +737,19 @@ inline BOOL IsProfilerTrackingInMemorySymbolsUpdatesEnabled(ProfilerInfo *pProfi return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED); } +inline HRESULT ModuleInMemorySymbolsUpdatedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId) +{ + return profInterface->ModuleInMemorySymbolsUpdated(moduleId); +} + inline void ProfControlBlock::ModuleInMemorySymbolsUpdated(ModuleID moduleId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingInMemorySymbolsUpdatesEnabled, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ModuleID moduleId) - { - return profInterface->ModuleInMemorySymbolsUpdated(moduleId); - }, - moduleId); + &ModuleInMemorySymbolsUpdatedHelper, + moduleId); } inline BOOL IsProfilerTrackingClasses(ProfilerInfo *pProfilerInfo) @@ -715,18 +765,24 @@ inline BOOL IsProfilerTrackingClasses(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS); } +inline HRESULT ClassLoadStartedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId) +{ + return profInterface->ClassLoadStarted(classId); +} + inline void ProfControlBlock::ClassLoadStarted(ClassID classId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ClassID classId) - { - return profInterface->ClassLoadStarted(classId); - }, - classId); + &ClassLoadStartedHelper, + classId); +} + +inline HRESULT ClassLoadFinishedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId, HRESULT hrStatus) +{ + return profInterface->ClassLoadFinished(classId, hrStatus); } inline void ProfControlBlock::ClassLoadFinished(ClassID classId, HRESULT hrStatus) @@ -735,12 +791,13 @@ inline void ProfControlBlock::ClassLoadFinished(ClassID classId, HRESULT hrStatu DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ClassID classId, HRESULT hrStatus) - { - return profInterface->ClassLoadFinished(classId, hrStatus); - }, - classId, hrStatus); + &ClassLoadFinishedHelper, + classId, hrStatus); +} + +inline HRESULT ClassUnloadStartedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId) +{ + return profInterface->ClassUnloadStarted(classId); } inline void ProfControlBlock::ClassUnloadStarted(ClassID classId) @@ -749,12 +806,13 @@ inline void ProfControlBlock::ClassUnloadStarted(ClassID classId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ClassID classId) - { - return profInterface->ClassUnloadStarted(classId); - }, - classId); + &ClassUnloadStartedHelper, + classId); +} + +inline HRESULT ClassUnloadFinishedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId, HRESULT hrStatus) +{ + return profInterface->ClassUnloadFinished(classId, hrStatus); } inline void ProfControlBlock::ClassUnloadFinished(ClassID classId, HRESULT hrStatus) @@ -763,12 +821,8 @@ inline void ProfControlBlock::ClassUnloadFinished(ClassID classId, HRESULT hrSta DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ClassID classId, HRESULT hrStatus) - { - return profInterface->ClassUnloadFinished(classId, hrStatus); - }, - classId, hrStatus); + &ClassUnloadFinishedHelper, + classId, hrStatus); } inline BOOL IsProfilerTrackingAppDomainLoads(ProfilerInfo *pProfilerInfo) @@ -784,18 +838,24 @@ inline BOOL IsProfilerTrackingAppDomainLoads(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS); } +inline HRESULT AppDomainCreationStartedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId) +{ + return profInterface->AppDomainCreationStarted(appDomainId); +} + inline void ProfControlBlock::AppDomainCreationStarted(AppDomainID appDomainId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AppDomainID appDomainId) - { - return profInterface->AppDomainCreationStarted(appDomainId); - }, - appDomainId); + &AppDomainCreationStartedHelper, + appDomainId); +} + +inline HRESULT AppDomainCreationFinishedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId, HRESULT hrStatus) +{ + return profInterface->AppDomainCreationFinished(appDomainId, hrStatus); } inline void ProfControlBlock::AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) @@ -804,12 +864,13 @@ inline void ProfControlBlock::AppDomainCreationFinished(AppDomainID appDomainId, DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AppDomainID appDomainId, HRESULT hrStatus) - { - return profInterface->AppDomainCreationFinished(appDomainId, hrStatus); - }, - appDomainId, hrStatus); + &AppDomainCreationFinishedHelper, + appDomainId, hrStatus); +} + +inline HRESULT AppDomainShutdownStartedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId) +{ + return profInterface->AppDomainShutdownStarted(appDomainId); } inline void ProfControlBlock::AppDomainShutdownStarted(AppDomainID appDomainId) @@ -818,12 +879,13 @@ inline void ProfControlBlock::AppDomainShutdownStarted(AppDomainID appDomainId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AppDomainID appDomainId) - { - return profInterface->AppDomainShutdownStarted(appDomainId); - }, - appDomainId); + &AppDomainShutdownStartedHelper, + appDomainId); +} + +inline HRESULT AppDomainShutdownFinishedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId, HRESULT hrStatus) +{ + return profInterface->AppDomainShutdownFinished(appDomainId, hrStatus); } inline void ProfControlBlock::AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) @@ -832,12 +894,8 @@ inline void ProfControlBlock::AppDomainShutdownFinished(AppDomainID appDomainId, DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AppDomainID appDomainId, HRESULT hrStatus) - { - return profInterface->AppDomainShutdownFinished(appDomainId, hrStatus); - }, - appDomainId, hrStatus); + &AppDomainShutdownFinishedHelper, + appDomainId, hrStatus); } inline BOOL IsProfilerTrackingAssemblyLoads(ProfilerInfo *pProfilerInfo) @@ -853,18 +911,24 @@ inline BOOL IsProfilerTrackingAssemblyLoads(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS); } +inline HRESULT AssemblyLoadStartedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId) +{ + return profInterface->AssemblyLoadStarted(assemblyId); +} + inline void ProfControlBlock::AssemblyLoadStarted(AssemblyID assemblyId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AssemblyID assemblyId) - { - return profInterface->AssemblyLoadStarted(assemblyId); - }, - assemblyId); + &AssemblyLoadStartedHelper, + assemblyId); +} + +inline HRESULT AssemblyLoadFinishedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId, HRESULT hrStatus) +{ + return profInterface->AssemblyLoadFinished(assemblyId, hrStatus); } inline void ProfControlBlock::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) @@ -873,12 +937,13 @@ inline void ProfControlBlock::AssemblyLoadFinished(AssemblyID assemblyId, HRESUL DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AssemblyID assemblyId, HRESULT hrStatus) - { - return profInterface->AssemblyLoadFinished(assemblyId, hrStatus); - }, - assemblyId, hrStatus); + &AssemblyLoadFinishedHelper, + assemblyId, hrStatus); +} + +inline HRESULT AssemblyUnloadStartedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId) +{ + return profInterface->AssemblyUnloadStarted(assemblyId); } inline void ProfControlBlock::AssemblyUnloadStarted(AssemblyID assemblyId) @@ -887,12 +952,13 @@ inline void ProfControlBlock::AssemblyUnloadStarted(AssemblyID assemblyId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AssemblyID assemblyId) - { - return profInterface->AssemblyUnloadStarted(assemblyId); - }, - assemblyId); + &AssemblyUnloadStartedHelper, + assemblyId); +} + +inline HRESULT AssemblyUnloadFinishedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId, HRESULT hrStatus) +{ + return profInterface->AssemblyUnloadFinished(assemblyId, hrStatus); } inline void ProfControlBlock::AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus) @@ -901,12 +967,8 @@ inline void ProfControlBlock::AssemblyUnloadFinished(AssemblyID assemblyId, HRES DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, AssemblyID assemblyId, HRESULT hrStatus) - { - return profInterface->AssemblyUnloadFinished(assemblyId, hrStatus); - }, - assemblyId, hrStatus); + &AssemblyUnloadFinishedHelper, + assemblyId, hrStatus); } inline BOOL IsProfilerTrackingTransitions(ProfilerInfo *pProfilerInfo) @@ -922,18 +984,24 @@ inline BOOL IsProfilerTrackingTransitions(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS); } +inline HRESULT UnmanagedToManagedTransitionHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) +{ + return profInterface->UnmanagedToManagedTransition(functionId, reason); +} + inline void ProfControlBlock::UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingTransitions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) - { - return profInterface->UnmanagedToManagedTransition(functionId, reason); - }, - functionId, reason); + &UnmanagedToManagedTransitionHelper, + functionId, reason); +} + +inline HRESULT ManagedToUnmanagedTransitionHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) +{ + return profInterface->ManagedToUnmanagedTransition(functionId, reason); } inline void ProfControlBlock::ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) @@ -942,12 +1010,8 @@ inline void ProfControlBlock::ManagedToUnmanagedTransition(FunctionID functionId DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingTransitions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) - { - return profInterface->ManagedToUnmanagedTransition(functionId, reason); - }, - functionId, reason); + &ManagedToUnmanagedTransitionHelper, + functionId, reason); } inline BOOL IsProfilerTrackingExceptions(ProfilerInfo *pProfilerInfo) @@ -963,18 +1027,24 @@ inline BOOL IsProfilerTrackingExceptions(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS); } +inline HRESULT ExceptionThrownHelper(EEToProfInterfaceImpl *profInterface, ObjectID thrownObjectId) +{ + return profInterface->ExceptionThrown(thrownObjectId); +} + inline void ProfControlBlock::ExceptionThrown(ObjectID thrownObjectId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ObjectID thrownObjectId) - { - return profInterface->ExceptionThrown(thrownObjectId); - }, - thrownObjectId); + &ExceptionThrownHelper, + thrownObjectId); +} + +inline HRESULT ExceptionSearchFunctionEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) +{ + return profInterface->ExceptionSearchFunctionEnter(functionId); } inline void ProfControlBlock::ExceptionSearchFunctionEnter(FunctionID functionId) @@ -983,12 +1053,13 @@ inline void ProfControlBlock::ExceptionSearchFunctionEnter(FunctionID functionId DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId) - { - return profInterface->ExceptionSearchFunctionEnter(functionId); - }, - functionId); + &ExceptionSearchFunctionEnterHelper, + functionId); +} + +inline HRESULT ExceptionSearchFunctionLeaveHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->ExceptionSearchFunctionLeave(); } inline void ProfControlBlock::ExceptionSearchFunctionLeave() @@ -997,11 +1068,12 @@ inline void ProfControlBlock::ExceptionSearchFunctionLeave() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->ExceptionSearchFunctionLeave(); - }); + &ExceptionSearchFunctionLeaveHelper); +} + +inline HRESULT ExceptionSearchFilterEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID funcId) +{ + return profInterface->ExceptionSearchFilterEnter(funcId); } inline void ProfControlBlock::ExceptionSearchFilterEnter(FunctionID funcId) @@ -1010,12 +1082,13 @@ inline void ProfControlBlock::ExceptionSearchFilterEnter(FunctionID funcId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID funcId) - { - return profInterface->ExceptionSearchFilterEnter(funcId); - }, - funcId); + &ExceptionSearchFilterEnterHelper, + funcId); +} + +inline HRESULT ExceptionSearchFilterLeaveHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->ExceptionSearchFilterLeave(); } inline void ProfControlBlock::ExceptionSearchFilterLeave() @@ -1024,11 +1097,12 @@ inline void ProfControlBlock::ExceptionSearchFilterLeave() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->ExceptionSearchFilterLeave(); - }); + &ExceptionSearchFilterLeaveHelper); +} + +inline HRESULT ExceptionSearchCatcherFoundHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) +{ + return profInterface->ExceptionSearchCatcherFound(functionId); } inline void ProfControlBlock::ExceptionSearchCatcherFound(FunctionID functionId) @@ -1037,12 +1111,13 @@ inline void ProfControlBlock::ExceptionSearchCatcherFound(FunctionID functionId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId) - { - return profInterface->ExceptionSearchCatcherFound(functionId); - }, - functionId); + &ExceptionSearchCatcherFoundHelper, + functionId); +} + +inline HRESULT ExceptionOSHandlerEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID funcId) +{ + return profInterface->ExceptionOSHandlerEnter(funcId); } inline void ProfControlBlock::ExceptionOSHandlerEnter(FunctionID funcId) @@ -1051,12 +1126,13 @@ inline void ProfControlBlock::ExceptionOSHandlerEnter(FunctionID funcId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID funcId) - { - return profInterface->ExceptionOSHandlerEnter(funcId); - }, - funcId); + &ExceptionOSHandlerEnterHelper, + funcId); +} + +inline HRESULT ExceptionOSHandlerLeaveHelper(EEToProfInterfaceImpl *profInterface, FunctionID funcId) +{ + return profInterface->ExceptionOSHandlerLeave(funcId); } inline void ProfControlBlock::ExceptionOSHandlerLeave(FunctionID funcId) @@ -1065,12 +1141,13 @@ inline void ProfControlBlock::ExceptionOSHandlerLeave(FunctionID funcId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID funcId) - { - return profInterface->ExceptionOSHandlerLeave(funcId); - }, - funcId); + &ExceptionOSHandlerLeaveHelper, + funcId); +} + +inline HRESULT ExceptionUnwindFunctionEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) +{ + return profInterface->ExceptionUnwindFunctionEnter(functionId); } inline void ProfControlBlock::ExceptionUnwindFunctionEnter(FunctionID functionId) @@ -1079,12 +1156,13 @@ inline void ProfControlBlock::ExceptionUnwindFunctionEnter(FunctionID functionId DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId) - { - return profInterface->ExceptionUnwindFunctionEnter(functionId); - }, - functionId); + &ExceptionUnwindFunctionEnterHelper, + functionId); +} + +inline HRESULT ExceptionUnwindFunctionLeaveHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->ExceptionUnwindFunctionLeave(); } inline void ProfControlBlock::ExceptionUnwindFunctionLeave() @@ -1093,11 +1171,12 @@ inline void ProfControlBlock::ExceptionUnwindFunctionLeave() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->ExceptionUnwindFunctionLeave(); - }); + &ExceptionUnwindFunctionLeaveHelper); +} + +inline HRESULT ExceptionUnwindFinallyEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) +{ + return profInterface->ExceptionUnwindFinallyEnter(functionId); } inline void ProfControlBlock::ExceptionUnwindFinallyEnter(FunctionID functionId) @@ -1106,12 +1185,13 @@ inline void ProfControlBlock::ExceptionUnwindFinallyEnter(FunctionID functionId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId) - { - return profInterface->ExceptionUnwindFinallyEnter(functionId); - }, - functionId); + &ExceptionUnwindFinallyEnterHelper, + functionId); +} + +inline HRESULT ExceptionUnwindFinallyLeaveHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->ExceptionUnwindFinallyLeave(); } inline void ProfControlBlock::ExceptionUnwindFinallyLeave() @@ -1120,11 +1200,12 @@ inline void ProfControlBlock::ExceptionUnwindFinallyLeave() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->ExceptionUnwindFinallyLeave(); - }); + &ExceptionUnwindFinallyLeaveHelper); +} + +inline HRESULT ExceptionCatcherEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, ObjectID objectId) +{ + return profInterface->ExceptionCatcherEnter(functionId, objectId); } inline void ProfControlBlock::ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) @@ -1133,12 +1214,13 @@ inline void ProfControlBlock::ExceptionCatcherEnter(FunctionID functionId, Objec DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, FunctionID functionId, ObjectID objectId) - { - return profInterface->ExceptionCatcherEnter(functionId, objectId); - }, - functionId, objectId); + &ExceptionCatcherEnterHelper, + functionId, objectId); +} + +inline HRESULT ExceptionCatcherLeaveHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->ExceptionCatcherLeave(); } inline void ProfControlBlock::ExceptionCatcherLeave() @@ -1147,11 +1229,7 @@ inline void ProfControlBlock::ExceptionCatcherLeave() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->ExceptionCatcherLeave(); - }); + &ExceptionCatcherLeaveHelper); } inline BOOL IsProfilerTrackingCCW(ProfilerInfo *pProfilerInfo) @@ -1167,18 +1245,19 @@ inline BOOL IsProfilerTrackingCCW(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW); } +inline HRESULT COMClassicVTableCreatedHelper(EEToProfInterfaceImpl *profInterface, ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) +{ + return profInterface->COMClassicVTableCreated(wrappedClassId, implementedIID, pVTable, cSlots); +} + inline void ProfControlBlock::COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingCCW, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) - { - return profInterface->COMClassicVTableCreated(wrappedClassId, implementedIID, pVTable, cSlots); - }, - wrappedClassId, implementedIID, pVTable, cSlots); + &COMClassicVTableCreatedHelper, + wrappedClassId, implementedIID, pVTable, cSlots); } inline BOOL IsProfilerTrackingSuspends(ProfilerInfo *pProfilerInfo) @@ -1194,18 +1273,24 @@ inline BOOL IsProfilerTrackingSuspends(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS); } +inline HRESULT RuntimeSuspendStartedHelper(EEToProfInterfaceImpl *profInterface, COR_PRF_SUSPEND_REASON suspendReason) +{ + return profInterface->RuntimeSuspendStarted(suspendReason); +} + inline void ProfControlBlock::RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, COR_PRF_SUSPEND_REASON suspendReason) - { - return profInterface->RuntimeSuspendStarted(suspendReason); - }, - suspendReason); + &RuntimeSuspendStartedHelper, + suspendReason); +} + +inline HRESULT RuntimeSuspendFinishedHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->RuntimeSuspendFinished(); } inline void ProfControlBlock::RuntimeSuspendFinished() @@ -1214,11 +1299,12 @@ inline void ProfControlBlock::RuntimeSuspendFinished() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->RuntimeSuspendFinished(); - }); + &RuntimeSuspendFinishedHelper); +} + +inline HRESULT RuntimeSuspendAbortedHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->RuntimeSuspendAborted(); } inline void ProfControlBlock::RuntimeSuspendAborted() @@ -1227,11 +1313,12 @@ inline void ProfControlBlock::RuntimeSuspendAborted() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->RuntimeSuspendAborted(); - }); + &RuntimeSuspendAbortedHelper); +} + +inline HRESULT RuntimeResumeStartedHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->RuntimeResumeStarted(); } inline void ProfControlBlock::RuntimeResumeStarted() @@ -1240,11 +1327,12 @@ inline void ProfControlBlock::RuntimeResumeStarted() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->RuntimeResumeStarted(); - }); + &RuntimeResumeStartedHelper); +} + +inline HRESULT RuntimeResumeFinishedHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->RuntimeResumeFinished(); } inline void ProfControlBlock::RuntimeResumeFinished() @@ -1253,11 +1341,12 @@ inline void ProfControlBlock::RuntimeResumeFinished() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->RuntimeResumeFinished(); - }); + &RuntimeResumeFinishedHelper); +} + +inline HRESULT RuntimeThreadSuspendedHelper(EEToProfInterfaceImpl *profInterface, ThreadID suspendedThreadId) +{ + return profInterface->RuntimeThreadSuspended(suspendedThreadId); } inline void ProfControlBlock::RuntimeThreadSuspended(ThreadID suspendedThreadId) @@ -1266,12 +1355,13 @@ inline void ProfControlBlock::RuntimeThreadSuspended(ThreadID suspendedThreadId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ThreadID suspendedThreadId) - { - return profInterface->RuntimeThreadSuspended(suspendedThreadId); - }, - suspendedThreadId); + &RuntimeThreadSuspendedHelper, + suspendedThreadId); +} + +inline HRESULT RuntimeThreadResumedHelper(EEToProfInterfaceImpl *profInterface, ThreadID resumedThreadId) +{ + return profInterface->RuntimeThreadResumed(resumedThreadId); } inline void ProfControlBlock::RuntimeThreadResumed(ThreadID resumedThreadId) @@ -1280,12 +1370,8 @@ inline void ProfControlBlock::RuntimeThreadResumed(ThreadID resumedThreadId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ThreadID resumedThreadId) - { - return profInterface->RuntimeThreadResumed(resumedThreadId); - }, - resumedThreadId); + &RuntimeThreadResumedHelper, + resumedThreadId); } inline BOOL IsProfilerTrackingAllocations(ProfilerInfo *pProfilerInfo) @@ -1302,18 +1388,19 @@ inline BOOL IsProfilerTrackingAllocations(ProfilerInfo *pProfilerInfo) || pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); } +inline HRESULT ObjectAllocatedHelper(EEToProfInterfaceImpl *profInterface, ObjectID objectId, ClassID classId) +{ + return profInterface->ObjectAllocated(objectId, classId); +} + inline void ProfControlBlock::ObjectAllocated(ObjectID objectId, ClassID classId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAllocations, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ObjectID objectId, ClassID classId) - { - return profInterface->ObjectAllocated(objectId, classId); - }, - objectId, classId); + &ObjectAllocatedHelper, + objectId, classId); } @@ -1330,18 +1417,24 @@ inline BOOL IsProfilerTrackingGC(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_GC); } +inline HRESULT FinalizeableObjectQueuedHelper(EEToProfInterfaceImpl *profInterface, BOOL isCritical, ObjectID objectID) +{ + return profInterface->FinalizeableObjectQueued(isCritical, objectID); +} + inline void ProfControlBlock::FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, BOOL isCritical, ObjectID objectID) - { - return profInterface->FinalizeableObjectQueued(isCritical, objectID); - }, - isCritical, objectID); + &FinalizeableObjectQueuedHelper, + isCritical, objectID); +} + +inline HRESULT MovedReferenceHelper(EEToProfInterfaceImpl *profInterface, BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) +{ + return profInterface->MovedReference(pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); } inline void ProfControlBlock::MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) @@ -1350,12 +1443,13 @@ inline void ProfControlBlock::MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemB DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) - { - return profInterface->MovedReference(pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); - }, - pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); + &MovedReferenceHelper, + pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); +} + +inline HRESULT EndMovedReferencesHelper(EEToProfInterfaceImpl *profInterface, void *pHeapId) +{ + return profInterface->EndMovedReferences(pHeapId); } inline void ProfControlBlock::EndMovedReferences(void *pHeapId) @@ -1364,12 +1458,13 @@ inline void ProfControlBlock::EndMovedReferences(void *pHeapId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, void *pHeapId) - { - return profInterface->EndMovedReferences(pHeapId); - }, - pHeapId); + &EndMovedReferencesHelper, + pHeapId); +} + +inline HRESULT RootReference2Helper(EEToProfInterfaceImpl *profInterface, BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) +{ + return profInterface->RootReference2(objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); } inline void ProfControlBlock::RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) @@ -1378,12 +1473,13 @@ inline void ProfControlBlock::RootReference2(BYTE *objectId, EtwGCRootKind dwEtw DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) - { - return profInterface->RootReference2(objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); - }, - objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); + &RootReference2Helper, + objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); +} + +inline HRESULT EndRootReferences2Helper(EEToProfInterfaceImpl *profInterface, void *pHeapId) +{ + return profInterface->EndRootReferences2(pHeapId); } inline void ProfControlBlock::EndRootReferences2(void *pHeapId) @@ -1392,50 +1488,53 @@ inline void ProfControlBlock::EndRootReferences2(void *pHeapId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, void *pHeapId) - { - return profInterface->EndRootReferences2(pHeapId); - }, - pHeapId); + &EndRootReferences2Helper, + pHeapId); } -inline void ProfControlBlock::ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) +inline HRESULT ConditionalWeakTableElementReferenceHelper(EEToProfInterfaceImpl *profInterface, BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) { - LIMITED_METHOD_CONTRACT; - - DoProfilerCallback(ProfilerCallbackType::Active, - IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) - { - if (!profInterface->IsCallback5Supported()) - { - return S_OK; - } + if (!profInterface->IsCallback5Supported()) + { + return S_OK; + } - return profInterface->ConditionalWeakTableElementReference(primaryObjectId, secondaryObjectId, rootID, pHeapId); - }, - primaryObjectId, secondaryObjectId, rootID, pHeapId); + return profInterface->ConditionalWeakTableElementReference(primaryObjectId, secondaryObjectId, rootID, pHeapId); } -inline void ProfControlBlock::EndConditionalWeakTableElementReferences(void *pHeapId) +inline void ProfControlBlock::ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, void *pHeapId) - { - if (!profInterface->IsCallback5Supported()) - { - return S_OK; - } + &ConditionalWeakTableElementReferenceHelper, + primaryObjectId, secondaryObjectId, rootID, pHeapId); +} + +inline HRESULT EndConditionalWeakTableElementReferencesHelper(EEToProfInterfaceImpl *profInterface, void *pHeapId) +{ + if (!profInterface->IsCallback5Supported()) + { + return S_OK; + } + + return profInterface->EndConditionalWeakTableElementReferences(pHeapId); +} + +inline void ProfControlBlock::EndConditionalWeakTableElementReferences(void *pHeapId) +{ + LIMITED_METHOD_CONTRACT; + + DoProfilerCallback(ProfilerCallbackType::Active, + IsProfilerTrackingGC, + &EndConditionalWeakTableElementReferencesHelper, + pHeapId); +} - return profInterface->EndConditionalWeakTableElementReferences(pHeapId); - }, - pHeapId); +inline HRESULT AllocByClassHelper(EEToProfInterfaceImpl *profInterface, ObjectID objId, ClassID classId, void *pHeapId) +{ + return profInterface->AllocByClass(objId, classId, pHeapId); } inline void ProfControlBlock::AllocByClass(ObjectID objId, ClassID classId, void *pHeapId) @@ -1444,12 +1543,13 @@ inline void ProfControlBlock::AllocByClass(ObjectID objId, ClassID classId, void DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ObjectID objId, ClassID classId, void *pHeapId) - { - return profInterface->AllocByClass(objId, classId, pHeapId); - }, - objId, classId, pHeapId); + &AllocByClassHelper, + objId, classId, pHeapId); +} + +inline HRESULT EndAllocByClassHelper(EEToProfInterfaceImpl *profInterface, void *pHeapId) +{ + return profInterface->EndAllocByClass(pHeapId); } inline void ProfControlBlock::EndAllocByClass(void *pHeapId) @@ -1458,12 +1558,13 @@ inline void ProfControlBlock::EndAllocByClass(void *pHeapId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, void *pHeapId) - { - return profInterface->EndAllocByClass(pHeapId); - }, - pHeapId); + &EndAllocByClassHelper, + pHeapId); +} + +inline HRESULT ObjectReferenceHelper(EEToProfInterfaceImpl *profInterface, ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) +{ + return profInterface->ObjectReference(objId, classId, cNumRefs, arrObjRef); } inline HRESULT ProfControlBlock::ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) @@ -1472,12 +1573,13 @@ inline HRESULT ProfControlBlock::ObjectReference(ObjectID objId, ClassID classId return DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) - { - return profInterface->ObjectReference(objId, classId, cNumRefs, arrObjRef); - }, - objId, classId, cNumRefs, arrObjRef); + &ObjectReferenceHelper, + objId, classId, cNumRefs, arrObjRef); +} + +inline HRESULT HandleCreatedHelper(EEToProfInterfaceImpl *profInterface, UINT_PTR handleId, ObjectID initialObjectId) +{ + return profInterface->HandleCreated(handleId, initialObjectId); } inline void ProfControlBlock::HandleCreated(UINT_PTR handleId, ObjectID initialObjectId) @@ -1486,12 +1588,13 @@ inline void ProfControlBlock::HandleCreated(UINT_PTR handleId, ObjectID initialO DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, UINT_PTR handleId, ObjectID initialObjectId) - { - return profInterface->HandleCreated(handleId, initialObjectId); - }, - handleId, initialObjectId); + &HandleCreatedHelper, + handleId, initialObjectId); +} + +inline HRESULT HandleDestroyedHelper(EEToProfInterfaceImpl *profInterface, UINT_PTR handleId) +{ + return profInterface->HandleDestroyed(handleId); } inline void ProfControlBlock::HandleDestroyed(UINT_PTR handleId) @@ -1500,12 +1603,8 @@ inline void ProfControlBlock::HandleDestroyed(UINT_PTR handleId) DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, UINT_PTR handleId) - { - return profInterface->HandleDestroyed(handleId); - }, - handleId); + &HandleDestroyedHelper, + handleId); } @@ -1545,18 +1644,24 @@ inline BOOL IsProfilerTrackingGCOrMovedObjects(ProfilerInfo *pProfilerInfo) return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingMovedObjects(pProfilerInfo); } +inline HRESULT GarbageCollectionStartedHelper(EEToProfInterfaceImpl *profInterface, int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) +{ + return profInterface->GarbageCollectionStarted(cGenerations, generationCollected, reason); +} + inline void ProfControlBlock::GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGCOrBasicGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) - { - return profInterface->GarbageCollectionStarted(cGenerations, generationCollected, reason); - }, - cGenerations, generationCollected, reason); + &GarbageCollectionStartedHelper, + cGenerations, generationCollected, reason); +} + +inline HRESULT GarbageCollectionFinishedHelper(EEToProfInterfaceImpl *profInterface) +{ + return profInterface->GarbageCollectionFinished(); } inline void ProfControlBlock::GarbageCollectionFinished() @@ -1565,11 +1670,7 @@ inline void ProfControlBlock::GarbageCollectionFinished() DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGCOrBasicGC, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface) - { - return profInterface->GarbageCollectionFinished(); - }); + &GarbageCollectionFinishedHelper); } @@ -1586,6 +1687,33 @@ inline BOOL IsProfilerMonitoringEventPipe(ProfilerInfo *pProfilerInfo) return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE); } +inline HRESULT EventPipeEventDeliveredHelper(EEToProfInterfaceImpl *profInterface, + EventPipeProvider *provider, + DWORD eventId, + DWORD eventVersion, + ULONG cbMetadataBlob, + LPCBYTE metadataBlob, + ULONG cbEventData, + LPCBYTE eventData, + LPCGUID pActivityId, + LPCGUID pRelatedActivityId, + Thread *pEventThread, + ULONG numStackFrames, + UINT_PTR stackFrames[]) +{ + return profInterface->EventPipeEventDelivered(provider, + eventId, + eventVersion, + cbMetadataBlob, + metadataBlob, + cbEventData, + eventData, + pActivityId, + pRelatedActivityId, + pEventThread, + numStackFrames, + stackFrames); +} inline void ProfControlBlock::EventPipeEventDelivered(EventPipeProvider *provider, DWORD eventId, @@ -1604,33 +1732,7 @@ inline void ProfControlBlock::EventPipeEventDelivered(EventPipeProvider *provide DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerMonitoringEventPipe, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, EventPipeProvider *provider, - DWORD eventId, - DWORD eventVersion, - ULONG cbMetadataBlob, - LPCBYTE metadataBlob, - ULONG cbEventData, - LPCBYTE eventData, - LPCGUID pActivityId, - LPCGUID pRelatedActivityId, - Thread *pEventThread, - ULONG numStackFrames, - UINT_PTR stackFrames[]) - { - return profInterface->EventPipeEventDelivered(provider, - eventId, - eventVersion, - cbMetadataBlob, - metadataBlob, - cbEventData, - eventData, - pActivityId, - pRelatedActivityId, - pEventThread, - numStackFrames, - stackFrames); - }, + &EventPipeEventDeliveredHelper, provider, eventId, eventVersion, @@ -1645,18 +1747,19 @@ inline void ProfControlBlock::EventPipeEventDelivered(EventPipeProvider *provide stackFrames); } +inline HRESULT EventPipeProviderCreatedHelper(EEToProfInterfaceImpl *profInterface, EventPipeProvider *provider) +{ + return profInterface->EventPipeProviderCreated(provider); +} + inline void ProfControlBlock::EventPipeProviderCreated(EventPipeProvider *provider) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerMonitoringEventPipe, - (void *)NULL, - [](void *additionalData, VolatilePtr profInterface, EventPipeProvider *provider) - { - return profInterface->EventPipeProviderCreated(provider); - }, - provider); + &EventPipeProviderCreatedHelper, + provider); } //--------------------------------------------------------------------------------------- @@ -1664,16 +1767,17 @@ inline void ProfControlBlock::EventPipeProviderCreated(EventPipeProvider *provid // and what features it enabled callbacks for. //--------------------------------------------------------------------------------------- -inline BOOL CORProfilerPresent() +FORCEINLINE BOOL CORProfilerPresent() { - LIMITED_METHOD_DAC_CONTRACT; + STATIC_CONTRACT_LIMITED_METHOD; - return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() >= kProfStatusActive; }); + return (&g_profControlBlock)->mainProfilerInfo.pProfInterface.Load() != NULL + || (&g_profControlBlock)->notificationProfilerCount.Load() > 0; } -inline BOOL CORMainProfilerPresent() +FORCEINLINE BOOL CORMainProfilerPresent() { - LIMITED_METHOD_DAC_CONTRACT; + STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->mainProfilerInfo.curProfStatus.Get() >= kProfStatusActive; } @@ -1681,15 +1785,9 @@ inline BOOL CORMainProfilerPresent() // These return whether a CLR Profiler is actively loaded AND has requested the // specified callback or functionality -inline BOOL CORProfilerFunctionIDMapperEnabled() +FORCEINLINE BOOL CORProfilerFunctionIDMapperEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; return (CORMainProfilerPresent() && ( @@ -1698,287 +1796,151 @@ inline BOOL CORProfilerFunctionIDMapperEnabled() )); } -inline BOOL CORProfilerTrackJITInfo() +FORCEINLINE BOOL CORProfilerTrackJITInfo() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION); } -inline BOOL CORProfilerTrackCacheSearches() +FORCEINLINE BOOL CORProfilerTrackCacheSearches() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES); } -inline BOOL CORProfilerTrackModuleLoads() +FORCEINLINE BOOL CORProfilerTrackModuleLoads() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS); } -inline BOOL CORProfilerTrackAssemblyLoads() +FORCEINLINE BOOL CORProfilerTrackAssemblyLoads() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS); } -inline BOOL CORProfilerTrackAppDomainLoads() +FORCEINLINE BOOL CORProfilerTrackAppDomainLoads() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS); } -inline BOOL CORProfilerTrackThreads() +FORCEINLINE BOOL CORProfilerTrackThreads() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS); } -inline BOOL CORProfilerTrackClasses() +FORCEINLINE BOOL CORProfilerTrackClasses() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS); } -inline BOOL CORProfilerTrackGC() +FORCEINLINE BOOL CORProfilerTrackGC() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_GC)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_GC); } -inline BOOL CORProfilerTrackAllocationsEnabled() +FORCEINLINE BOOL CORProfilerTrackAllocationsEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; return ( #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED (&g_profControlBlock)->fTestOnlyForceObjectAllocated || #endif - (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED)) + (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED) ); } -inline BOOL CORProfilerTrackAllocations() +FORCEINLINE BOOL CORProfilerTrackAllocations() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return - (CORProfilerTrackAllocationsEnabled() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_OBJECT_ALLOCATED)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_OBJECT_ALLOCATED); } -inline BOOL CORProfilerTrackLargeAllocations() +FORCEINLINE BOOL CORProfilerTrackLargeAllocations() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return - (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED); } -inline BOOL CORProfilerTrackPinnedAllocations() +FORCEINLINE BOOL CORProfilerTrackPinnedAllocations() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return - (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_PINNEDOBJECT_ALLOCATED)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_PINNEDOBJECT_ALLOCATED); } -inline BOOL CORProfilerEnableRejit() +FORCEINLINE BOOL CORProfilerEnableRejit() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORMainProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT); } -inline BOOL CORProfilerTrackExceptions() +FORCEINLINE BOOL CORProfilerTrackExceptions() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS); } -inline BOOL CORProfilerTrackTransitions() +FORCEINLINE BOOL CORProfilerTrackTransitions() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS); } -inline BOOL CORProfilerTrackEnterLeave() +FORCEINLINE BOOL CORProfilerTrackEnterLeave() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; #ifdef PROF_TEST_ONLY_FORCE_ELT if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) return TRUE; #endif // PROF_TEST_ONLY_FORCE_ELT - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ENTERLEAVE)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ENTERLEAVE); } -inline BOOL CORProfilerTrackCCW() +FORCEINLINE BOOL CORProfilerTrackCCW() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW); } -inline BOOL CORProfilerTrackSuspends() +FORCEINLINE BOOL CORProfilerTrackSuspends() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS); } -inline BOOL CORProfilerDisableInlining() +FORCEINLINE BOOL CORProfilerDisableInlining() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_INLINING)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_INLINING); } -inline BOOL CORProfilerDisableOptimizations() +FORCEINLINE BOOL CORProfilerDisableOptimizations() { CONTRACTL { @@ -1989,56 +1951,35 @@ inline BOOL CORProfilerDisableOptimizations() } CONTRACTL_END; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_OPTIMIZATIONS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_OPTIMIZATIONS); } -inline BOOL CORProfilerUseProfileImages() +FORCEINLINE BOOL CORProfilerUseProfileImages() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; #ifdef PROF_TEST_ONLY_FORCE_ELT if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) return TRUE; #endif // PROF_TEST_ONLY_FORCE_ELT - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_REQUIRE_PROFILE_IMAGE)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_REQUIRE_PROFILE_IMAGE); } -inline BOOL CORProfilerDisableAllNGenImages() +FORCEINLINE BOOL CORProfilerDisableAllNGenImages() { - LIMITED_METHOD_DAC_CONTRACT; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_ALL_NGEN_IMAGES)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_ALL_NGEN_IMAGES); } -inline BOOL CORProfilerTrackConditionalWeakTableElements() +FORCEINLINE BOOL CORProfilerTrackConditionalWeakTableElements() { - LIMITED_METHOD_DAC_CONTRACT; + STATIC_CONTRACT_LIMITED_METHOD; return CORProfilerTrackGC() && (&g_profControlBlock)->IsCallback5Supported(); } -// CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively -// loaded and ready to receive callbacks OR a CLR Profiler has loaded just enough that it -// is ready to receive (or is currently executing inside) its Initialize() callback. -// Typically, you'll want to use code:CORProfilerPresent instead of this. But there is -// some internal profiling API code that wants to test for event flags for a profiler -// that may still be initializing, and this function is appropriate for that code. -inline BOOL CORProfilerPresentOrInitializing() -{ - LIMITED_METHOD_CONTRACT; - return AnyProfilerPassesCondition([](ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() > kProfStatusDetaching; }); -} - // These return whether a CLR Profiler has requested the specified functionality. // // Note that, unlike the above functions, a profiler that's not done loading (and is @@ -2047,243 +1988,124 @@ inline BOOL CORProfilerPresentOrInitializing() // are used primarily during the initialization path to choose between slow / fast-path // ELT hooks (and later on as part of asserts). -inline BOOL CORProfilerELT3SlowPathEnabled() +FORCEINLINE BOOL CORProfilerELT3SlowPathEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)); } -inline BOOL CORProfilerELT3SlowPathEnterEnabled() +FORCEINLINE BOOL CORProfilerELT3SlowPathEnterEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)); } -inline BOOL CORProfilerELT3SlowPathLeaveEnabled() +FORCEINLINE BOOL CORProfilerELT3SlowPathLeaveEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)); } -inline BOOL CORProfilerELT3SlowPathTailcallEnabled() +FORCEINLINE BOOL CORProfilerELT3SlowPathTailcallEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FRAME_INFO))); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FRAME_INFO)); } -inline BOOL CORProfilerELT2FastPathEnterEnabled() +FORCEINLINE BOOL CORProfilerELT2FastPathEnterEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); + return !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); } -inline BOOL CORProfilerELT2FastPathLeaveEnabled() +FORCEINLINE BOOL CORProfilerELT2FastPathLeaveEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); + return !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); } -inline BOOL CORProfilerELT2FastPathTailcallEnabled() +FORCEINLINE BOOL CORProfilerELT2FastPathTailcallEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); + return !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO))); } -inline BOOL CORProfilerFunctionArgsEnabled() +FORCEINLINE BOOL CORProfilerFunctionArgsEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_ARGS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_ARGS); } -inline BOOL CORProfilerFunctionReturnValueEnabled() +FORCEINLINE BOOL CORProfilerFunctionReturnValueEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_RETVAL)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_RETVAL); } -inline BOOL CORProfilerFrameInfoEnabled() +FORCEINLINE BOOL CORProfilerFrameInfoEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FRAME_INFO)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FRAME_INFO); } -inline BOOL CORProfilerStackSnapshotEnabled() +FORCEINLINE BOOL CORProfilerStackSnapshotEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresentOrInitializing() && - (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_STACK_SNAPSHOT)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_STACK_SNAPSHOT); } -inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled() +FORCEINLINE BOOL CORProfilerInMemorySymbolsUpdatesEnabled() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED); } -inline BOOL CORProfilerTrackDynamicFunctionUnloads() +FORCEINLINE BOOL CORProfilerTrackDynamicFunctionUnloads() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS); } -inline BOOL CORProfilerDisableTieredCompilation() +FORCEINLINE BOOL CORProfilerDisableTieredCompilation() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_DISABLE_TIERED_COMPILATION)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_DISABLE_TIERED_COMPILATION); } -inline BOOL CORProfilerTrackBasicGC() +FORCEINLINE BOOL CORProfilerTrackBasicGC() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC); } -inline BOOL CORProfilerTrackGCMovedObjects() +FORCEINLINE BOOL CORProfilerTrackGCMovedObjects() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS); } -inline BOOL CORProfilerTrackEventPipe() +FORCEINLINE BOOL CORProfilerTrackEventPipe() { - CONTRACTL - { - NOTHROW; - GC_NOTRIGGER; - CANNOT_TAKE_LOCK; - } - CONTRACTL_END; + STATIC_CONTRACT_LIMITED_METHOD; - return (CORProfilerPresent() && - (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE)); + return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE); } #if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE) diff --git a/src/coreclr/interop/comwrappers.cpp b/src/coreclr/interop/comwrappers.cpp index 5600b6a69f50dd..aad3d6fa235913 100644 --- a/src/coreclr/interop/comwrappers.cpp +++ b/src/coreclr/interop/comwrappers.cpp @@ -791,17 +791,6 @@ void NativeObjectWrapperContext::Destroy(_In_ NativeObjectWrapperContext* wrappe { _ASSERTE(wrapper != nullptr); - // Check if the tracker object manager should be informed prior to being destroyed. - IReferenceTracker* trackerMaybe = wrapper->GetReferenceTracker(); - if (trackerMaybe != nullptr) - { - // We only call this during a GC so ignore the failure as - // there is no way we can handle it at this point. - HRESULT hr = TrackerObjectManager::BeforeWrapperDestroyed(trackerMaybe); - _ASSERTE(SUCCEEDED(hr)); - (void)hr; - } - // Manually trigger the destructor since placement // new was used to allocate the object. wrapper->~NativeObjectWrapperContext(); diff --git a/src/coreclr/interop/comwrappers.hpp b/src/coreclr/interop/comwrappers.hpp index bd383beabc5dce..6217b0ebe7e7b9 100644 --- a/src/coreclr/interop/comwrappers.hpp +++ b/src/coreclr/interop/comwrappers.hpp @@ -212,8 +212,8 @@ class TrackerObjectManager // Called after wrapper has been created. static HRESULT AfterWrapperCreated(_In_ IReferenceTracker* obj); - // Called before wrapper is about to be destroyed (the same lifetime as short weak handle). - static HRESULT BeforeWrapperDestroyed(_In_ IReferenceTracker* obj); + // Called before wrapper is about to be finalized (the same lifetime as short weak handle). + static HRESULT BeforeWrapperFinalized(_In_ IReferenceTracker* obj); public: // Begin the reference tracking process for external objects. diff --git a/src/coreclr/interop/inc/interoplib.h b/src/coreclr/interop/inc/interoplib.h index 96f157929e0a5c..37237f5f7cab3c 100644 --- a/src/coreclr/interop/inc/interoplib.h +++ b/src/coreclr/interop/inc/interoplib.h @@ -87,8 +87,12 @@ namespace InteropLib _In_ size_t contextSize, _Out_ ExternalWrapperResult* result) noexcept; - // Destroy the supplied wrapper. - void DestroyWrapperForExternal(_In_ void* context) noexcept; + // Inform the wrapper it is being collected. + void NotifyWrapperForExternalIsBeingCollected(_In_ void* context) noexcept; + + // Destroy the supplied wrapper. + // Optionally notify the wrapper of collection at the same time. + void DestroyWrapperForExternal(_In_ void* context, _In_ bool notifyIsBeingCollected = false) noexcept; // Separate the supplied wrapper from the tracker runtime. void SeparateWrapperFromTrackerRuntime(_In_ void* context) noexcept; diff --git a/src/coreclr/interop/interoplib.cpp b/src/coreclr/interop/interoplib.cpp index 7af7af9e7adcf1..db9e9800fbd46e 100644 --- a/src/coreclr/interop/interoplib.cpp +++ b/src/coreclr/interop/interoplib.cpp @@ -166,15 +166,37 @@ namespace InteropLib return S_OK; } - void DestroyWrapperForExternal(_In_ void* contextMaybe) noexcept + void NotifyWrapperForExternalIsBeingCollected(_In_ void* contextMaybe) noexcept + { + NativeObjectWrapperContext* context = NativeObjectWrapperContext::MapFromRuntimeContext(contextMaybe); + + // A caller should not be destroying a context without knowing if the context is valid. + _ASSERTE(context != nullptr); + + // Check if the tracker object manager should be informed of collection. + IReferenceTracker* trackerMaybe = context->GetReferenceTracker(); + if (trackerMaybe != nullptr) + { + // We only call this during a GC so ignore the failure as + // there is no way we can handle it at this point. + HRESULT hr = TrackerObjectManager::BeforeWrapperFinalized(trackerMaybe); + _ASSERTE(SUCCEEDED(hr)); + (void)hr; + } + } + + void DestroyWrapperForExternal(_In_ void* contextMaybe, _In_ bool notifyIsBeingCollected) noexcept { NativeObjectWrapperContext* context = NativeObjectWrapperContext::MapFromRuntimeContext(contextMaybe); // A caller should not be destroying a context without knowing if the context is valid. _ASSERTE(context != nullptr); - NativeObjectWrapperContext::Destroy(context); - } + if (notifyIsBeingCollected) + NotifyWrapperForExternalIsBeingCollected(contextMaybe); + + NativeObjectWrapperContext::Destroy(context); + } void SeparateWrapperFromTrackerRuntime(_In_ void* contextMaybe) noexcept { diff --git a/src/coreclr/interop/trackerobjectmanager.cpp b/src/coreclr/interop/trackerobjectmanager.cpp index 0a199b71690a46..5214e6b8349d18 100644 --- a/src/coreclr/interop/trackerobjectmanager.cpp +++ b/src/coreclr/interop/trackerobjectmanager.cpp @@ -305,13 +305,13 @@ HRESULT TrackerObjectManager::AfterWrapperCreated(_In_ IReferenceTracker* obj) return S_OK; } -HRESULT TrackerObjectManager::BeforeWrapperDestroyed(_In_ IReferenceTracker* obj) +HRESULT TrackerObjectManager::BeforeWrapperFinalized(_In_ IReferenceTracker* obj) { _ASSERTE(obj != nullptr); HRESULT hr; - // Notify tracker runtime that we are about to destroy a wrapper + // Notify tracker runtime that we are about to finalize a wrapper // (same timing as short weak handle) for this object. // They need this information to disconnect weak refs and stop firing events, // so that they can avoid resurrecting the object. diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index f29e37f91baae3..fec125b78ae06e 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -176,5 +176,6 @@ DEF_CLR_API(recordRelocation) DEF_CLR_API(getRelocTypeHint) DEF_CLR_API(getExpectedTargetArchitecture) DEF_CLR_API(getJitFlags) +DEF_CLR_API(doesFieldBelongToClass) #undef DEF_CLR_API diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 66292765480a38..f902b3b99ecd6c 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1690,6 +1690,16 @@ uint32_t WrapICorJitInfo::getJitFlags( return temp; } +bool WrapICorJitInfo::doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(doesFieldBelongToClass); + bool temp = wrapHnd->doesFieldBelongToClass(fldHnd, cls); + API_LEAVE(doesFieldBelongToClass); + return temp; +} + /**********************************************************************************/ // clang-format on /**********************************************************************************/ diff --git a/src/coreclr/jit/bitsetasshortlong.h b/src/coreclr/jit/bitsetasshortlong.h index dce54d6a5ca3ab..365cf346a10ac2 100644 --- a/src/coreclr/jit/bitsetasshortlong.h +++ b/src/coreclr/jit/bitsetasshortlong.h @@ -345,7 +345,7 @@ class BitSetOps - [{lvType,en}] - [{lvType,en}-{lvReason,s}] + [V{lvSlotNum,d}: {lvType,en}] + [V{lvSlotNum,d}: {lvType,en}-{lvReason,s}] diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index dcf1768c60a7dd..4ba948ec4793c5 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -486,13 +486,14 @@ regMaskTP CodeGenInterface::genGetRegMask(const LclVarDsc* varDsc) assert(varDsc->lvIsInReg()); - if (varTypeUsesFloatReg(varDsc->TypeGet())) + regNumber reg = varDsc->GetRegNum(); + if (genIsValidFloatReg(reg)) { - regMask = genRegMaskFloat(varDsc->GetRegNum(), varDsc->TypeGet()); + regMask = genRegMaskFloat(reg, varDsc->GetRegisterType()); } else { - regMask = genRegMask(varDsc->GetRegNum()); + regMask = genRegMask(reg); } return regMask; } @@ -7148,8 +7149,9 @@ void CodeGen::genFnProlog() if (isInReg) { - regMaskTP regMask = genRegMask(varDsc->GetRegNum()); - if (!varDsc->IsFloatRegType()) + regNumber regForVar = varDsc->GetRegNum(); + regMaskTP regMask = genRegMask(regForVar); + if (!genIsValidFloatReg(regForVar)) { initRegs |= regMask; @@ -12551,6 +12553,17 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn) assert(varDsc->lvOnFrame); + int size = (int)compiler->lvaLclSize(varNum); + + if ((size / TARGET_POINTER_SIZE) > 16) + { + // For very large structs the offsets in the movs we emit below can + // grow too large to be handled properly by JIT. Furthermore, while + // this is only debug code, for very large structs this can bloat + // the code too much due to the singular movs used. + continue; + } + if (!hasPoisonImm) { #ifdef TARGET_64BIT @@ -12568,8 +12581,7 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn) #else int addr = 0; #endif - int size = (int)compiler->lvaLclSize(varNum); - int end = addr + size; + int end = addr + size; for (int offs = addr; offs < end;) { #ifdef TARGET_64BIT diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index f58a8db0997e3c..94da35b01c172e 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -51,19 +51,16 @@ void CodeGen::genInitializeRegisterState() continue; } - // Is this a floating-point argument? - if (varDsc->IsFloatRegType()) + if (varDsc->lvAddrExposed) { continue; } - noway_assert(!varTypeUsesFloatReg(varDsc->TypeGet())); - // Mark the register as holding the variable - assert(varDsc->GetRegNum() != REG_STK); - if (!varDsc->lvAddrExposed) + regNumber reg = varDsc->GetRegNum(); + if (genIsValidIntReg(reg)) { - regSet.verifyRegUsed(varDsc->GetRegNum()); + regSet.verifyRegUsed(reg); } } } diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index f268c6a066a86a..759f1037ca2da7 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -1891,7 +1891,7 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) // genMultiRegStoreToSIMDLocal: store multi-reg value to a single-reg SIMD local // // Arguments: -// lclNode - GentreeLclVar of GT_STORE_LCL_VAR +// lclNode - GenTreeLclVar of GT_STORE_LCL_VAR // // Return Value: // None @@ -1996,6 +1996,7 @@ void CodeGen::genMultiRegStoreToSIMDLocal(GenTreeLclVar* lclNode) else { regNumber tempXmm = lclNode->GetSingleTempReg(); + assert(tempXmm != targetReg); inst_Mov(TYP_FLOAT, tempXmm, reg1, /* canSkip */ false); GetEmitter()->emitIns_SIMD_R_R_R(INS_punpckldq, size, targetReg, targetReg, tempXmm); } diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 2c35262a5df0db..cca34ff20bbb38 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -2170,7 +2170,7 @@ VarName Compiler::compVarName(regNumber reg, bool isFloatReg) /* If the variable is not in a register, or not in the register we're looking for, quit. */ /* Also, if it is a compiler generated variable (i.e. slot# > info.compVarScopesCount), don't bother. */ if ((varDsc->lvRegister != 0) && (varDsc->GetRegNum() == reg) && - (varDsc->IsFloatRegType() || !isFloatReg) && (varDsc->lvSlotNum < info.compVarScopesCount)) + (varDsc->lvSlotNum < info.compVarScopesCount)) { /* check if variable in that register is live */ if (VarSetOps::IsMember(this, compCurLife, varDsc->lvVarIndex)) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index f843a6233e907b..b928060d722480 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -502,6 +502,9 @@ class LclVarDsc unsigned char lvUnusedStruct : 1; // All references to this promoted struct are through its field locals. // I.e. there is no longer any reference to the struct directly. // In this case we can simply remove this struct local. + + unsigned char lvUndoneStructPromotion : 1; // The struct promotion was undone and hence there should be no + // reference to the fields of this struct. #endif unsigned char lvLRACandidate : 1; // Tracked for linear scan register allocation purposes @@ -958,10 +961,6 @@ class LclVarDsc Compiler* pComp, RefCountState state = RCS_NORMAL, bool propagate = true); - bool IsFloatRegType() const - { - return varTypeUsesFloatReg(lvType) || lvIsHfaRegArg(); - } var_types GetHfaType() const { @@ -5204,6 +5203,8 @@ class Compiler // Does value-numbering for a block assignment. void fgValueNumberBlockAssignment(GenTree* tree); + bool fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLclVarTree, GenTreeLclVarCommon* rhsLclVarTree); + // Does value-numbering for a cast tree. void fgValueNumberCastTree(GenTree* tree); @@ -8910,15 +8911,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX } private: - unsigned getSIMDInitTempVarNum() - { - if (lvaSIMDInitTempVarNum == BAD_VAR_NUM) - { - lvaSIMDInitTempVarNum = lvaGrabTempWithImplicitUse(false DEBUGARG("SIMDInitTempVar")); - lvaTable[lvaSIMDInitTempVarNum].lvType = getSIMDVectorType(); - } - return lvaSIMDInitTempVarNum; - } + unsigned getSIMDInitTempVarNum(var_types simdType); #else // !FEATURE_SIMD bool isOpaqueSIMDLclVar(LclVarDsc* varDsc) diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 16ad448cd3d768..97cbc11c3cb93c 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -10370,7 +10370,7 @@ BYTE* emitter::emitOutputAM(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc) noway_assert((int)dsp == dsp); // This requires, specifying a SIB byte after ModRM byte. - if (EncodedBySSE38orSSE3A(ins)) + if (EncodedBySSE38orSSE3A(ins) || (ins == INS_crc32)) { dst += emitOutputByte(dst, code | 0x04); } diff --git a/src/coreclr/jit/fgehopt.cpp b/src/coreclr/jit/fgehopt.cpp index 06abf455ac2df1..18cb78ac12e612 100644 --- a/src/coreclr/jit/fgehopt.cpp +++ b/src/coreclr/jit/fgehopt.cpp @@ -99,6 +99,14 @@ PhaseStatus Compiler::fgRemoveEmptyFinally() continue; } + // If the finally's block jumps back to itself, then it is not empty. + if ((firstBlock->bbJumpKind == BBJ_ALWAYS) && firstBlock->bbJumpDest == firstBlock) + { + JITDUMP("EH#%u finally has basic block that jumps to itself; skipping.\n", XTnum); + XTnum++; + continue; + } + // Limit for now to finallys that contain only a GT_RETFILT. bool isEmpty = true; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 22e46b6a819eb2..d06b00a9d4d4e0 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -7475,6 +7475,7 @@ GenTreeAllocObj* Compiler::gtNewAllocObjNode(CORINFO_RESOLVED_TOKEN* pResolvedTo #ifdef FEATURE_READYTORUN_COMPILER if (usingReadyToRunHelper) { + assert(lookup.addr != nullptr); allocObj->gtEntryPoint = lookup; } #endif @@ -7879,6 +7880,9 @@ GenTree* Compiler::gtCloneExpr( copy = new (this, GT_ALLOCOBJ) GenTreeAllocObj(tree->TypeGet(), asAllocObj->gtNewHelper, asAllocObj->gtHelperHasSideEffects, asAllocObj->gtAllocObjClsHnd, asAllocObj->gtOp1); +#ifdef FEATURE_READYTORUN_COMPILER + copy->AsAllocObj()->gtEntryPoint = asAllocObj->gtEntryPoint; +#endif } break; diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index da396f145bfe05..04e074cf449120 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -17275,45 +17275,6 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) #endif } - // If we are inlining a method that returns a struct byref, check whether we are "reinterpreting" the - // struct. - GenTree* effectiveRetVal = op2->gtEffectiveVal(); - if ((returnType == TYP_BYREF) && (info.compRetType == TYP_BYREF) && - (effectiveRetVal->OperGet() == GT_ADDR)) - { - GenTree* addrChild = effectiveRetVal->gtGetOp1(); - if (addrChild->OperGet() == GT_LCL_VAR) - { - LclVarDsc* varDsc = lvaGetDesc(addrChild->AsLclVarCommon()); - - if (varTypeIsStruct(addrChild->TypeGet()) && !isOpaqueSIMDLclVar(varDsc)) - { - CORINFO_CLASS_HANDLE referentClassHandle; - CorInfoType referentType = - info.compCompHnd->getChildType(info.compMethodInfo->args.retTypeClass, - &referentClassHandle); - if (varTypeIsStruct(JITtype2varType(referentType)) && - (varDsc->GetStructHnd() != referentClassHandle)) - { - // We are returning a byref to struct1; the method signature specifies return type as - // byref - // to struct2. struct1 and struct2 are different so we are "reinterpreting" the struct. - // This may happen in, for example, System.Runtime.CompilerServices.Unsafe.As. - // We need to mark the source struct variable as having overlapping fields because its - // fields may be accessed using field handles of a different type, which may confuse - // optimizations, in particular, value numbering. - - JITDUMP("\nSetting lvOverlappingFields to true on V%02u because of struct " - "reinterpretation\n", - addrChild->AsLclVarCommon()->GetLclNum()); - - varDsc->lvOverlappingFields = true; - } - } - } - } - #ifdef DEBUG if (verbose) { diff --git a/src/coreclr/jit/inlinepolicy.h b/src/coreclr/jit/inlinepolicy.h index 466e17fe0e1127..e604fd57a36ed5 100644 --- a/src/coreclr/jit/inlinepolicy.h +++ b/src/coreclr/jit/inlinepolicy.h @@ -185,7 +185,7 @@ class DefaultPolicy : public LegalPolicy class ExtendedDefaultPolicy : public DefaultPolicy { public: - ExtendedDefaultPolicy::ExtendedDefaultPolicy(Compiler* compiler, bool isPrejitRoot) + ExtendedDefaultPolicy(Compiler* compiler, bool isPrejitRoot) : DefaultPolicy(compiler, isPrejitRoot) , m_ProfileFrequency(0.0) , m_BinaryExprWithCns(0) diff --git a/src/coreclr/jit/jiteh.cpp b/src/coreclr/jit/jiteh.cpp index da431dd82e2de9..12e91d077690ba 100644 --- a/src/coreclr/jit/jiteh.cpp +++ b/src/coreclr/jit/jiteh.cpp @@ -4410,7 +4410,7 @@ void Compiler::fgExtendEHRegionBefore(BasicBlock* block) #endif // DEBUG // The first block of a handler has an artificial extra refcount. Transfer that to the new block. - assert(block->bbRefs > 0); + noway_assert(block->countOfInEdges() > 0); block->bbRefs--; HBtab->ebdHndBeg = bPrev; @@ -4459,7 +4459,7 @@ void Compiler::fgExtendEHRegionBefore(BasicBlock* block) #endif // DEBUG // The first block of a filter has an artificial extra refcount. Transfer that to the new block. - assert(block->bbRefs > 0); + noway_assert(block->countOfInEdges() > 0); block->bbRefs--; HBtab->ebdFilter = bPrev; diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index caa8a1bdc872d6..0ffd46f47b7845 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -210,7 +210,7 @@ class LocalAddressVisitor final : public GenTreeVisitor // Arguments: // val - the input value // field - the FIELD node that uses the input address value - // fieldSeqStore - the compiler's field sequence store + // compiler - the compiler instance // // Return Value: // `true` if the value was consumed. `false` if the input value @@ -224,8 +224,9 @@ class LocalAddressVisitor final : public GenTreeVisitor // if the offset overflows then location is not representable, must escape // - UNKNOWN => UNKNOWN // - bool Field(Value& val, GenTreeField* field, FieldSeqStore* fieldSeqStore) + bool Field(Value& val, GenTreeField* field, Compiler* compiler) { + assert(!IsLocation() && !IsAddress()); if (val.IsLocation()) @@ -246,14 +247,80 @@ class LocalAddressVisitor final : public GenTreeVisitor m_lclNum = val.m_lclNum; m_offset = newOffset.Value(); + bool haveCorrectFieldForVN; if (field->gtFldMayOverlap) { - m_fieldSeq = FieldSeqStore::NotAField(); + haveCorrectFieldForVN = false; } else { + LclVarDsc* varDsc = compiler->lvaGetDesc(m_lclNum); + if (!varTypeIsStruct(varDsc)) + { + haveCorrectFieldForVN = false; + } + else if (FieldSeqStore::IsPseudoField(field->gtFldHnd)) + { + assert(compiler->compObjectStackAllocation()); + // We use PseudoFields when accessing stack allocated classes. + haveCorrectFieldForVN = false; + } + else if (val.m_fieldSeq == nullptr) + { + + CORINFO_CLASS_HANDLE clsHnd = varDsc->GetStructHnd(); + // If the answer is no we are probably accessing a canon type with a non-canon fldHnd, + // currently it could happen in crossgen2 scenario where VM distinguishes class._field + // from class._field. + haveCorrectFieldForVN = + compiler->info.compCompHnd->doesFieldBelongToClass(field->gtFldHnd, clsHnd); + } + else + { + FieldSeqNode* lastSeqNode = val.m_fieldSeq->GetTail(); + assert(lastSeqNode != nullptr); + if (lastSeqNode->IsPseudoField() || lastSeqNode == FieldSeqStore::NotAField()) + { + haveCorrectFieldForVN = false; + } + else + { + CORINFO_FIELD_HANDLE lastFieldBeforeTheCurrent = lastSeqNode->GetFieldHandle(); + + CORINFO_CLASS_HANDLE clsHnd; + CorInfoType fieldCorType = + compiler->info.compCompHnd->getFieldType(lastFieldBeforeTheCurrent, &clsHnd); + if (fieldCorType != CORINFO_TYPE_VALUECLASS) + { + // For example, System.IntPtr:ToInt64, when inlined, creates trees like + // * FIELD long _value + // \--* ADDR byref + // \--* FIELD long Information + // \--* ADDR byref + // \--* LCL_VAR struct V08 tmp7 + haveCorrectFieldForVN = false; + } + else + { + + haveCorrectFieldForVN = + compiler->info.compCompHnd->doesFieldBelongToClass(field->gtFldHnd, clsHnd); + noway_assert(haveCorrectFieldForVN); + } + } + } + } + + if (haveCorrectFieldForVN) + { + FieldSeqStore* fieldSeqStore = compiler->GetFieldSeqStore(); m_fieldSeq = fieldSeqStore->Append(val.m_fieldSeq, fieldSeqStore->CreateSingleton(field->gtFldHnd)); } + else + { + m_fieldSeq = FieldSeqStore::NotAField(); + JITDUMP("Setting NotAField for [%06u],\n", compiler->dspTreeID(field)); + } } INDEBUG(val.Consume();) @@ -463,7 +530,7 @@ class LocalAddressVisitor final : public GenTreeVisitor assert(TopValue(1).Node() == node); assert(TopValue(0).Node() == node->AsField()->gtFldObj); - if (!TopValue(1).Field(TopValue(0), node->AsField(), m_compiler->GetFieldSeqStore())) + if (!TopValue(1).Field(TopValue(0), node->AsField(), m_compiler)) { // Either the address comes from a location value (e.g. FIELD(IND(...))) // or the field offset has overflowed. diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 27771bbb7c18ce..6b7032336bd2d2 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -2103,8 +2103,13 @@ bool Compiler::StructPromotionHelper::ShouldPromoteStructVar(unsigned lclNum) // multiple registers? if (compiler->lvaIsMultiregStruct(varDsc, compiler->info.compIsVarArgs)) { - if ((structPromotionInfo.fieldCnt != 2) && - !((structPromotionInfo.fieldCnt == 1) && varTypeIsSIMD(structPromotionInfo.fields[0].fldType))) + if (structPromotionInfo.containsHoles && structPromotionInfo.customLayout) + { + JITDUMP("Not promoting multi-reg struct local V%02u with holes.\n", lclNum); + shouldPromote = false; + } + else if ((structPromotionInfo.fieldCnt != 2) && + !((structPromotionInfo.fieldCnt == 1) && varTypeIsSIMD(structPromotionInfo.fields[0].fldType))) { JITDUMP("Not promoting multireg struct local V%02u, because lvIsParam is true, #fields != 2 and it's " "not a single SIMD.\n", @@ -4075,6 +4080,16 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, varDsc->incRefCnts(weight, this); +#ifdef DEBUG + if (varDsc->lvIsStructField) + { + // If ref count was increased for struct field, ensure that the + // parent struct is still promoted. + LclVarDsc* parentStruct = &lvaTable[varDsc->lvParentLcl]; + assert(!parentStruct->lvUndoneStructPromotion); + } +#endif + if (!isRecompute) { if (lvaVarAddrExposed(lclNum)) @@ -4142,8 +4157,10 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, { bool bbInALoop = (block->bbFlags & BBF_BACKWARD_JUMP) != 0; bool bbIsReturn = block->bbJumpKind == BBJ_RETURN; - // TODO: Zero-inits in LSRA are created with below condition. Try to use similar condition here as well. - // if (compiler->info.compInitMem || varTypeIsGC(varDsc->TypeGet())) + // TODO: Zero-inits in LSRA are created with below condition. But if filter out based on that condition + // we filter lot of interesting variables that would benefit otherwise with EH var enregistration. + // bool needsExplicitZeroInit = !varDsc->lvIsParam && (info.compInitMem || + // varTypeIsGC(varDsc->TypeGet())); bool needsExplicitZeroInit = fgVarNeedsExplicitZeroInit(lclNum, bbInALoop, bbIsReturn); if (varDsc->lvSingleDefRegCandidate || needsExplicitZeroInit) diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index 69e916c3249525..9b2898a3270edd 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -968,7 +968,14 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext else if (loop->lpFlags & LPFLG_VAR_INIT) { // initVar >= 0 - LC_Condition geZero(GT_GE, LC_Expr(LC_Ident(loop->lpVarInit, LC_Ident::Var)), + const unsigned initLcl = loop->lpVarInit; + if (!genActualTypeIsInt(lvaGetDesc(initLcl))) + { + JITDUMP("> Init var V%02u not compatible with TYP_INT\n", initLcl); + return false; + } + + LC_Condition geZero(GT_GE, LC_Expr(LC_Ident(initLcl, LC_Ident::Var)), LC_Expr(LC_Ident(0, LC_Ident::Const))); context->EnsureConditions(loopNum)->Push(geZero); } @@ -992,9 +999,14 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext } else if (loop->lpFlags & LPFLG_VAR_LIMIT) { - unsigned limitLcl = loop->lpVarLimit(); - ident = LC_Ident(limitLcl, LC_Ident::Var); + const unsigned limitLcl = loop->lpVarLimit(); + if (!genActualTypeIsInt(lvaGetDesc(limitLcl))) + { + JITDUMP("> Limit var V%02u not compatible with TYP_INT\n", limitLcl); + return false; + } + ident = LC_Ident(limitLcl, LC_Ident::Var); LC_Condition geZero(GT_GE, LC_Expr(ident), LC_Expr(LC_Ident(0, LC_Ident::Const))); context->EnsureConditions(loopNum)->Push(geZero); diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 08cbc8b0ad0d37..ed269cc77b9141 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -2984,9 +2984,8 @@ void Lowering::LowerRet(GenTreeUnOp* ret) // There are two kinds of retyping: // - A simple bitcast can be inserted when: // - We're returning a floating type as an integral type or vice-versa, or - // - We're returning a struct as a primitive type and using the old form of retyping. - // - If we're returning a struct as a primitive type and *not* using old retying, we change the type of - // 'retval' in 'LowerRetStructLclVar()' + // - If we're returning a struct as a primitive type, we change the type of + // 'retval' in 'LowerRetStructLclVar()' bool needBitcast = (ret->TypeGet() != TYP_VOID) && (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(ret->gtGetOp1())); bool doPrimitiveBitcast = false; @@ -3408,6 +3407,7 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret) unsigned lclNum = lclVar->GetLclNum(); LclVarDsc* varDsc = comp->lvaGetDesc(lclNum); + bool replacedInLowering = false; if (varDsc->CanBeReplacedWithItsField(comp)) { // We can replace the struct with its only field and keep the field on a register. @@ -3420,8 +3420,9 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret) "[%06u]\n", lclNum, fieldLclNum, comp->dspTreeID(ret)); lclVar->ChangeType(fieldDsc->lvType); - lclNum = fieldLclNum; - varDsc = comp->lvaGetDesc(lclNum); + lclNum = fieldLclNum; + varDsc = comp->lvaGetDesc(lclNum); + replacedInLowering = true; } else if (varDsc->lvPromoted) { @@ -3434,18 +3435,49 @@ void Lowering::LowerRetSingleRegStructLclVar(GenTreeUnOp* ret) { lclVar->ChangeOper(GT_LCL_FLD); lclVar->AsLclFld()->SetLclOffs(0); - lclVar->ChangeType(ret->TypeGet()); + + // We are returning as a primitive type and the lcl is of struct type. + assert(comp->info.compRetNativeType != TYP_STRUCT); + assert((genTypeSize(comp->info.compRetNativeType) == genTypeSize(ret)) || + (varTypeIsIntegral(ret) && varTypeIsIntegral(comp->info.compRetNativeType) && + (genTypeSize(comp->info.compRetNativeType) <= genTypeSize(ret)))); + // If the actual return type requires normalization, then make sure we + // do so by using the correct small type for the GT_LCL_FLD. It would + // be conservative to check just compRetNativeType for this since small + // structs are normalized to primitive types when they are returned in + // registers, so we would normalize for them as well. + if (varTypeIsSmall(comp->info.compRetType)) + { + assert(genTypeSize(comp->info.compRetNativeType) == genTypeSize(comp->info.compRetType)); + lclVar->ChangeType(comp->info.compRetType); + } + else + { + // Otherwise we don't mind that we leave the upper bits undefined. + lclVar->ChangeType(ret->TypeGet()); + } } else { const var_types lclVarType = varDsc->GetRegisterType(lclVar); assert(lclVarType != TYP_UNDEF); + + if (varDsc->lvNormalizeOnLoad() && replacedInLowering) + { + // For a normalize-on-load var that we replaced late we need to insert a cast + // as morph would typically be responsible for this. + GenTreeCast* cast = comp->gtNewCastNode(TYP_INT, lclVar, false, lclVarType); + ret->gtOp1 = cast; + BlockRange().InsertBefore(ret, cast); + ContainCheckCast(cast); + } + const var_types actualType = genActualType(lclVarType); lclVar->ChangeType(actualType); if (varTypeUsesFloatReg(ret) != varTypeUsesFloatReg(lclVarType)) { - GenTree* bitcast = comp->gtNewBitCastNode(ret->TypeGet(), lclVar); + GenTree* bitcast = comp->gtNewBitCastNode(ret->TypeGet(), ret->gtOp1); ret->gtOp1 = bitcast; BlockRange().InsertBefore(ret, bitcast); ContainCheckBitCast(bitcast); diff --git a/src/coreclr/jit/lsra.cpp b/src/coreclr/jit/lsra.cpp index 9491b2c0773578..58e55bae823348 100644 --- a/src/coreclr/jit/lsra.cpp +++ b/src/coreclr/jit/lsra.cpp @@ -4945,6 +4945,13 @@ void LinearScan::allocateRegisters() // it to a different register file. allocate = false; } + else if ((currentInterval->isWriteThru) && (refType == RefTypeZeroInit)) + { + // For RefTypeZeroInit which is a write thru, there is no need to allocate register + // right away. It can be assigned when actually definition occurs. + // In future, see if avoiding allocation for RefTypeZeroInit gives any benefit in general. + allocate = false; + } if (!allocate) { INDEBUG(dumpLsraAllocationEvent(LSRA_EVENT_NO_ENTRY_REG_ALLOCATED, currentInterval)); diff --git a/src/coreclr/jit/lsraarm64.cpp b/src/coreclr/jit/lsraarm64.cpp index a7a14fdfe54f96..88644ead77225f 100644 --- a/src/coreclr/jit/lsraarm64.cpp +++ b/src/coreclr/jit/lsraarm64.cpp @@ -1132,7 +1132,8 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) { // If the index is not a constant or op1 is in register, // we will use the SIMD temp location to store the vector. - compiler->getSIMDInitTempVarNum(); + var_types requiredSimdTempType = (intrin.id == NI_Vector64_GetElement) ? TYP_SIMD8 : TYP_SIMD16; + compiler->getSIMDInitTempVarNum(requiredSimdTempType); } } diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index cf11833a1f356a..3214c67ac17737 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -3413,6 +3413,8 @@ int LinearScan::BuildStoreLoc(GenTreeLclVarCommon* storeLoc) { // Need an additional register to create a SIMD8 from EAX/EDX without SSE4.1. buildInternalFloatRegisterDefForNode(storeLoc, allSIMDRegs()); + // This internal register must be different from the target register. + setInternalRegsDelayFree = true; } } #endif // FEATURE_SIMD && TARGET_X86 && TARGET_WINDOWS diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index f4401828f8ad21..5ccb43dbdd7a41 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -2201,7 +2201,8 @@ int LinearScan::BuildHWIntrinsic(GenTreeHWIntrinsic* intrinsicTree) { // If the index is not a constant or op1 is in register, // we will use the SIMD temp location to store the vector. - compiler->getSIMDInitTempVarNum(); + var_types requiredSimdTempType = (intrinsicId == NI_Vector128_GetElement) ? TYP_SIMD16 : TYP_SIMD32; + compiler->getSIMDInitTempVarNum(requiredSimdTempType); } break; } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 2ff290263c2798..ba5f450b616c9f 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -7896,6 +7896,15 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call) // Avoid potential extra work for the return (for example, vzeroupper) call->gtType = TYP_VOID; + // The runtime requires that we perform a null check on the `this` argument before + // tail calling to a virtual dispatch stub. This requirement is a consequence of limitations + // in the runtime's ability to map an AV to a NullReferenceException if + // the AV occurs in a dispatch stub that has unmanaged caller. + if (call->IsVirtualStub()) + { + call->gtFlags |= GTF_CALL_NULLCHECK; + } + // Do some target-specific transformations (before we process the args, // etc.) for the JIT helper case. if (tailCallViaJitHelper) @@ -8622,15 +8631,6 @@ void Compiler::fgMorphTailCallViaJitHelper(GenTreeCall* call) JITDUMP("fgMorphTailCallViaJitHelper (before):\n"); DISPTREE(call); - // The runtime requires that we perform a null check on the `this` argument before - // tail calling to a virtual dispatch stub. This requirement is a consequence of limitations - // in the runtime's ability to map an AV to a NullReferenceException if - // the AV occurs in a dispatch stub that has unmanaged caller. - if (call->IsVirtualStub()) - { - call->gtFlags |= GTF_CALL_NULLCHECK; - } - // For the helper-assisted tail calls, we need to push all the arguments // into a single list, and then add a few extra at the beginning or end. // @@ -13177,6 +13177,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) GenTree* newOp2 = gtNewIconNode(-constVal, op1op2->TypeGet()); // -C mulOrDiv->gtOp1 = newOp1; mulOrDiv->gtOp2 = newOp2; + mulOrDiv->SetVNsFromNode(tree); DEBUG_DESTROY_NODE(tree); DEBUG_DESTROY_NODE(op1op2); @@ -13996,6 +13997,12 @@ GenTree* Compiler::fgMorphRetInd(GenTreeUnOp* ret) if (addr->OperIs(GT_ADDR) && addr->gtGetOp1()->OperIs(GT_LCL_VAR)) { + // If struct promotion was undone, adjust the annotations + if (fgGlobalMorph && fgMorphImplicitByRefArgs(addr)) + { + return ind; + } + // If `return` retypes LCL_VAR as a smaller struct it should not set `doNotEnregister` on that // LclVar. // Example: in `Vector128:AsVector2` we have RETURN SIMD8(OBJ SIMD8(ADDR byref(LCL_VAR SIMD16))). @@ -17661,6 +17668,8 @@ void Compiler::fgRetypeImplicitByRefArgs() void Compiler::fgMarkDemotedImplicitByRefArgs() { + JITDUMP("\n*************** In fgMarkDemotedImplicitByRefArgs()\n"); + #if (defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI)) || defined(TARGET_ARM64) for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) @@ -17669,6 +17678,8 @@ void Compiler::fgMarkDemotedImplicitByRefArgs() if (lvaIsImplicitByRefLocal(lclNum)) { + JITDUMP("Clearing annotation for V%02d\n", lclNum); + if (varDsc->lvPromoted) { // The parameter is simply a pointer now, so clear lvPromoted. It was left set @@ -17695,7 +17706,8 @@ void Compiler::fgMarkDemotedImplicitByRefArgs() LclVarDsc* structVarDsc = &lvaTable[structLclNum]; structVarDsc->lvAddrExposed = false; #ifdef DEBUG - structVarDsc->lvUnusedStruct = true; + structVarDsc->lvUnusedStruct = true; + structVarDsc->lvUndoneStructPromotion = true; #endif // DEBUG unsigned fieldLclStart = structVarDsc->lvFieldLclStart; @@ -17704,6 +17716,8 @@ void Compiler::fgMarkDemotedImplicitByRefArgs() for (unsigned fieldLclNum = fieldLclStart; fieldLclNum < fieldLclStop; ++fieldLclNum) { + JITDUMP("Fixing pointer for field V%02d from V%02d to V%02d\n", fieldLclNum, lclNum, structLclNum); + // Fix the pointer to the parent local. LclVarDsc* fieldVarDsc = &lvaTable[fieldLclNum]; assert(fieldVarDsc->lvParentLcl == lclNum); diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp index 720ec2585c4d61..0d21c1ab6104db 100644 --- a/src/coreclr/jit/objectalloc.cpp +++ b/src/coreclr/jit/objectalloc.cpp @@ -481,6 +481,11 @@ GenTree* ObjectAllocator::MorphAllocObjNodeIntoHelperCall(GenTreeAllocObj* alloc assert(comp->opts.IsReadyToRun()); helperCall->AsCall()->setEntryPoint(entryPoint); } + else + { + assert(helper != CORINFO_HELP_READYTORUN_NEW); // If this is true, then we should have collected a non-null + // entrypoint above + } #endif return helperCall; diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 2eb0fca532ca85..ef5e482df31139 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -107,6 +107,34 @@ int Compiler::getSIMDTypeAlignment(var_types simdType) #endif } +//------------------------------------------------------------------------ +// Get, and allocate if necessary, the SIMD temp used for various operations. +// The temp is allocated as the maximum sized type of all operations required. +// +// Arguments: +// simdType - Required SIMD type +// +// Returns: +// The temp number +// +unsigned Compiler::getSIMDInitTempVarNum(var_types simdType) +{ + if (lvaSIMDInitTempVarNum == BAD_VAR_NUM) + { + JITDUMP("Allocating SIMDInitTempVar as %s\n", varTypeName(simdType)); + lvaSIMDInitTempVarNum = lvaGrabTempWithImplicitUse(false DEBUGARG("SIMDInitTempVar")); + lvaTable[lvaSIMDInitTempVarNum].lvType = simdType; + } + else if (genTypeSize(lvaTable[lvaSIMDInitTempVarNum].lvType) < genTypeSize(simdType)) + { + // We want the largest required type size for the temp. + JITDUMP("Increasing SIMDInitTempVar type size from %s to %s\n", + varTypeName(lvaTable[lvaSIMDInitTempVarNum].lvType), varTypeName(simdType)); + lvaTable[lvaSIMDInitTempVarNum].lvType = simdType; + } + return lvaSIMDInitTempVarNum; +} + //---------------------------------------------------------------------------------- // Return the base type and size of SIMD vector type given its type handle. // diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 0e924073112cda..8b07434c3e87c6 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -4242,11 +4242,12 @@ ValueNum Compiler::fgValueNumberArrIndexVal(GenTree* tree, var_types elemTyp = DecodeElemType(elemTypeEq); var_types indType = (tree == nullptr) ? elemTyp : tree->TypeGet(); ValueNum selectedElem; + unsigned elemWidth = elemTyp == TYP_STRUCT ? info.compCompHnd->getClassSize(elemTypeEq) : genTypeSize(elemTyp); - if (fldSeq == FieldSeqStore::NotAField()) + if ((fldSeq == FieldSeqStore::NotAField()) || (genTypeSize(indType) > elemWidth)) { // This doesn't represent a proper array access - JITDUMP(" *** NotAField sequence encountered in fgValueNumberArrIndexVal\n"); + JITDUMP(" *** Not a proper arrray access encountered in fgValueNumberArrIndexVal\n"); // a new unique value number selectedElem = vnStore->VNForExpr(compCurBB, elemTyp); @@ -7116,6 +7117,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) unsigned lhsLclNum = lclVarTree->GetLclNum(); FieldSeqNode* lhsFldSeq = nullptr; unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree); + LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclNum); // If it's excluded from SSA, don't need to do anything. if (lvaInSsa(lhsLclNum) && lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM) { @@ -7176,9 +7178,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) } else { - rhsVNPair = lvaTable[rhsLclVarTree->GetLclNum()] - .GetPerSsaData(rhsLclVarTree->GetSsaNum()) - ->m_vnPair; + rhsVNPair = rhsVarDsc->GetPerSsaData(rhsLclVarTree->GetSsaNum())->m_vnPair; var_types indType = rhsLclVarTree->TypeGet(); rhsVNPair = vnStore->VNPairApplySelectors(rhsVNPair, rhsFldSeq, indType); @@ -7186,7 +7186,6 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) } else { - rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, rhs->TypeGet())); isNewUniq = true; } } @@ -7205,9 +7204,7 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) } else { - rhsVNPair = lvaTable[rhsLclVarTree->GetLclNum()] - .GetPerSsaData(rhsLclVarTree->GetSsaNum()) - ->m_vnPair; + rhsVNPair = rhsVarDsc->GetPerSsaData(rhsLclVarTree->GetSsaNum())->m_vnPair; var_types indType = rhsLclVarTree->TypeGet(); rhsVNPair = vnStore->VNPairApplySelectors(rhsVNPair, rhsFldSeq, indType); @@ -7273,6 +7270,11 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) isNewUniq = true; } + if (!isNewUniq && (lclVarTree != nullptr) && (rhsLclVarTree != nullptr)) + { + isNewUniq = fgValueNumberIsStructReinterpretation(lclVarTree, rhsLclVarTree); + } + if (isNewUniq) { rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet())); @@ -7293,14 +7295,13 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) } else { - ValueNumPair oldLhsVNPair = - lvaTable[lhsLclNum].GetPerSsaData(lclVarTree->GetSsaNum())->m_vnPair; + ValueNumPair oldLhsVNPair = lhsVarDsc->GetPerSsaData(lclVarTree->GetSsaNum())->m_vnPair; rhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, lhsFldSeq, rhsVNPair, lclVarTree->TypeGet(), compCurBB); } } - lvaTable[lhsLclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = vnStore->VNPNormalPair(rhsVNPair); + lhsVarDsc->GetPerSsaData(lclDefSsaNum)->m_vnPair = vnStore->VNPNormalPair(rhsVNPair); #ifdef DEBUG if (verbose) @@ -7338,6 +7339,67 @@ void Compiler::fgValueNumberBlockAssignment(GenTree* tree) } } +//------------------------------------------------------------------------ +// fgValueNumberIsStructReinterpretation: Checks if there is a struct reinterpretation that prevent VN propagation. +// +// Arguments: +// lhsLclVarTree - a lcl var tree on the lhs of the asg; +// rhsLclVarTree - a lcl var tree on the rhs of the asg; +// +// Return Value: +// True if the locals have different struct types and VN can't use rhs VN for lhs VN. +// False if locals have the same struct type or if this ASG is not a struct ASG. +// +bool Compiler::fgValueNumberIsStructReinterpretation(GenTreeLclVarCommon* lhsLclVarTree, + GenTreeLclVarCommon* rhsLclVarTree) +{ + assert(lhsLclVarTree != nullptr); + assert(rhsLclVarTree != nullptr); + + if (rhsLclVarTree->TypeGet() == TYP_STRUCT) + { + if (rhsLclVarTree->TypeGet() == lhsLclVarTree->TypeGet()) + { + if (lhsLclVarTree->isLclField() || rhsLclVarTree->isLclField()) + { + // Jit does not have a real support for `LCL_FLD struct [FldSeq]` because it can't determinate their + // size + // when the fieldSeq is `NotAField`, but by mistake we could have + // `BLK(ADDR byref(LCL_FLD struct Fseq[]))` nowadays in out IR. + // Generate a unique VN for now, it currently won't match the other side, + // otherwise we would not have 'OBJ struct2 (ADDR(LCL_FLD struct1))` cast. + return true; + } + + assert(lhsLclVarTree->OperIs(GT_LCL_VAR)); + assert(rhsLclVarTree->OperIs(GT_LCL_VAR)); + + const LclVarDsc* lhsVarDsc = lvaGetDesc(lhsLclVarTree); + const LclVarDsc* rhsVarDsc = lvaGetDesc(rhsLclVarTree); + assert(rhsVarDsc->TypeGet() == TYP_STRUCT); + assert(lhsVarDsc->TypeGet() == TYP_STRUCT); + + CORINFO_CLASS_HANDLE rhsStructHnd = rhsVarDsc->GetStructHnd(); + CORINFO_CLASS_HANDLE lhsStructHnd = lhsVarDsc->GetStructHnd(); + + if (rhsStructHnd != lhsStructHnd) + { + // This can occur for nested structs or for unsafe casts, when we have IR like + // struct1 = struct2. + // Use an unique value number for the old map, as we don't have information about + // the dst field values using dst FIELD_HANDLE. + // Note that other asignments, like struct1 = IND struct(ADDR(LCL_VAR long)) + // will be handled in `VNPairApplySelectorsAssign`, here we care only about + // `LCL_VAR structX = (*)LCL_VAR structY` cases. + JITDUMP(" *** Different struct handles for Dst/Src of COPYBLK\n"); + return true; + } + } + } + + return false; +} + void Compiler::fgValueNumberTree(GenTree* tree) { genTreeOps oper = tree->OperGet(); @@ -7989,12 +8051,10 @@ void Compiler::fgValueNumberTree(GenTree* tree) rhsVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lclVarTree->TypeGet())); } - unsigned lclDefSsaNum; ValueNumPair newLhsVNPair; if (isEntire) { newLhsVNPair = rhsVNPair; - lclDefSsaNum = lclVarTree->GetSsaNum(); } else { @@ -8003,12 +8063,13 @@ void Compiler::fgValueNumberTree(GenTree* tree) ValueNumPair oldLhsVNPair = lvaTable[lclVarTree->GetLclNum()] .GetPerSsaData(lclVarTree->GetSsaNum()) ->m_vnPair; - lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree); newLhsVNPair = vnStore->VNPairApplySelectorsAssign(oldLhsVNPair, fieldSeq, rhsVNPair, lhs->TypeGet(), compCurBB); } + unsigned lclDefSsaNum = GetSsaNumForLocalVarDef(lclVarTree); + if (lclDefSsaNum != SsaConfig::RESERVED_SSA_NUM) { lvaTable[lclNum].GetPerSsaData(lclDefSsaNum)->m_vnPair = newLhsVNPair; @@ -9764,25 +9825,25 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc) vnf = VNF_Dbl2Int; break; case CORINFO_HELP_DBL2INT_OVF: - vnf = VNF_Dbl2Int; + vnf = VNF_Dbl2IntOvf; break; case CORINFO_HELP_DBL2LNG: vnf = VNF_Dbl2Lng; break; case CORINFO_HELP_DBL2LNG_OVF: - vnf = VNF_Dbl2Lng; + vnf = VNF_Dbl2LngOvf; break; case CORINFO_HELP_DBL2UINT: vnf = VNF_Dbl2UInt; break; case CORINFO_HELP_DBL2UINT_OVF: - vnf = VNF_Dbl2UInt; + vnf = VNF_Dbl2UIntOvf; break; case CORINFO_HELP_DBL2ULNG: vnf = VNF_Dbl2ULng; break; case CORINFO_HELP_DBL2ULNG_OVF: - vnf = VNF_Dbl2ULng; + vnf = VNF_Dbl2ULngOvf; break; case CORINFO_HELP_FLTREM: vnf = VNFunc(GT_MOD); diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h index 6b5c89bbbbf485..6b2fa5236f3a17 100644 --- a/src/coreclr/jit/valuenumfuncs.h +++ b/src/coreclr/jit/valuenumfuncs.h @@ -75,6 +75,10 @@ ValueNumFuncDef(Dbl2Int, 1, false, false, false) ValueNumFuncDef(Dbl2UInt, 1, false, false, false) ValueNumFuncDef(Dbl2Lng, 1, false, false, false) ValueNumFuncDef(Dbl2ULng, 1, false, false, false) +ValueNumFuncDef(Dbl2IntOvf, 1, false, false, false) +ValueNumFuncDef(Dbl2UIntOvf, 1, false, false, false) +ValueNumFuncDef(Dbl2LngOvf, 1, false, false, false) +ValueNumFuncDef(Dbl2ULngOvf, 1, false, false, false) ValueNumFuncDef(FltRound, 1, false, false, false) ValueNumFuncDef(DblRound, 1, false, false, false) diff --git a/src/coreclr/md/enc/pdbheap.cpp b/src/coreclr/md/enc/pdbheap.cpp index 962472ac65a2e0..a95cf4ccefd6da 100644 --- a/src/coreclr/md/enc/pdbheap.cpp +++ b/src/coreclr/md/enc/pdbheap.cpp @@ -26,6 +26,16 @@ HRESULT PdbHeap::SetData(PORT_PDB_STREAM* data) (sizeof(ULONG) * data->typeSystemTableRowsSize); m_data = new BYTE[m_size]; +#if BIGENDIAN + PORT_PDB_STREAM swappedData = *data; + SwapGuid(&swappedData.id.pdbGuid); + swappedData.id.pdbTimeStamp = VAL32(swappedData.id.pdbTimeStamp); + swappedData.entryPoint = VAL32(swappedData.entryPoint); + swappedData.referencedTypeSystemTables = VAL64(swappedData.referencedTypeSystemTables); + // typeSystemTableRows and typeSystemTableRowsSize handled below + data = &swappedData; +#endif + ULONG offset = 0; if (memcpy_s(m_data + offset, m_size, &data->id, sizeof(data->id))) return E_FAIL; @@ -39,9 +49,17 @@ HRESULT PdbHeap::SetData(PORT_PDB_STREAM* data) return E_FAIL; offset += sizeof(data->referencedTypeSystemTables); +#if !BIGENDIAN if (memcpy_s(m_data + offset, m_size, data->typeSystemTableRows, sizeof(ULONG) * data->typeSystemTableRowsSize)) return E_FAIL; offset += sizeof(ULONG) * data->typeSystemTableRowsSize; +#else + for (int i = 0; i < data->typeSystemTableRowsSize; i++) + { + SET_UNALIGNED_VAL32(m_data + offset, data->typeSystemTableRows[i]); + offset += sizeof(ULONG); + } +#endif _ASSERTE(offset == m_size); diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index cd96f5753cc8fd..e59e406d14f907 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -432,13 +432,22 @@ PALAPI PAL_SetShutdownCallback( IN PSHUTDOWN_CALLBACK callback); +// Must be the same as the copy in excep.h and the WriteDumpFlags enum in the diagnostics repo +enum +{ + GenerateDumpFlagsNone = 0x00, + GenerateDumpFlagsLoggingEnabled = 0x01, + GenerateDumpFlagsVerboseLoggingEnabled = 0x02, + GenerateDumpFlagsCrashReportEnabled = 0x04 +}; + PALIMPORT BOOL PALAPI PAL_GenerateCoreDump( IN LPCSTR dumpName, IN INT dumpType, - IN BOOL diag); + IN ULONG32 flags); typedef VOID (*PPAL_STARTUP_CALLBACK)( char *modulePath, diff --git a/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp b/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp index 0499684f403d4b..c509c3c16cd529 100644 --- a/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp +++ b/src/coreclr/pal/prebuilt/idl/cordebug_i.cpp @@ -1,3 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ @@ -7,10 +9,10 @@ /* File created by MIDL compiler version 8.01.0622 */ /* Compiler settings for cordebug.idl: - Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ @@ -21,7 +23,7 @@ #ifdef __cplusplus extern "C"{ -#endif +#endif #include @@ -251,6 +253,9 @@ MIDL_DEFINE_GUID(IID, IID_ICorDebugThread3,0xF8544EC3,0x5E4E,0x46c7,0x8D,0x3E,0x MIDL_DEFINE_GUID(IID, IID_ICorDebugThread4,0x1A1F204B,0x1C66,0x4637,0x82,0x3F,0x3E,0xE6,0xC7,0x44,0xA6,0x9C); +MIDL_DEFINE_GUID(IID, IID_ICorDebugThread5,0xF98421C4,0xE506,0x4D24,0x91,0x6F,0x02,0x37,0xEE,0x85,0x3E,0xC6); + + MIDL_DEFINE_GUID(IID, IID_ICorDebugStackWalk,0xA0647DE9,0x55DE,0x4816,0x92,0x9C,0x38,0x52,0x71,0xC6,0x4C,0xF7); @@ -480,6 +485,3 @@ MIDL_DEFINE_GUID(CLSID, CLSID_EmbeddedCLRCorDebug,0x211f1254,0xbc7e,0x4af5,0xb9, #ifdef __cplusplus } #endif - - - diff --git a/src/coreclr/pal/prebuilt/inc/cordebug.h b/src/coreclr/pal/prebuilt/inc/cordebug.h index ed5c428df0e972..df876984714400 100644 --- a/src/coreclr/pal/prebuilt/inc/cordebug.h +++ b/src/coreclr/pal/prebuilt/inc/cordebug.h @@ -1,14 +1,15 @@ - +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0622 */ /* Compiler settings for cordebug.idl: - Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ @@ -41,7 +42,7 @@ #pragma once #endif -/* Forward Declarations */ +/* Forward Declarations */ #ifndef __ICorDebugDataTarget_FWD_DEFINED__ #define __ICorDebugDataTarget_FWD_DEFINED__ @@ -477,6 +478,13 @@ typedef interface ICorDebugThread4 ICorDebugThread4; #endif /* __ICorDebugThread4_FWD_DEFINED__ */ +#ifndef __ICorDebugThread5_FWD_DEFINED__ +#define __ICorDebugThread5_FWD_DEFINED__ +typedef interface ICorDebugThread5 ICorDebugThread5; + +#endif /* __ICorDebugThread5_FWD_DEFINED__ */ + + #ifndef __ICorDebugStackWalk_FWD_DEFINED__ #define __ICorDebugStackWalk_FWD_DEFINED__ typedef interface ICorDebugStackWalk ICorDebugStackWalk; @@ -1242,11 +1250,11 @@ typedef interface ICorDebugModule3 ICorDebugModule3; #ifdef __cplusplus extern "C"{ -#endif +#endif /* interface __MIDL_itf_cordebug_0000_0000 */ -/* [local] */ +/* [local] */ #if 0 typedef UINT32 mdToken; @@ -1300,7 +1308,7 @@ typedef struct _COR_IL_MAP #endif //_COR_IL_MAP #ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_ #define _COR_DEBUG_IL_TO_NATIVE_MAP_ -typedef +typedef enum CorDebugIlToNativeMappingTypes { NO_MAPPING = -1, @@ -1317,7 +1325,7 @@ typedef struct COR_DEBUG_IL_TO_NATIVE_MAP #endif // _COR_DEBUG_IL_TO_NATIVE_MAP_ #define REMOTE_DEBUGGING_DLL_ENTRY L"Software\\Microsoft\\.NETFramework\\Debugger\\ActivateRemoteDebugging" -typedef +typedef enum CorDebugJITCompilerFlags { CORDEBUG_JIT_DEFAULT = 0x1, @@ -1325,20 +1333,21 @@ enum CorDebugJITCompilerFlags CORDEBUG_JIT_ENABLE_ENC = 0x7 } CorDebugJITCompilerFlags; -typedef +typedef enum CorDebugJITCompilerFlagsDecprecated { CORDEBUG_JIT_TRACK_DEBUG_INFO = 0x1 } CorDebugJITCompilerFlagsDeprecated; -typedef +typedef enum CorDebugNGENPolicy { DISABLE_LOCAL_NIC = 1 } CorDebugNGENPolicy; #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) + @@ -1412,7 +1421,7 @@ typedef ULONG64 CORDB_REGISTER; typedef DWORD CORDB_CONTINUE_STATUS; -typedef +typedef enum CorDebugBlockingReason { BLOCKING_NONE = 0, @@ -1450,9 +1459,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0000_v0_0_s_ifspec; #define __ICorDebugDataTarget_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugPlatform { CORDB_PLATFORM_WINDOWS_X86 = 0, @@ -1466,72 +1475,72 @@ enum CorDebugPlatform CORDB_PLATFORM_POSIX_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM64 + 1 ) , CORDB_PLATFORM_POSIX_X86 = ( CORDB_PLATFORM_POSIX_AMD64 + 1 ) , CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , - CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) + CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) } CorDebugPlatform; EXTERN_C const IID IID_ICorDebugDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FE06DC28-49FB-4636-A4A3-E80DB4AE116C") ICorDebugDataTarget : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetPlatform( + virtual HRESULT STDMETHODCALLTYPE GetPlatform( /* [out] */ CorDebugPlatform *pTargetPlatform) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReadVirtual( + + virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTargetVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget * This); - - HRESULT ( STDMETHODCALLTYPE *GetPlatform )( + + HRESULT ( STDMETHODCALLTYPE *GetPlatform )( ICorDebugDataTarget * This, /* [out] */ CorDebugPlatform *pTargetPlatform); - - HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICorDebugDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead); - - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext); - + END_INTERFACE } ICorDebugDataTargetVtbl; @@ -1540,29 +1549,29 @@ EXTERN_C const IID IID_ICorDebugDataTarget; CONST_VTBL struct ICorDebugDataTargetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget_GetPlatform(This,pTargetPlatform) \ - ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) + ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) #define ICorDebugDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ - ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) + ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) #define ICorDebugDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ - ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) + ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) #endif /* COBJMACROS */ @@ -1579,63 +1588,63 @@ EXTERN_C const IID IID_ICorDebugDataTarget; #define __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ /* interface ICorDebugStaticFieldSymbol */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CBF9DA63-F68D-4BBB-A21C-15A45EAADF5B") ICorDebugStaticFieldSymbol : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAddress( + + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pRVA) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStaticFieldSymbolVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStaticFieldSymbol * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStaticFieldSymbol * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStaticFieldSymbol * This); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugStaticFieldSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugStaticFieldSymbol * This, /* [out] */ ULONG32 *pcbSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugStaticFieldSymbol * This, /* [out] */ CORDB_ADDRESS *pRVA); - + END_INTERFACE } ICorDebugStaticFieldSymbolVtbl; @@ -1644,29 +1653,29 @@ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; CONST_VTBL struct ICorDebugStaticFieldSymbolVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStaticFieldSymbol_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStaticFieldSymbol_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStaticFieldSymbol_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStaticFieldSymbol_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugStaticFieldSymbol_GetSize(This,pcbSize) \ - ( (This)->lpVtbl -> GetSize(This,pcbSize) ) + ( (This)->lpVtbl -> GetSize(This,pcbSize) ) #define ICorDebugStaticFieldSymbol_GetAddress(This,pRVA) \ - ( (This)->lpVtbl -> GetAddress(This,pRVA) ) + ( (This)->lpVtbl -> GetAddress(This,pRVA) ) #endif /* COBJMACROS */ @@ -1683,63 +1692,63 @@ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; #define __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ /* interface ICorDebugInstanceFieldSymbol */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A074096B-3ADC-4485-81DA-68C7A4EA52DB") ICorDebugInstanceFieldSymbol : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOffset( + + virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ ULONG32 *pcbOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugInstanceFieldSymbolVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInstanceFieldSymbol * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInstanceFieldSymbol * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInstanceFieldSymbol * This); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugInstanceFieldSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugInstanceFieldSymbol * This, /* [out] */ ULONG32 *pcbSize); - - HRESULT ( STDMETHODCALLTYPE *GetOffset )( + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugInstanceFieldSymbol * This, /* [out] */ ULONG32 *pcbOffset); - + END_INTERFACE } ICorDebugInstanceFieldSymbolVtbl; @@ -1748,29 +1757,29 @@ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; CONST_VTBL struct ICorDebugInstanceFieldSymbolVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugInstanceFieldSymbol_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInstanceFieldSymbol_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInstanceFieldSymbol_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInstanceFieldSymbol_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugInstanceFieldSymbol_GetSize(This,pcbSize) \ - ( (This)->lpVtbl -> GetSize(This,pcbSize) ) + ( (This)->lpVtbl -> GetSize(This,pcbSize) ) #define ICorDebugInstanceFieldSymbol_GetOffset(This,pcbOffset) \ - ( (This)->lpVtbl -> GetOffset(This,pcbOffset) ) + ( (This)->lpVtbl -> GetOffset(This,pcbOffset) ) #endif /* COBJMACROS */ @@ -1787,76 +1796,76 @@ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; #define __ICorDebugVariableSymbol_INTERFACE_DEFINED__ /* interface ICorDebugVariableSymbol */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugVariableSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("707E8932-1163-48D9-8A93-F5B1F480FBB7") ICorDebugVariableSymbol : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetValue( + + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [in] */ ULONG32 offset, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [out] */ ULONG32 *pcbValue, /* [length_is][size_is][out] */ BYTE pValue[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetValue( + + virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ ULONG32 offset, /* [in] */ DWORD threadID, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [size_is][in] */ BYTE pValue[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( /* [out] */ ULONG32 *pSlotIndex) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVariableSymbolVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableSymbol * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableSymbol * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableSymbol * This); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugVariableSymbol * This, /* [out] */ ULONG32 *pcbValue); - - HRESULT ( STDMETHODCALLTYPE *GetValue )( + + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 offset, /* [in] */ ULONG32 cbContext, @@ -1864,8 +1873,8 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; /* [in] */ ULONG32 cbValue, /* [out] */ ULONG32 *pcbValue, /* [length_is][size_is][out] */ BYTE pValue[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetValue )( + + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 offset, /* [in] */ DWORD threadID, @@ -1873,11 +1882,11 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [size_is][in] */ BYTE pValue[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( ICorDebugVariableSymbol * This, /* [out] */ ULONG32 *pSlotIndex); - + END_INTERFACE } ICorDebugVariableSymbolVtbl; @@ -1886,35 +1895,35 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; CONST_VTBL struct ICorDebugVariableSymbolVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVariableSymbol_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableSymbol_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableSymbol_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableSymbol_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugVariableSymbol_GetSize(This,pcbValue) \ - ( (This)->lpVtbl -> GetSize(This,pcbValue) ) + ( (This)->lpVtbl -> GetSize(This,pcbValue) ) #define ICorDebugVariableSymbol_GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) \ - ( (This)->lpVtbl -> GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) ) + ( (This)->lpVtbl -> GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) ) #define ICorDebugVariableSymbol_SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) \ - ( (This)->lpVtbl -> SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) ) + ( (This)->lpVtbl -> SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) ) #define ICorDebugVariableSymbol_GetSlotIndex(This,pSlotIndex) \ - ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) #endif /* COBJMACROS */ @@ -1931,52 +1940,52 @@ EXTERN_C const IID IID_ICorDebugVariableSymbol; #define __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ /* interface ICorDebugMemoryBuffer */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMemoryBuffer; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("677888B3-D160-4B8C-A73B-D79E6AAA1D13") ICorDebugMemoryBuffer : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetStartAddress( + virtual HRESULT STDMETHODCALLTYPE GetStartAddress( /* [out] */ LPCVOID *address) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbBufferLength) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMemoryBufferVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMemoryBuffer * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMemoryBuffer * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMemoryBuffer * This); - - HRESULT ( STDMETHODCALLTYPE *GetStartAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetStartAddress )( ICorDebugMemoryBuffer * This, /* [out] */ LPCVOID *address); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugMemoryBuffer * This, /* [out] */ ULONG32 *pcbBufferLength); - + END_INTERFACE } ICorDebugMemoryBufferVtbl; @@ -1985,26 +1994,26 @@ EXTERN_C const IID IID_ICorDebugMemoryBuffer; CONST_VTBL struct ICorDebugMemoryBufferVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMemoryBuffer_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMemoryBuffer_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMemoryBuffer_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMemoryBuffer_GetStartAddress(This,address) \ - ( (This)->lpVtbl -> GetStartAddress(This,address) ) + ( (This)->lpVtbl -> GetStartAddress(This,address) ) #define ICorDebugMemoryBuffer_GetSize(This,pcbBufferLength) \ - ( (This)->lpVtbl -> GetSize(This,pcbBufferLength) ) + ( (This)->lpVtbl -> GetSize(This,pcbBufferLength) ) #endif /* COBJMACROS */ @@ -2021,102 +2030,102 @@ EXTERN_C const IID IID_ICorDebugMemoryBuffer; #define __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ /* interface ICorDebugMergedAssemblyRecord */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FAA8637B-3BBE-4671-8E26-3B59875B922A") ICorDebugMergedAssemblyRecord : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetSimpleName( + virtual HRESULT STDMETHODCALLTYPE GetSimpleName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersion( + + virtual HRESULT STDMETHODCALLTYPE GetVersion( /* [out] */ USHORT *pMajor, /* [out] */ USHORT *pMinor, /* [out] */ USHORT *pBuild, /* [out] */ USHORT *pRevision) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCulture( + + virtual HRESULT STDMETHODCALLTYPE GetCulture( /* [in] */ ULONG32 cchCulture, /* [out] */ ULONG32 *pcchCulture, /* [length_is][size_is][out] */ WCHAR szCulture[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetPublicKey( + + virtual HRESULT STDMETHODCALLTYPE GetPublicKey( /* [in] */ ULONG32 cbPublicKey, /* [out] */ ULONG32 *pcbPublicKey, /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetPublicKeyToken( + + virtual HRESULT STDMETHODCALLTYPE GetPublicKeyToken( /* [in] */ ULONG32 cbPublicKeyToken, /* [out] */ ULONG32 *pcbPublicKeyToken, /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetIndex( + + virtual HRESULT STDMETHODCALLTYPE GetIndex( /* [out] */ ULONG32 *pIndex) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMergedAssemblyRecordVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMergedAssemblyRecord * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMergedAssemblyRecord * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMergedAssemblyRecord * This); - - HRESULT ( STDMETHODCALLTYPE *GetSimpleName )( + + HRESULT ( STDMETHODCALLTYPE *GetSimpleName )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetVersion )( + + HRESULT ( STDMETHODCALLTYPE *GetVersion )( ICorDebugMergedAssemblyRecord * This, /* [out] */ USHORT *pMajor, /* [out] */ USHORT *pMinor, /* [out] */ USHORT *pBuild, /* [out] */ USHORT *pRevision); - - HRESULT ( STDMETHODCALLTYPE *GetCulture )( + + HRESULT ( STDMETHODCALLTYPE *GetCulture )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cchCulture, /* [out] */ ULONG32 *pcchCulture, /* [length_is][size_is][out] */ WCHAR szCulture[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetPublicKey )( + + HRESULT ( STDMETHODCALLTYPE *GetPublicKey )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cbPublicKey, /* [out] */ ULONG32 *pcbPublicKey, /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetPublicKeyToken )( + + HRESULT ( STDMETHODCALLTYPE *GetPublicKeyToken )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cbPublicKeyToken, /* [out] */ ULONG32 *pcbPublicKeyToken, /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetIndex )( + + HRESULT ( STDMETHODCALLTYPE *GetIndex )( ICorDebugMergedAssemblyRecord * This, /* [out] */ ULONG32 *pIndex); - + END_INTERFACE } ICorDebugMergedAssemblyRecordVtbl; @@ -2125,38 +2134,38 @@ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; CONST_VTBL struct ICorDebugMergedAssemblyRecordVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMergedAssemblyRecord_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMergedAssemblyRecord_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMergedAssemblyRecord_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMergedAssemblyRecord_GetSimpleName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetSimpleName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetSimpleName(This,cchName,pcchName,szName) ) #define ICorDebugMergedAssemblyRecord_GetVersion(This,pMajor,pMinor,pBuild,pRevision) \ - ( (This)->lpVtbl -> GetVersion(This,pMajor,pMinor,pBuild,pRevision) ) + ( (This)->lpVtbl -> GetVersion(This,pMajor,pMinor,pBuild,pRevision) ) #define ICorDebugMergedAssemblyRecord_GetCulture(This,cchCulture,pcchCulture,szCulture) \ - ( (This)->lpVtbl -> GetCulture(This,cchCulture,pcchCulture,szCulture) ) + ( (This)->lpVtbl -> GetCulture(This,cchCulture,pcchCulture,szCulture) ) #define ICorDebugMergedAssemblyRecord_GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) \ - ( (This)->lpVtbl -> GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) ) + ( (This)->lpVtbl -> GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) ) #define ICorDebugMergedAssemblyRecord_GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) \ - ( (This)->lpVtbl -> GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) ) + ( (This)->lpVtbl -> GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) ) #define ICorDebugMergedAssemblyRecord_GetIndex(This,pIndex) \ - ( (This)->lpVtbl -> GetIndex(This,pIndex) ) + ( (This)->lpVtbl -> GetIndex(This,pIndex) ) #endif /* COBJMACROS */ @@ -2173,138 +2182,138 @@ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; #define __ICorDebugSymbolProvider_INTERFACE_DEFINED__ /* interface ICorDebugSymbolProvider */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugSymbolProvider; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3948A999-FD8A-4C38-A708-8A71E9B04DBB") ICorDebugSymbolProvider : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldSymbols( + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldSymbols( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetInstanceFieldSymbols( + + virtual HRESULT STDMETHODCALLTYPE GetInstanceFieldSymbols( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMethodLocalSymbols( + + virtual HRESULT STDMETHODCALLTYPE GetMethodLocalSymbols( /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMethodParameterSymbols( + + virtual HRESULT STDMETHODCALLTYPE GetMethodParameterSymbols( /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMergedAssemblyRecords( + + virtual HRESULT STDMETHODCALLTYPE GetMergedAssemblyRecords( /* [in] */ ULONG32 cRequestedRecords, /* [out] */ ULONG32 *pcFetchedRecords, /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMethodProps( + + virtual HRESULT STDMETHODCALLTYPE GetMethodProps( /* [in] */ ULONG32 codeRva, /* [out] */ mdToken *pMethodToken, /* [out] */ ULONG32 *pcGenericParams, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeProps( + + virtual HRESULT STDMETHODCALLTYPE GetTypeProps( /* [in] */ ULONG32 vtableRva, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeRange( + + virtual HRESULT STDMETHODCALLTYPE GetCodeRange( /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartAddress, ULONG32 *pCodeSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageBytes( + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageBytes( /* [in] */ CORDB_ADDRESS rva, /* [in] */ ULONG32 length, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObjectSize( + + virtual HRESULT STDMETHODCALLTYPE GetObjectSize( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [out] */ ULONG32 *pObjectSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageMetadata( + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageMetadata( /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugSymbolProviderVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugSymbolProvider * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugSymbolProvider * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugSymbolProvider * This); - - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldSymbols )( + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetInstanceFieldSymbols )( + + HRESULT ( STDMETHODCALLTYPE *GetInstanceFieldSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetMethodLocalSymbols )( + + HRESULT ( STDMETHODCALLTYPE *GetMethodLocalSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetMethodParameterSymbols )( + + HRESULT ( STDMETHODCALLTYPE *GetMethodParameterSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetMergedAssemblyRecords )( + + HRESULT ( STDMETHODCALLTYPE *GetMergedAssemblyRecords )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cRequestedRecords, /* [out] */ ULONG32 *pcFetchedRecords, /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetMethodProps )( + + HRESULT ( STDMETHODCALLTYPE *GetMethodProps )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 codeRva, /* [out] */ mdToken *pMethodToken, @@ -2312,36 +2321,36 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider; /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetTypeProps )( + + HRESULT ( STDMETHODCALLTYPE *GetTypeProps )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 vtableRva, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetCodeRange )( + + HRESULT ( STDMETHODCALLTYPE *GetCodeRange )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartAddress, ULONG32 *pCodeSize); - - HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageBytes )( + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageBytes )( ICorDebugSymbolProvider * This, /* [in] */ CORDB_ADDRESS rva, /* [in] */ ULONG32 length, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); - - HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [out] */ ULONG32 *pObjectSize); - - HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageMetadata )( + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageMetadata )( ICorDebugSymbolProvider * This, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); - + END_INTERFACE } ICorDebugSymbolProviderVtbl; @@ -2350,53 +2359,53 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider; CONST_VTBL struct ICorDebugSymbolProviderVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugSymbolProvider_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugSymbolProvider_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugSymbolProvider_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugSymbolProvider_GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ - ( (This)->lpVtbl -> GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + ( (This)->lpVtbl -> GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) \ - ( (This)->lpVtbl -> GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) ) + ( (This)->lpVtbl -> GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) ) #define ICorDebugSymbolProvider_GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) \ - ( (This)->lpVtbl -> GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) ) + ( (This)->lpVtbl -> GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) ) #define ICorDebugSymbolProvider_GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) \ - ( (This)->lpVtbl -> GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) ) + ( (This)->lpVtbl -> GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) ) #define ICorDebugSymbolProvider_GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) \ - ( (This)->lpVtbl -> GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) ) + ( (This)->lpVtbl -> GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) ) #define ICorDebugSymbolProvider_GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) \ - ( (This)->lpVtbl -> GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) ) + ( (This)->lpVtbl -> GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) ) #define ICorDebugSymbolProvider_GetObjectSize(This,cbSignature,typeSig,pObjectSize) \ - ( (This)->lpVtbl -> GetObjectSize(This,cbSignature,typeSig,pObjectSize) ) + ( (This)->lpVtbl -> GetObjectSize(This,cbSignature,typeSig,pObjectSize) ) #define ICorDebugSymbolProvider_GetAssemblyImageMetadata(This,ppMemoryBuffer) \ - ( (This)->lpVtbl -> GetAssemblyImageMetadata(This,ppMemoryBuffer) ) + ( (This)->lpVtbl -> GetAssemblyImageMetadata(This,ppMemoryBuffer) ) #endif /* COBJMACROS */ @@ -2413,56 +2422,56 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider; #define __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ /* interface ICorDebugSymbolProvider2 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugSymbolProvider2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F9801807-4764-4330-9E67-4F685094165E") ICorDebugSymbolProvider2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetGenericDictionaryInfo( + virtual HRESULT STDMETHODCALLTYPE GetGenericDictionaryInfo( /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFrameProps( + + virtual HRESULT STDMETHODCALLTYPE GetFrameProps( /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartRva, /* [out] */ ULONG32 *pParentFrameStartRva) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugSymbolProvider2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugSymbolProvider2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugSymbolProvider2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugSymbolProvider2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetGenericDictionaryInfo )( + + HRESULT ( STDMETHODCALLTYPE *GetGenericDictionaryInfo )( ICorDebugSymbolProvider2 * This, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); - - HRESULT ( STDMETHODCALLTYPE *GetFrameProps )( + + HRESULT ( STDMETHODCALLTYPE *GetFrameProps )( ICorDebugSymbolProvider2 * This, /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartRva, /* [out] */ ULONG32 *pParentFrameStartRva); - + END_INTERFACE } ICorDebugSymbolProvider2Vtbl; @@ -2471,26 +2480,26 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider2; CONST_VTBL struct ICorDebugSymbolProvider2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugSymbolProvider2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugSymbolProvider2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugSymbolProvider2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugSymbolProvider2_GetGenericDictionaryInfo(This,ppMemoryBuffer) \ - ( (This)->lpVtbl -> GetGenericDictionaryInfo(This,ppMemoryBuffer) ) + ( (This)->lpVtbl -> GetGenericDictionaryInfo(This,ppMemoryBuffer) ) #define ICorDebugSymbolProvider2_GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) \ - ( (This)->lpVtbl -> GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) ) + ( (This)->lpVtbl -> GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) ) #endif /* COBJMACROS */ @@ -2507,56 +2516,56 @@ EXTERN_C const IID IID_ICorDebugSymbolProvider2; #define __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ /* interface ICorDebugVirtualUnwinder */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F69126B7-C787-4F6B-AE96-A569786FC670") ICorDebugVirtualUnwinder : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContext( + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContextBuf, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; - + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVirtualUnwinderVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVirtualUnwinder * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVirtualUnwinder * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVirtualUnwinder * This); - - HRESULT ( STDMETHODCALLTYPE *GetContext )( + + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugVirtualUnwinder * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContextBuf, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugVirtualUnwinder * This); - + END_INTERFACE } ICorDebugVirtualUnwinderVtbl; @@ -2565,26 +2574,26 @@ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; CONST_VTBL struct ICorDebugVirtualUnwinderVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVirtualUnwinder_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVirtualUnwinder_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVirtualUnwinder_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVirtualUnwinder_GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) \ - ( (This)->lpVtbl -> GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) ) + ( (This)->lpVtbl -> GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) ) #define ICorDebugVirtualUnwinder_Next(This) \ - ( (This)->lpVtbl -> Next(This) ) + ( (This)->lpVtbl -> Next(This) ) #endif /* COBJMACROS */ @@ -2601,97 +2610,97 @@ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; #define __ICorDebugDataTarget2_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget2 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2eb364da-605b-4e8d-b333-3394c4828d41") ICorDebugDataTarget2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetImageFromPointer( + virtual HRESULT STDMETHODCALLTYPE GetImageFromPointer( /* [in] */ CORDB_ADDRESS addr, /* [out] */ CORDB_ADDRESS *pImageBase, /* [out] */ ULONG32 *pSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetImageLocation( + + virtual HRESULT STDMETHODCALLTYPE GetImageLocation( /* [in] */ CORDB_ADDRESS baseAddress, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSymbolProviderForImage( + + virtual HRESULT STDMETHODCALLTYPE GetSymbolProviderForImage( /* [in] */ CORDB_ADDRESS imageBaseAddress, /* [out] */ ICorDebugSymbolProvider **ppSymProvider) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateThreadIDs( + + virtual HRESULT STDMETHODCALLTYPE EnumerateThreadIDs( /* [in] */ ULONG32 cThreadIds, /* [out] */ ULONG32 *pcThreadIds, /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateVirtualUnwinder( + + virtual HRESULT STDMETHODCALLTYPE CreateVirtualUnwinder( /* [in] */ DWORD nativeThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE initialContext[ ], /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTarget2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetImageFromPointer )( + + HRESULT ( STDMETHODCALLTYPE *GetImageFromPointer )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS addr, /* [out] */ CORDB_ADDRESS *pImageBase, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetImageLocation )( + + HRESULT ( STDMETHODCALLTYPE *GetImageLocation )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS baseAddress, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetSymbolProviderForImage )( + + HRESULT ( STDMETHODCALLTYPE *GetSymbolProviderForImage )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS imageBaseAddress, /* [out] */ ICorDebugSymbolProvider **ppSymProvider); - - HRESULT ( STDMETHODCALLTYPE *EnumerateThreadIDs )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreadIDs )( ICorDebugDataTarget2 * This, /* [in] */ ULONG32 cThreadIds, /* [out] */ ULONG32 *pcThreadIds, /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]); - - HRESULT ( STDMETHODCALLTYPE *CreateVirtualUnwinder )( + + HRESULT ( STDMETHODCALLTYPE *CreateVirtualUnwinder )( ICorDebugDataTarget2 * This, /* [in] */ DWORD nativeThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE initialContext[ ], /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder); - + END_INTERFACE } ICorDebugDataTarget2Vtbl; @@ -2700,35 +2709,35 @@ EXTERN_C const IID IID_ICorDebugDataTarget2; CONST_VTBL struct ICorDebugDataTarget2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget2_GetImageFromPointer(This,addr,pImageBase,pSize) \ - ( (This)->lpVtbl -> GetImageFromPointer(This,addr,pImageBase,pSize) ) + ( (This)->lpVtbl -> GetImageFromPointer(This,addr,pImageBase,pSize) ) #define ICorDebugDataTarget2_GetImageLocation(This,baseAddress,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetImageLocation(This,baseAddress,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetImageLocation(This,baseAddress,cchName,pcchName,szName) ) #define ICorDebugDataTarget2_GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) \ - ( (This)->lpVtbl -> GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) ) + ( (This)->lpVtbl -> GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) ) #define ICorDebugDataTarget2_EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) \ - ( (This)->lpVtbl -> EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) ) + ( (This)->lpVtbl -> EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) ) #define ICorDebugDataTarget2_CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) \ - ( (This)->lpVtbl -> CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) ) + ( (This)->lpVtbl -> CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) ) #endif /* COBJMACROS */ @@ -2745,63 +2754,63 @@ EXTERN_C const IID IID_ICorDebugDataTarget2; #define __ICorDebugLoadedModule_INTERFACE_DEFINED__ /* interface ICorDebugLoadedModule */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugLoadedModule; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("817F343A-6630-4578-96C5-D11BC0EC5EE2") ICorDebugLoadedModule : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( + virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugLoadedModuleVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugLoadedModule * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugLoadedModule * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugLoadedModule * This); - - HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( ICorDebugLoadedModule * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugLoadedModule * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugLoadedModule * This, /* [out] */ ULONG32 *pcBytes); - + END_INTERFACE } ICorDebugLoadedModuleVtbl; @@ -2810,29 +2819,29 @@ EXTERN_C const IID IID_ICorDebugLoadedModule; CONST_VTBL struct ICorDebugLoadedModuleVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugLoadedModule_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugLoadedModule_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugLoadedModule_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugLoadedModule_GetBaseAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) #define ICorDebugLoadedModule_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugLoadedModule_GetSize(This,pcBytes) \ - ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #endif /* COBJMACROS */ @@ -2849,49 +2858,49 @@ EXTERN_C const IID IID_ICorDebugLoadedModule; #define __ICorDebugDataTarget3_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget3 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D05E60C3-848C-4E7D-894E-623320FF6AFA") ICorDebugDataTarget3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetLoadedModules( + virtual HRESULT STDMETHODCALLTYPE GetLoadedModules( /* [in] */ ULONG32 cRequestedModules, /* [out] */ ULONG32 *pcFetchedModules, /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTarget3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetLoadedModules )( + + HRESULT ( STDMETHODCALLTYPE *GetLoadedModules )( ICorDebugDataTarget3 * This, /* [in] */ ULONG32 cRequestedModules, /* [out] */ ULONG32 *pcFetchedModules, /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]); - + END_INTERFACE } ICorDebugDataTarget3Vtbl; @@ -2900,23 +2909,23 @@ EXTERN_C const IID IID_ICorDebugDataTarget3; CONST_VTBL struct ICorDebugDataTarget3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget3_GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) \ - ( (This)->lpVtbl -> GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) ) + ( (This)->lpVtbl -> GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) ) #endif /* COBJMACROS */ @@ -2933,49 +2942,49 @@ EXTERN_C const IID IID_ICorDebugDataTarget3; #define __ICorDebugDataTarget4_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget4 */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("E799DC06-E099-4713-BDD9-906D3CC02CF2") ICorDebugDataTarget4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE VirtualUnwind( + virtual HRESULT STDMETHODCALLTYPE VirtualUnwind( /* [in] */ DWORD threadId, /* [in] */ ULONG32 contextSize, /* [size_is][out][in] */ BYTE *context) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDataTarget4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget4 * This); - - HRESULT ( STDMETHODCALLTYPE *VirtualUnwind )( + + HRESULT ( STDMETHODCALLTYPE *VirtualUnwind )( ICorDebugDataTarget4 * This, /* [in] */ DWORD threadId, /* [in] */ ULONG32 contextSize, /* [size_is][out][in] */ BYTE *context); - + END_INTERFACE } ICorDebugDataTarget4Vtbl; @@ -2984,23 +2993,23 @@ EXTERN_C const IID IID_ICorDebugDataTarget4; CONST_VTBL struct ICorDebugDataTarget4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDataTarget4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget4_VirtualUnwind(This,threadId,contextSize,context) \ - ( (This)->lpVtbl -> VirtualUnwind(This,threadId,contextSize,context) ) + ( (This)->lpVtbl -> VirtualUnwind(This,threadId,contextSize,context) ) #endif /* COBJMACROS */ @@ -3017,87 +3026,87 @@ EXTERN_C const IID IID_ICorDebugDataTarget4; #define __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ /* interface ICorDebugMutableDataTarget */ -/* [unique][local][uuid][object] */ +/* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMutableDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A1B8A756-3CB6-4CCB-979F-3DF999673A59") ICorDebugMutableDataTarget : public ICorDebugDataTarget { public: - virtual HRESULT STDMETHODCALLTYPE WriteVirtual( + virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CORDB_ADDRESS address, /* [size_is][in] */ const BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ const BYTE *pContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged( + + virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged( /* [in] */ DWORD dwThreadId, /* [in] */ CORDB_CONTINUE_STATUS continueStatus) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMutableDataTargetVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMutableDataTarget * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMutableDataTarget * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMutableDataTarget * This); - - HRESULT ( STDMETHODCALLTYPE *GetPlatform )( + + HRESULT ( STDMETHODCALLTYPE *GetPlatform )( ICorDebugMutableDataTarget * This, /* [out] */ CorDebugPlatform *pTargetPlatform); - - HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICorDebugMutableDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead); - - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext); - - HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( ICorDebugMutableDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [size_is][in] */ const BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested); - - HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ const BYTE *pContext); - - HRESULT ( STDMETHODCALLTYPE *ContinueStatusChanged )( + + HRESULT ( STDMETHODCALLTYPE *ContinueStatusChanged )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadId, /* [in] */ CORDB_CONTINUE_STATUS continueStatus); - + END_INTERFACE } ICorDebugMutableDataTargetVtbl; @@ -3106,39 +3115,39 @@ EXTERN_C const IID IID_ICorDebugMutableDataTarget; CONST_VTBL struct ICorDebugMutableDataTargetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMutableDataTarget_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMutableDataTarget_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMutableDataTarget_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMutableDataTarget_GetPlatform(This,pTargetPlatform) \ - ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) + ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) #define ICorDebugMutableDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ - ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) + ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) #define ICorDebugMutableDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ - ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) + ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) #define ICorDebugMutableDataTarget_WriteVirtual(This,address,pBuffer,bytesRequested) \ - ( (This)->lpVtbl -> WriteVirtual(This,address,pBuffer,bytesRequested) ) + ( (This)->lpVtbl -> WriteVirtual(This,address,pBuffer,bytesRequested) ) #define ICorDebugMutableDataTarget_SetThreadContext(This,dwThreadID,contextSize,pContext) \ - ( (This)->lpVtbl -> SetThreadContext(This,dwThreadID,contextSize,pContext) ) + ( (This)->lpVtbl -> SetThreadContext(This,dwThreadID,contextSize,pContext) ) #define ICorDebugMutableDataTarget_ContinueStatusChanged(This,dwThreadId,continueStatus) \ - ( (This)->lpVtbl -> ContinueStatusChanged(This,dwThreadId,continueStatus) ) + ( (This)->lpVtbl -> ContinueStatusChanged(This,dwThreadId,continueStatus) ) #endif /* COBJMACROS */ @@ -3155,59 +3164,59 @@ EXTERN_C const IID IID_ICorDebugMutableDataTarget; #define __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ /* interface ICorDebugMetaDataLocator */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugMetaDataLocator; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("7cef8ba9-2ef7-42bf-973f-4171474f87d9") ICorDebugMetaDataLocator : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetMetaData( + virtual HRESULT STDMETHODCALLTYPE GetMetaData( /* [in] */ LPCWSTR wszImagePath, /* [in] */ DWORD dwImageTimeStamp, /* [in] */ DWORD dwImageSize, /* [in] */ ULONG32 cchPathBuffer, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchPathBuffer, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMetaDataLocatorVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMetaDataLocator * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMetaDataLocator * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMetaDataLocator * This); - - HRESULT ( STDMETHODCALLTYPE *GetMetaData )( + + HRESULT ( STDMETHODCALLTYPE *GetMetaData )( ICorDebugMetaDataLocator * This, /* [in] */ LPCWSTR wszImagePath, /* [in] */ DWORD dwImageTimeStamp, /* [in] */ DWORD dwImageSize, /* [in] */ ULONG32 cchPathBuffer, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchPathBuffer, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]); - + END_INTERFACE } ICorDebugMetaDataLocatorVtbl; @@ -3216,23 +3225,23 @@ EXTERN_C const IID IID_ICorDebugMetaDataLocator; CONST_VTBL struct ICorDebugMetaDataLocatorVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMetaDataLocator_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMetaDataLocator_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMetaDataLocator_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMetaDataLocator_GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) \ - ( (This)->lpVtbl -> GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) ) + ( (This)->lpVtbl -> GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) ) #endif /* COBJMACROS */ @@ -3246,10 +3255,10 @@ EXTERN_C const IID IID_ICorDebugMetaDataLocator; /* interface __MIDL_itf_cordebug_0000_0015 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_c_ifspec; @@ -3259,9 +3268,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_s_ifspec; #define __ICorDebugManagedCallback_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugStepReason { STEP_NORMAL = 0, @@ -3270,10 +3279,10 @@ enum CorDebugStepReason STEP_EXCEPTION_FILTER = ( STEP_CALL + 1 ) , STEP_EXCEPTION_HANDLER = ( STEP_EXCEPTION_FILTER + 1 ) , STEP_INTERCEPT = ( STEP_EXCEPTION_HANDLER + 1 ) , - STEP_EXIT = ( STEP_INTERCEPT + 1 ) + STEP_EXIT = ( STEP_INTERCEPT + 1 ) } CorDebugStepReason; -typedef +typedef enum LoggingLevelEnum { LTraceLevel0 = 0, @@ -3291,253 +3300,253 @@ enum LoggingLevelEnum LPanicLevel = 100 } LoggingLevelEnum; -typedef +typedef enum LogSwitchCallReason { SWITCH_CREATE = 0, SWITCH_MODIFY = ( SWITCH_CREATE + 1 ) , - SWITCH_DELETE = ( SWITCH_MODIFY + 1 ) + SWITCH_DELETE = ( SWITCH_MODIFY + 1 ) } LogSwitchCallReason; EXTERN_C const IID IID_ICorDebugManagedCallback; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f60-7538-11d3-8d5b-00104b35e7ef") ICorDebugManagedCallback : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Breakpoint( + virtual HRESULT STDMETHODCALLTYPE Breakpoint( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE StepComplete( + + virtual HRESULT STDMETHODCALLTYPE StepComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugStepper *pStepper, /* [in] */ CorDebugStepReason reason) = 0; - - virtual HRESULT STDMETHODCALLTYPE Break( + + virtual HRESULT STDMETHODCALLTYPE Break( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; - - virtual HRESULT STDMETHODCALLTYPE Exception( + + virtual HRESULT STDMETHODCALLTYPE Exception( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ BOOL unhandled) = 0; - - virtual HRESULT STDMETHODCALLTYPE EvalComplete( + + virtual HRESULT STDMETHODCALLTYPE EvalComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval) = 0; - - virtual HRESULT STDMETHODCALLTYPE EvalException( + + virtual HRESULT STDMETHODCALLTYPE EvalException( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateProcess( + + virtual HRESULT STDMETHODCALLTYPE CreateProcess( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExitProcess( + + virtual HRESULT STDMETHODCALLTYPE ExitProcess( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateThread( + + virtual HRESULT STDMETHODCALLTYPE CreateThread( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExitThread( + + virtual HRESULT STDMETHODCALLTYPE ExitThread( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; - - virtual HRESULT STDMETHODCALLTYPE LoadModule( + + virtual HRESULT STDMETHODCALLTYPE LoadModule( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnloadModule( + + virtual HRESULT STDMETHODCALLTYPE UnloadModule( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE LoadClass( + + virtual HRESULT STDMETHODCALLTYPE LoadClass( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnloadClass( + + virtual HRESULT STDMETHODCALLTYPE UnloadClass( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c) = 0; - - virtual HRESULT STDMETHODCALLTYPE DebuggerError( + + virtual HRESULT STDMETHODCALLTYPE DebuggerError( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ HRESULT errorHR, /* [in] */ DWORD errorCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE LogMessage( + + virtual HRESULT STDMETHODCALLTYPE LogMessage( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pMessage) = 0; - - virtual HRESULT STDMETHODCALLTYPE LogSwitch( + + virtual HRESULT STDMETHODCALLTYPE LogSwitch( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ ULONG ulReason, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pParentName) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( + + virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExitAppDomain( + + virtual HRESULT STDMETHODCALLTYPE ExitAppDomain( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE LoadAssembly( + + virtual HRESULT STDMETHODCALLTYPE LoadAssembly( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE UnloadAssembly( + + virtual HRESULT STDMETHODCALLTYPE UnloadAssembly( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE ControlCTrap( + + virtual HRESULT STDMETHODCALLTYPE ControlCTrap( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE NameChange( + + virtual HRESULT STDMETHODCALLTYPE NameChange( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE UpdateModuleSymbols( + + virtual HRESULT STDMETHODCALLTYPE UpdateModuleSymbols( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule, /* [in] */ IStream *pSymbolStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE EditAndContinueRemap( + + virtual HRESULT STDMETHODCALLTYPE EditAndContinueRemap( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ BOOL fAccurate) = 0; - - virtual HRESULT STDMETHODCALLTYPE BreakpointSetError( + + virtual HRESULT STDMETHODCALLTYPE BreakpointSetError( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint, /* [in] */ DWORD dwError) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallbackVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback * This); - - HRESULT ( STDMETHODCALLTYPE *Breakpoint )( + + HRESULT ( STDMETHODCALLTYPE *Breakpoint )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *StepComplete )( + + HRESULT ( STDMETHODCALLTYPE *StepComplete )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugStepper *pStepper, /* [in] */ CorDebugStepReason reason); - - HRESULT ( STDMETHODCALLTYPE *Break )( + + HRESULT ( STDMETHODCALLTYPE *Break )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); - - HRESULT ( STDMETHODCALLTYPE *Exception )( + + HRESULT ( STDMETHODCALLTYPE *Exception )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ BOOL unhandled); - - HRESULT ( STDMETHODCALLTYPE *EvalComplete )( + + HRESULT ( STDMETHODCALLTYPE *EvalComplete )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval); - - HRESULT ( STDMETHODCALLTYPE *EvalException )( + + HRESULT ( STDMETHODCALLTYPE *EvalException )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval); - - HRESULT ( STDMETHODCALLTYPE *CreateProcess )( + + HRESULT ( STDMETHODCALLTYPE *CreateProcess )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); - - HRESULT ( STDMETHODCALLTYPE *ExitProcess )( + + HRESULT ( STDMETHODCALLTYPE *ExitProcess )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); - - HRESULT ( STDMETHODCALLTYPE *CreateThread )( + + HRESULT ( STDMETHODCALLTYPE *CreateThread )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); - - HRESULT ( STDMETHODCALLTYPE *ExitThread )( + + HRESULT ( STDMETHODCALLTYPE *ExitThread )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); - - HRESULT ( STDMETHODCALLTYPE *LoadModule )( + + HRESULT ( STDMETHODCALLTYPE *LoadModule )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule); - - HRESULT ( STDMETHODCALLTYPE *UnloadModule )( + + HRESULT ( STDMETHODCALLTYPE *UnloadModule )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule); - - HRESULT ( STDMETHODCALLTYPE *LoadClass )( + + HRESULT ( STDMETHODCALLTYPE *LoadClass )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c); - - HRESULT ( STDMETHODCALLTYPE *UnloadClass )( + + HRESULT ( STDMETHODCALLTYPE *UnloadClass )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c); - - HRESULT ( STDMETHODCALLTYPE *DebuggerError )( + + HRESULT ( STDMETHODCALLTYPE *DebuggerError )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ HRESULT errorHR, /* [in] */ DWORD errorCode); - - HRESULT ( STDMETHODCALLTYPE *LogMessage )( + + HRESULT ( STDMETHODCALLTYPE *LogMessage )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pMessage); - - HRESULT ( STDMETHODCALLTYPE *LogSwitch )( + + HRESULT ( STDMETHODCALLTYPE *LogSwitch )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, @@ -3545,56 +3554,56 @@ EXTERN_C const IID IID_ICorDebugManagedCallback; /* [in] */ ULONG ulReason, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pParentName); - - HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( + + HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain); - - HRESULT ( STDMETHODCALLTYPE *ExitAppDomain )( + + HRESULT ( STDMETHODCALLTYPE *ExitAppDomain )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain); - - HRESULT ( STDMETHODCALLTYPE *LoadAssembly )( + + HRESULT ( STDMETHODCALLTYPE *LoadAssembly )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly); - - HRESULT ( STDMETHODCALLTYPE *UnloadAssembly )( + + HRESULT ( STDMETHODCALLTYPE *UnloadAssembly )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly); - - HRESULT ( STDMETHODCALLTYPE *ControlCTrap )( + + HRESULT ( STDMETHODCALLTYPE *ControlCTrap )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); - - HRESULT ( STDMETHODCALLTYPE *NameChange )( + + HRESULT ( STDMETHODCALLTYPE *NameChange )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread); - - HRESULT ( STDMETHODCALLTYPE *UpdateModuleSymbols )( + + HRESULT ( STDMETHODCALLTYPE *UpdateModuleSymbols )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule, /* [in] */ IStream *pSymbolStream); - - HRESULT ( STDMETHODCALLTYPE *EditAndContinueRemap )( + + HRESULT ( STDMETHODCALLTYPE *EditAndContinueRemap )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ BOOL fAccurate); - - HRESULT ( STDMETHODCALLTYPE *BreakpointSetError )( + + HRESULT ( STDMETHODCALLTYPE *BreakpointSetError )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint, /* [in] */ DWORD dwError); - + END_INTERFACE } ICorDebugManagedCallbackVtbl; @@ -3603,98 +3612,98 @@ EXTERN_C const IID IID_ICorDebugManagedCallback; CONST_VTBL struct ICorDebugManagedCallbackVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback_Breakpoint(This,pAppDomain,pThread,pBreakpoint) \ - ( (This)->lpVtbl -> Breakpoint(This,pAppDomain,pThread,pBreakpoint) ) + ( (This)->lpVtbl -> Breakpoint(This,pAppDomain,pThread,pBreakpoint) ) #define ICorDebugManagedCallback_StepComplete(This,pAppDomain,pThread,pStepper,reason) \ - ( (This)->lpVtbl -> StepComplete(This,pAppDomain,pThread,pStepper,reason) ) + ( (This)->lpVtbl -> StepComplete(This,pAppDomain,pThread,pStepper,reason) ) #define ICorDebugManagedCallback_Break(This,pAppDomain,thread) \ - ( (This)->lpVtbl -> Break(This,pAppDomain,thread) ) + ( (This)->lpVtbl -> Break(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_Exception(This,pAppDomain,pThread,unhandled) \ - ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,unhandled) ) + ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,unhandled) ) #define ICorDebugManagedCallback_EvalComplete(This,pAppDomain,pThread,pEval) \ - ( (This)->lpVtbl -> EvalComplete(This,pAppDomain,pThread,pEval) ) + ( (This)->lpVtbl -> EvalComplete(This,pAppDomain,pThread,pEval) ) #define ICorDebugManagedCallback_EvalException(This,pAppDomain,pThread,pEval) \ - ( (This)->lpVtbl -> EvalException(This,pAppDomain,pThread,pEval) ) + ( (This)->lpVtbl -> EvalException(This,pAppDomain,pThread,pEval) ) #define ICorDebugManagedCallback_CreateProcess(This,pProcess) \ - ( (This)->lpVtbl -> CreateProcess(This,pProcess) ) + ( (This)->lpVtbl -> CreateProcess(This,pProcess) ) #define ICorDebugManagedCallback_ExitProcess(This,pProcess) \ - ( (This)->lpVtbl -> ExitProcess(This,pProcess) ) + ( (This)->lpVtbl -> ExitProcess(This,pProcess) ) #define ICorDebugManagedCallback_CreateThread(This,pAppDomain,thread) \ - ( (This)->lpVtbl -> CreateThread(This,pAppDomain,thread) ) + ( (This)->lpVtbl -> CreateThread(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_ExitThread(This,pAppDomain,thread) \ - ( (This)->lpVtbl -> ExitThread(This,pAppDomain,thread) ) + ( (This)->lpVtbl -> ExitThread(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_LoadModule(This,pAppDomain,pModule) \ - ( (This)->lpVtbl -> LoadModule(This,pAppDomain,pModule) ) + ( (This)->lpVtbl -> LoadModule(This,pAppDomain,pModule) ) #define ICorDebugManagedCallback_UnloadModule(This,pAppDomain,pModule) \ - ( (This)->lpVtbl -> UnloadModule(This,pAppDomain,pModule) ) + ( (This)->lpVtbl -> UnloadModule(This,pAppDomain,pModule) ) #define ICorDebugManagedCallback_LoadClass(This,pAppDomain,c) \ - ( (This)->lpVtbl -> LoadClass(This,pAppDomain,c) ) + ( (This)->lpVtbl -> LoadClass(This,pAppDomain,c) ) #define ICorDebugManagedCallback_UnloadClass(This,pAppDomain,c) \ - ( (This)->lpVtbl -> UnloadClass(This,pAppDomain,c) ) + ( (This)->lpVtbl -> UnloadClass(This,pAppDomain,c) ) #define ICorDebugManagedCallback_DebuggerError(This,pProcess,errorHR,errorCode) \ - ( (This)->lpVtbl -> DebuggerError(This,pProcess,errorHR,errorCode) ) + ( (This)->lpVtbl -> DebuggerError(This,pProcess,errorHR,errorCode) ) #define ICorDebugManagedCallback_LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) \ - ( (This)->lpVtbl -> LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) ) + ( (This)->lpVtbl -> LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) ) #define ICorDebugManagedCallback_LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) \ - ( (This)->lpVtbl -> LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) ) + ( (This)->lpVtbl -> LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) ) #define ICorDebugManagedCallback_CreateAppDomain(This,pProcess,pAppDomain) \ - ( (This)->lpVtbl -> CreateAppDomain(This,pProcess,pAppDomain) ) + ( (This)->lpVtbl -> CreateAppDomain(This,pProcess,pAppDomain) ) #define ICorDebugManagedCallback_ExitAppDomain(This,pProcess,pAppDomain) \ - ( (This)->lpVtbl -> ExitAppDomain(This,pProcess,pAppDomain) ) + ( (This)->lpVtbl -> ExitAppDomain(This,pProcess,pAppDomain) ) #define ICorDebugManagedCallback_LoadAssembly(This,pAppDomain,pAssembly) \ - ( (This)->lpVtbl -> LoadAssembly(This,pAppDomain,pAssembly) ) + ( (This)->lpVtbl -> LoadAssembly(This,pAppDomain,pAssembly) ) #define ICorDebugManagedCallback_UnloadAssembly(This,pAppDomain,pAssembly) \ - ( (This)->lpVtbl -> UnloadAssembly(This,pAppDomain,pAssembly) ) + ( (This)->lpVtbl -> UnloadAssembly(This,pAppDomain,pAssembly) ) #define ICorDebugManagedCallback_ControlCTrap(This,pProcess) \ - ( (This)->lpVtbl -> ControlCTrap(This,pProcess) ) + ( (This)->lpVtbl -> ControlCTrap(This,pProcess) ) #define ICorDebugManagedCallback_NameChange(This,pAppDomain,pThread) \ - ( (This)->lpVtbl -> NameChange(This,pAppDomain,pThread) ) + ( (This)->lpVtbl -> NameChange(This,pAppDomain,pThread) ) #define ICorDebugManagedCallback_UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) \ - ( (This)->lpVtbl -> UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) ) + ( (This)->lpVtbl -> UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) ) #define ICorDebugManagedCallback_EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) \ - ( (This)->lpVtbl -> EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) ) + ( (This)->lpVtbl -> EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) ) #define ICorDebugManagedCallback_BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) \ - ( (This)->lpVtbl -> BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) ) + ( (This)->lpVtbl -> BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) ) #endif /* COBJMACROS */ @@ -3708,7 +3717,7 @@ EXTERN_C const IID IID_ICorDebugManagedCallback; /* interface __MIDL_itf_cordebug_0000_0016 */ -/* [local] */ +/* [local] */ #pragma warning(pop) #pragma warning(push) @@ -3721,47 +3730,47 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_s_ifspec; #define __ICorDebugManagedCallback3_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugManagedCallback3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("264EA0FC-2591-49AA-868E-835E6515323F") ICorDebugManagedCallback3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CustomNotification( + virtual HRESULT STDMETHODCALLTYPE CustomNotification( /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallback3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback3 * This); - - HRESULT ( STDMETHODCALLTYPE *CustomNotification )( + + HRESULT ( STDMETHODCALLTYPE *CustomNotification )( ICorDebugManagedCallback3 * This, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugAppDomain *pAppDomain); - + END_INTERFACE } ICorDebugManagedCallback3Vtbl; @@ -3770,23 +3779,23 @@ EXTERN_C const IID IID_ICorDebugManagedCallback3; CONST_VTBL struct ICorDebugManagedCallback3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback3_CustomNotification(This,pThread,pAppDomain) \ - ( (This)->lpVtbl -> CustomNotification(This,pThread,pAppDomain) ) + ( (This)->lpVtbl -> CustomNotification(This,pThread,pAppDomain) ) #endif /* COBJMACROS */ @@ -3803,65 +3812,65 @@ EXTERN_C const IID IID_ICorDebugManagedCallback3; #define __ICorDebugManagedCallback4_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugManagedCallback4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("322911AE-16A5-49BA-84A3-ED69678138A3") ICorDebugManagedCallback4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( + virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( + + virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( /* [in] */ ICorDebugProcess *pProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugThread *pThread, /* [in] */ BYTE *pContext, /* [in] */ ULONG32 contextSize) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallback4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback4 * This); - - HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( + + HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess); - - HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( + + HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess); - - HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugThread *pThread, /* [in] */ BYTE *pContext, /* [in] */ ULONG32 contextSize); - + END_INTERFACE } ICorDebugManagedCallback4Vtbl; @@ -3870,29 +3879,29 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4; CONST_VTBL struct ICorDebugManagedCallback4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback4_BeforeGarbageCollection(This,pProcess) \ - ( (This)->lpVtbl -> BeforeGarbageCollection(This,pProcess) ) + ( (This)->lpVtbl -> BeforeGarbageCollection(This,pProcess) ) #define ICorDebugManagedCallback4_AfterGarbageCollection(This,pProcess) \ - ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) + ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) #define ICorDebugManagedCallback4_DataBreakpoint(This,pProcess,pThread,pContext,contextSize) \ - ( (This)->lpVtbl -> DataBreakpoint(This,pProcess,pThread,pContext,contextSize) ) + ( (This)->lpVtbl -> DataBreakpoint(This,pProcess,pThread,pContext,contextSize) ) #endif /* COBJMACROS */ @@ -3906,9 +3915,9 @@ EXTERN_C const IID IID_ICorDebugManagedCallback4; /* interface __MIDL_itf_cordebug_0000_0018 */ -/* [local] */ +/* [local] */ -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_c_ifspec; @@ -3918,9 +3927,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_s_ifspec; #define __ICorDebugManagedCallback2_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugExceptionCallbackType { DEBUG_EXCEPTION_FIRST_CHANCE = 1, @@ -3929,14 +3938,14 @@ enum CorDebugExceptionCallbackType DEBUG_EXCEPTION_UNHANDLED = 4 } CorDebugExceptionCallbackType; -typedef +typedef enum CorDebugExceptionFlags { DEBUG_EXCEPTION_NONE = 0, DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x1 } CorDebugExceptionFlags; -typedef +typedef enum CorDebugExceptionUnwindCallbackType { DEBUG_EXCEPTION_UNWIND_BEGIN = 1, @@ -3947,101 +3956,101 @@ enum CorDebugExceptionUnwindCallbackType EXTERN_C const IID IID_ICorDebugManagedCallback2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("250E5EEA-DB5C-4C76-B6F3-8C46F12E3203") ICorDebugManagedCallback2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE FunctionRemapOpportunity( + virtual HRESULT STDMETHODCALLTYPE FunctionRemapOpportunity( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pOldFunction, /* [in] */ ICorDebugFunction *pNewFunction, /* [in] */ ULONG32 oldILOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateConnection( + + virtual HRESULT STDMETHODCALLTYPE CreateConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId, /* [in] */ WCHAR *pConnName) = 0; - - virtual HRESULT STDMETHODCALLTYPE ChangeConnection( + + virtual HRESULT STDMETHODCALLTYPE ChangeConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId) = 0; - - virtual HRESULT STDMETHODCALLTYPE DestroyConnection( + + virtual HRESULT STDMETHODCALLTYPE DestroyConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId) = 0; - - virtual HRESULT STDMETHODCALLTYPE Exception( + + virtual HRESULT STDMETHODCALLTYPE Exception( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFrame *pFrame, /* [in] */ ULONG32 nOffset, /* [in] */ CorDebugExceptionCallbackType dwEventType, /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind( + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE FunctionRemapComplete( + + virtual HRESULT STDMETHODCALLTYPE FunctionRemapComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE MDANotification( + + virtual HRESULT STDMETHODCALLTYPE MDANotification( /* [in] */ ICorDebugController *pController, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugMDA *pMDA) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugManagedCallback2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback2 * This); - - HRESULT ( STDMETHODCALLTYPE *FunctionRemapOpportunity )( + + HRESULT ( STDMETHODCALLTYPE *FunctionRemapOpportunity )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pOldFunction, /* [in] */ ICorDebugFunction *pNewFunction, /* [in] */ ULONG32 oldILOffset); - - HRESULT ( STDMETHODCALLTYPE *CreateConnection )( + + HRESULT ( STDMETHODCALLTYPE *CreateConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId, /* [in] */ WCHAR *pConnName); - - HRESULT ( STDMETHODCALLTYPE *ChangeConnection )( + + HRESULT ( STDMETHODCALLTYPE *ChangeConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId); - - HRESULT ( STDMETHODCALLTYPE *DestroyConnection )( + + HRESULT ( STDMETHODCALLTYPE *DestroyConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId); - - HRESULT ( STDMETHODCALLTYPE *Exception )( + + HRESULT ( STDMETHODCALLTYPE *Exception )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, @@ -4049,26 +4058,26 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2; /* [in] */ ULONG32 nOffset, /* [in] */ CorDebugExceptionCallbackType dwEventType, /* [in] */ DWORD dwFlags); - - HRESULT ( STDMETHODCALLTYPE *ExceptionUnwind )( + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwind )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, /* [in] */ DWORD dwFlags); - - HRESULT ( STDMETHODCALLTYPE *FunctionRemapComplete )( + + HRESULT ( STDMETHODCALLTYPE *FunctionRemapComplete )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction); - - HRESULT ( STDMETHODCALLTYPE *MDANotification )( + + HRESULT ( STDMETHODCALLTYPE *MDANotification )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugController *pController, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugMDA *pMDA); - + END_INTERFACE } ICorDebugManagedCallback2Vtbl; @@ -4077,44 +4086,44 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2; CONST_VTBL struct ICorDebugManagedCallback2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugManagedCallback2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback2_FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) \ - ( (This)->lpVtbl -> FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) ) + ( (This)->lpVtbl -> FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) ) #define ICorDebugManagedCallback2_CreateConnection(This,pProcess,dwConnectionId,pConnName) \ - ( (This)->lpVtbl -> CreateConnection(This,pProcess,dwConnectionId,pConnName) ) + ( (This)->lpVtbl -> CreateConnection(This,pProcess,dwConnectionId,pConnName) ) #define ICorDebugManagedCallback2_ChangeConnection(This,pProcess,dwConnectionId) \ - ( (This)->lpVtbl -> ChangeConnection(This,pProcess,dwConnectionId) ) + ( (This)->lpVtbl -> ChangeConnection(This,pProcess,dwConnectionId) ) #define ICorDebugManagedCallback2_DestroyConnection(This,pProcess,dwConnectionId) \ - ( (This)->lpVtbl -> DestroyConnection(This,pProcess,dwConnectionId) ) + ( (This)->lpVtbl -> DestroyConnection(This,pProcess,dwConnectionId) ) #define ICorDebugManagedCallback2_Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) \ - ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) ) + ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) ) #define ICorDebugManagedCallback2_ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) \ - ( (This)->lpVtbl -> ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) ) + ( (This)->lpVtbl -> ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) ) #define ICorDebugManagedCallback2_FunctionRemapComplete(This,pAppDomain,pThread,pFunction) \ - ( (This)->lpVtbl -> FunctionRemapComplete(This,pAppDomain,pThread,pFunction) ) + ( (This)->lpVtbl -> FunctionRemapComplete(This,pAppDomain,pThread,pFunction) ) #define ICorDebugManagedCallback2_MDANotification(This,pController,pThread,pMDA) \ - ( (This)->lpVtbl -> MDANotification(This,pController,pThread,pMDA) ) + ( (This)->lpVtbl -> MDANotification(This,pController,pThread,pMDA) ) #endif /* COBJMACROS */ @@ -4128,7 +4137,7 @@ EXTERN_C const IID IID_ICorDebugManagedCallback2; /* interface __MIDL_itf_cordebug_0000_0019 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -4140,47 +4149,47 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_s_ifspec; #define __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ /* interface ICorDebugUnmanagedCallback */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5263E909-8CB5-11d3-BD2F-0000F80849BD") ICorDebugUnmanagedCallback : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE DebugEvent( + virtual HRESULT STDMETHODCALLTYPE DebugEvent( /* [in] */ LPDEBUG_EVENT pDebugEvent, /* [in] */ BOOL fOutOfBand) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugUnmanagedCallbackVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugUnmanagedCallback * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugUnmanagedCallback * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugUnmanagedCallback * This); - - HRESULT ( STDMETHODCALLTYPE *DebugEvent )( + + HRESULT ( STDMETHODCALLTYPE *DebugEvent )( ICorDebugUnmanagedCallback * This, /* [in] */ LPDEBUG_EVENT pDebugEvent, /* [in] */ BOOL fOutOfBand); - + END_INTERFACE } ICorDebugUnmanagedCallbackVtbl; @@ -4189,23 +4198,23 @@ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; CONST_VTBL struct ICorDebugUnmanagedCallbackVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugUnmanagedCallback_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugUnmanagedCallback_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugUnmanagedCallback_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugUnmanagedCallback_DebugEvent(This,pDebugEvent,fOutOfBand) \ - ( (This)->lpVtbl -> DebugEvent(This,pDebugEvent,fOutOfBand) ) + ( (This)->lpVtbl -> DebugEvent(This,pDebugEvent,fOutOfBand) ) #endif /* COBJMACROS */ @@ -4219,15 +4228,15 @@ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; /* interface __MIDL_itf_cordebug_0000_0020 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugCreateProcessFlags { DEBUG_NO_SPECIAL_OPTIONS = 0 } CorDebugCreateProcessFlags; -typedef +typedef enum CorDebugHandleType { HANDLE_STRONG = 1, @@ -4236,7 +4245,7 @@ enum CorDebugHandleType } CorDebugHandleType; #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_c_ifspec; @@ -4246,28 +4255,28 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_s_ifspec; #define __ICorDebug_INTERFACE_DEFINED__ /* interface ICorDebug */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebug; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f61-7538-11d3-8d5b-00104b35e7ef") ICorDebug : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Initialize( void) = 0; - + virtual HRESULT STDMETHODCALLTYPE Terminate( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetManagedHandler( + + virtual HRESULT STDMETHODCALLTYPE SetManagedHandler( /* [in] */ ICorDebugManagedCallback *pCallback) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUnmanagedHandler( + + virtual HRESULT STDMETHODCALLTYPE SetUnmanagedHandler( /* [in] */ ICorDebugUnmanagedCallback *pCallback) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateProcess( + + virtual HRESULT STDMETHODCALLTYPE CreateProcess( /* [in] */ LPCWSTR lpApplicationName, /* [in] */ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, @@ -4280,59 +4289,59 @@ EXTERN_C const IID IID_ICorDebug; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE DebugActiveProcess( + + virtual HRESULT STDMETHODCALLTYPE DebugActiveProcess( /* [in] */ DWORD id, /* [in] */ BOOL win32Attach, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateProcesses( + + virtual HRESULT STDMETHODCALLTYPE EnumerateProcesses( /* [out] */ ICorDebugProcessEnum **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetProcess( + + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [in] */ DWORD dwProcessId, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanLaunchOrAttach( + + virtual HRESULT STDMETHODCALLTYPE CanLaunchOrAttach( /* [in] */ DWORD dwProcessId, /* [in] */ BOOL win32DebuggingEnabled) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebug * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebug * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebug * This); - - HRESULT ( STDMETHODCALLTYPE *Initialize )( + + HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorDebug * This); - - HRESULT ( STDMETHODCALLTYPE *Terminate )( + + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebug * This); - - HRESULT ( STDMETHODCALLTYPE *SetManagedHandler )( + + HRESULT ( STDMETHODCALLTYPE *SetManagedHandler )( ICorDebug * This, /* [in] */ ICorDebugManagedCallback *pCallback); - - HRESULT ( STDMETHODCALLTYPE *SetUnmanagedHandler )( + + HRESULT ( STDMETHODCALLTYPE *SetUnmanagedHandler )( ICorDebug * This, /* [in] */ ICorDebugUnmanagedCallback *pCallback); - - HRESULT ( STDMETHODCALLTYPE *CreateProcess )( + + HRESULT ( STDMETHODCALLTYPE *CreateProcess )( ICorDebug * This, /* [in] */ LPCWSTR lpApplicationName, /* [in] */ LPWSTR lpCommandLine, @@ -4346,27 +4355,27 @@ EXTERN_C const IID IID_ICorDebug; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *DebugActiveProcess )( + + HRESULT ( STDMETHODCALLTYPE *DebugActiveProcess )( ICorDebug * This, /* [in] */ DWORD id, /* [in] */ BOOL win32Attach, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *EnumerateProcesses )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateProcesses )( ICorDebug * This, /* [out] */ ICorDebugProcessEnum **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebug * This, /* [in] */ DWORD dwProcessId, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *CanLaunchOrAttach )( + + HRESULT ( STDMETHODCALLTYPE *CanLaunchOrAttach )( ICorDebug * This, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL win32DebuggingEnabled); - + END_INTERFACE } ICorDebugVtbl; @@ -4375,47 +4384,47 @@ EXTERN_C const IID IID_ICorDebug; CONST_VTBL struct ICorDebugVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebug_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebug_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebug_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebug_Initialize(This) \ - ( (This)->lpVtbl -> Initialize(This) ) + ( (This)->lpVtbl -> Initialize(This) ) #define ICorDebug_Terminate(This) \ - ( (This)->lpVtbl -> Terminate(This) ) + ( (This)->lpVtbl -> Terminate(This) ) #define ICorDebug_SetManagedHandler(This,pCallback) \ - ( (This)->lpVtbl -> SetManagedHandler(This,pCallback) ) + ( (This)->lpVtbl -> SetManagedHandler(This,pCallback) ) #define ICorDebug_SetUnmanagedHandler(This,pCallback) \ - ( (This)->lpVtbl -> SetUnmanagedHandler(This,pCallback) ) + ( (This)->lpVtbl -> SetUnmanagedHandler(This,pCallback) ) #define ICorDebug_CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ - ( (This)->lpVtbl -> CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) + ( (This)->lpVtbl -> CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) #define ICorDebug_DebugActiveProcess(This,id,win32Attach,ppProcess) \ - ( (This)->lpVtbl -> DebugActiveProcess(This,id,win32Attach,ppProcess) ) + ( (This)->lpVtbl -> DebugActiveProcess(This,id,win32Attach,ppProcess) ) #define ICorDebug_EnumerateProcesses(This,ppProcess) \ - ( (This)->lpVtbl -> EnumerateProcesses(This,ppProcess) ) + ( (This)->lpVtbl -> EnumerateProcesses(This,ppProcess) ) #define ICorDebug_GetProcess(This,dwProcessId,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,dwProcessId,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,dwProcessId,ppProcess) ) #define ICorDebug_CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) \ - ( (This)->lpVtbl -> CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) ) + ( (This)->lpVtbl -> CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) ) #endif /* COBJMACROS */ @@ -4429,7 +4438,7 @@ EXTERN_C const IID IID_ICorDebug; /* interface __MIDL_itf_cordebug_0000_0021 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -4441,53 +4450,53 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_s_ifspec; #define __ICorDebugRemoteTarget_INTERFACE_DEFINED__ /* interface ICorDebugRemoteTarget */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRemoteTarget; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("C3ED8383-5A49-4cf5-B4B7-01864D9E582D") ICorDebugRemoteTarget : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetHostName( + virtual HRESULT STDMETHODCALLTYPE GetHostName( /* [in] */ ULONG32 cchHostName, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchHostName, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRemoteTargetVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRemoteTarget * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRemoteTarget * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRemoteTarget * This); - - HRESULT ( STDMETHODCALLTYPE *GetHostName )( + + HRESULT ( STDMETHODCALLTYPE *GetHostName )( ICorDebugRemoteTarget * This, /* [in] */ ULONG32 cchHostName, - /* [annotation][out] */ + /* [annotation][out] */ _Out_ ULONG32 *pcchHostName, - /* [annotation][length_is][size_is][out] */ + /* [annotation][length_is][size_is][out] */ _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]); - + END_INTERFACE } ICorDebugRemoteTargetVtbl; @@ -4496,23 +4505,23 @@ EXTERN_C const IID IID_ICorDebugRemoteTarget; CONST_VTBL struct ICorDebugRemoteTargetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRemoteTarget_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRemoteTarget_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRemoteTarget_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRemoteTarget_GetHostName(This,cchHostName,pcchHostName,szHostName) \ - ( (This)->lpVtbl -> GetHostName(This,cchHostName,pcchHostName,szHostName) ) + ( (This)->lpVtbl -> GetHostName(This,cchHostName,pcchHostName,szHostName) ) #endif /* COBJMACROS */ @@ -4529,21 +4538,21 @@ EXTERN_C const IID IID_ICorDebugRemoteTarget; #define __ICorDebugRemote_INTERFACE_DEFINED__ /* interface ICorDebugRemote */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRemote; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64") ICorDebugRemote : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateProcessEx( + virtual HRESULT STDMETHODCALLTYPE CreateProcessEx( /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ LPCWSTR lpApplicationName, - /* [annotation][in] */ + /* [annotation][in] */ _In_ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, @@ -4555,39 +4564,39 @@ EXTERN_C const IID IID_ICorDebugRemote; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE DebugActiveProcessEx( + + virtual HRESULT STDMETHODCALLTYPE DebugActiveProcessEx( /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL fWin32Attach, /* [out] */ ICorDebugProcess **ppProcess) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRemoteVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRemote * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRemote * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRemote * This); - - HRESULT ( STDMETHODCALLTYPE *CreateProcessEx )( + + HRESULT ( STDMETHODCALLTYPE *CreateProcessEx )( ICorDebugRemote * This, /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ LPCWSTR lpApplicationName, - /* [annotation][in] */ + /* [annotation][in] */ _In_ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, @@ -4599,14 +4608,14 @@ EXTERN_C const IID IID_ICorDebugRemote; /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *DebugActiveProcessEx )( + + HRESULT ( STDMETHODCALLTYPE *DebugActiveProcessEx )( ICorDebugRemote * This, /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL fWin32Attach, /* [out] */ ICorDebugProcess **ppProcess); - + END_INTERFACE } ICorDebugRemoteVtbl; @@ -4615,26 +4624,26 @@ EXTERN_C const IID IID_ICorDebugRemote; CONST_VTBL struct ICorDebugRemoteVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRemote_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRemote_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRemote_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRemote_CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ - ( (This)->lpVtbl -> CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) + ( (This)->lpVtbl -> CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) #define ICorDebugRemote_DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) \ - ( (This)->lpVtbl -> DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) ) + ( (This)->lpVtbl -> DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) ) #endif /* COBJMACROS */ @@ -4648,7 +4657,7 @@ EXTERN_C const IID IID_ICorDebugRemote; /* interface __MIDL_itf_cordebug_0000_0023 */ -/* [local] */ +/* [local] */ typedef struct _COR_VERSION { @@ -4667,9 +4676,9 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_s_ifspec; #define __ICorDebug2_INTERFACE_DEFINED__ /* interface ICorDebug2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugInterfaceVersion { CorDebugInvalidVersion = 0, @@ -4763,32 +4772,32 @@ enum CorDebugInterfaceVersion EXTERN_C const IID IID_ICorDebug2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("ECCCCF2E-B286-4b3e-A983-860A8793D105") ICorDebug2 : public IUnknown { public: }; - - + + #else /* C style interface */ typedef struct ICorDebug2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebug2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebug2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebug2 * This); - + END_INTERFACE } ICorDebug2Vtbl; @@ -4797,19 +4806,19 @@ EXTERN_C const IID IID_ICorDebug2; CONST_VTBL struct ICorDebug2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebug2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebug2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebug2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #endif /* COBJMACROS */ @@ -4824,13 +4833,13 @@ EXTERN_C const IID IID_ICorDebug2; /* interface __MIDL_itf_cordebug_0000_0024 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugThreadState { THREAD_RUN = 0, - THREAD_SUSPEND = ( THREAD_RUN + 1 ) + THREAD_SUSPEND = ( THREAD_RUN + 1 ) } CorDebugThreadState; @@ -4842,118 +4851,118 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_s_ifspec; #define __ICorDebugController_INTERFACE_DEFINED__ /* interface ICorDebugController */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugController; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f62-7538-11d3-8d5b-00104b35e7ef") ICorDebugController : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Stop( + virtual HRESULT STDMETHODCALLTYPE Stop( /* [in] */ DWORD dwTimeoutIgnored) = 0; - - virtual HRESULT STDMETHODCALLTYPE Continue( + + virtual HRESULT STDMETHODCALLTYPE Continue( /* [in] */ BOOL fIsOutOfBand) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsRunning( + + virtual HRESULT STDMETHODCALLTYPE IsRunning( /* [out] */ BOOL *pbRunning) = 0; - - virtual HRESULT STDMETHODCALLTYPE HasQueuedCallbacks( + + virtual HRESULT STDMETHODCALLTYPE HasQueuedCallbacks( /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateThreads( + + virtual HRESULT STDMETHODCALLTYPE EnumerateThreads( /* [out] */ ICorDebugThreadEnum **ppThreads) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetAllThreadsDebugState( + + virtual HRESULT STDMETHODCALLTYPE SetAllThreadsDebugState( /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread) = 0; - + virtual HRESULT STDMETHODCALLTYPE Detach( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Terminate( + + virtual HRESULT STDMETHODCALLTYPE Terminate( /* [in] */ UINT exitCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanCommitChanges( + + virtual HRESULT STDMETHODCALLTYPE CanCommitChanges( /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; - - virtual HRESULT STDMETHODCALLTYPE CommitChanges( + + virtual HRESULT STDMETHODCALLTYPE CommitChanges( /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugControllerVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugController * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugController * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugController * This); - - HRESULT ( STDMETHODCALLTYPE *Stop )( + + HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugController * This, /* [in] */ DWORD dwTimeoutIgnored); - - HRESULT ( STDMETHODCALLTYPE *Continue )( + + HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugController * This, /* [in] */ BOOL fIsOutOfBand); - - HRESULT ( STDMETHODCALLTYPE *IsRunning )( + + HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugController * This, /* [out] */ BOOL *pbRunning); - - HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugController * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); - - HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugController * This, /* [out] */ ICorDebugThreadEnum **ppThreads); - - HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugController * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); - - HRESULT ( STDMETHODCALLTYPE *Detach )( + + HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugController * This); - - HRESULT ( STDMETHODCALLTYPE *Terminate )( + + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugController * This, /* [in] */ UINT exitCode); - - HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugController * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - - HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugController * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - + END_INTERFACE } ICorDebugControllerVtbl; @@ -4962,50 +4971,50 @@ EXTERN_C const IID IID_ICorDebugController; CONST_VTBL struct ICorDebugControllerVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugController_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugController_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugController_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugController_Stop(This,dwTimeoutIgnored) \ - ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugController_Continue(This,fIsOutOfBand) \ - ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugController_IsRunning(This,pbRunning) \ - ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugController_HasQueuedCallbacks(This,pThread,pbQueued) \ - ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugController_EnumerateThreads(This,ppThreads) \ - ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugController_SetAllThreadsDebugState(This,state,pExceptThisThread) \ - ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugController_Detach(This) \ - ( (This)->lpVtbl -> Detach(This) ) + ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugController_Terminate(This,exitCode) \ - ( (This)->lpVtbl -> Terminate(This,exitCode) ) + ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugController_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugController_CommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #endif /* COBJMACROS */ @@ -5019,10 +5028,10 @@ EXTERN_C const IID IID_ICorDebugController; /* interface __MIDL_itf_cordebug_0000_0025 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_c_ifspec; @@ -5032,157 +5041,157 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_s_ifspec; #define __ICorDebugAppDomain_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f63-7538-11d3-8d5b-00104b35e7ef") ICorDebugAppDomain : public ICorDebugController { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateAssemblies( + + virtual HRESULT STDMETHODCALLTYPE EnumerateAssemblies( /* [out] */ ICorDebugAssemblyEnum **ppAssemblies) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetModuleFromMetaDataInterface( + + virtual HRESULT STDMETHODCALLTYPE GetModuleFromMetaDataInterface( /* [in] */ IUnknown *pIMetaData, /* [out] */ ICorDebugModule **ppModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateBreakpoints( + + virtual HRESULT STDMETHODCALLTYPE EnumerateBreakpoints( /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateSteppers( + + virtual HRESULT STDMETHODCALLTYPE EnumerateSteppers( /* [out] */ ICorDebugStepperEnum **ppSteppers) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsAttached( + + virtual HRESULT STDMETHODCALLTYPE IsAttached( /* [out] */ BOOL *pbAttached) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; - + virtual HRESULT STDMETHODCALLTYPE Attach( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetID( + + virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ ULONG32 *pId) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomainVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain * This); - - HRESULT ( STDMETHODCALLTYPE *Stop )( + + HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugAppDomain * This, /* [in] */ DWORD dwTimeoutIgnored); - - HRESULT ( STDMETHODCALLTYPE *Continue )( + + HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugAppDomain * This, /* [in] */ BOOL fIsOutOfBand); - - HRESULT ( STDMETHODCALLTYPE *IsRunning )( + + HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugAppDomain * This, /* [out] */ BOOL *pbRunning); - - HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugAppDomain * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); - - HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugAppDomain * This, /* [out] */ ICorDebugThreadEnum **ppThreads); - - HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugAppDomain * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); - - HRESULT ( STDMETHODCALLTYPE *Detach )( + + HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugAppDomain * This); - - HRESULT ( STDMETHODCALLTYPE *Terminate )( + + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugAppDomain * This, /* [in] */ UINT exitCode); - - HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugAppDomain * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - - HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugAppDomain * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugAppDomain * This, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *EnumerateAssemblies )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateAssemblies )( ICorDebugAppDomain * This, /* [out] */ ICorDebugAssemblyEnum **ppAssemblies); - - HRESULT ( STDMETHODCALLTYPE *GetModuleFromMetaDataInterface )( + + HRESULT ( STDMETHODCALLTYPE *GetModuleFromMetaDataInterface )( ICorDebugAppDomain * This, /* [in] */ IUnknown *pIMetaData, /* [out] */ ICorDebugModule **ppModule); - - HRESULT ( STDMETHODCALLTYPE *EnumerateBreakpoints )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateBreakpoints )( ICorDebugAppDomain * This, /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints); - - HRESULT ( STDMETHODCALLTYPE *EnumerateSteppers )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateSteppers )( ICorDebugAppDomain * This, /* [out] */ ICorDebugStepperEnum **ppSteppers); - - HRESULT ( STDMETHODCALLTYPE *IsAttached )( + + HRESULT ( STDMETHODCALLTYPE *IsAttached )( ICorDebugAppDomain * This, /* [out] */ BOOL *pbAttached); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugAppDomain * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetObject )( + + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugAppDomain * This, /* [out] */ ICorDebugValue **ppObject); - - HRESULT ( STDMETHODCALLTYPE *Attach )( + + HRESULT ( STDMETHODCALLTYPE *Attach )( ICorDebugAppDomain * This); - - HRESULT ( STDMETHODCALLTYPE *GetID )( + + HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugAppDomain * This, /* [out] */ ULONG32 *pId); - + END_INTERFACE } ICorDebugAppDomainVtbl; @@ -5191,81 +5200,81 @@ EXTERN_C const IID IID_ICorDebugAppDomain; CONST_VTBL struct ICorDebugAppDomainVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain_Stop(This,dwTimeoutIgnored) \ - ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugAppDomain_Continue(This,fIsOutOfBand) \ - ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugAppDomain_IsRunning(This,pbRunning) \ - ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugAppDomain_HasQueuedCallbacks(This,pThread,pbQueued) \ - ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugAppDomain_EnumerateThreads(This,ppThreads) \ - ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugAppDomain_SetAllThreadsDebugState(This,state,pExceptThisThread) \ - ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugAppDomain_Detach(This) \ - ( (This)->lpVtbl -> Detach(This) ) + ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugAppDomain_Terminate(This,exitCode) \ - ( (This)->lpVtbl -> Terminate(This,exitCode) ) + ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugAppDomain_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugAppDomain_CommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugAppDomain_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugAppDomain_EnumerateAssemblies(This,ppAssemblies) \ - ( (This)->lpVtbl -> EnumerateAssemblies(This,ppAssemblies) ) + ( (This)->lpVtbl -> EnumerateAssemblies(This,ppAssemblies) ) #define ICorDebugAppDomain_GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) \ - ( (This)->lpVtbl -> GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) ) + ( (This)->lpVtbl -> GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) ) #define ICorDebugAppDomain_EnumerateBreakpoints(This,ppBreakpoints) \ - ( (This)->lpVtbl -> EnumerateBreakpoints(This,ppBreakpoints) ) + ( (This)->lpVtbl -> EnumerateBreakpoints(This,ppBreakpoints) ) #define ICorDebugAppDomain_EnumerateSteppers(This,ppSteppers) \ - ( (This)->lpVtbl -> EnumerateSteppers(This,ppSteppers) ) + ( (This)->lpVtbl -> EnumerateSteppers(This,ppSteppers) ) #define ICorDebugAppDomain_IsAttached(This,pbAttached) \ - ( (This)->lpVtbl -> IsAttached(This,pbAttached) ) + ( (This)->lpVtbl -> IsAttached(This,pbAttached) ) #define ICorDebugAppDomain_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugAppDomain_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #define ICorDebugAppDomain_Attach(This) \ - ( (This)->lpVtbl -> Attach(This) ) + ( (This)->lpVtbl -> Attach(This) ) #define ICorDebugAppDomain_GetID(This,pId) \ - ( (This)->lpVtbl -> GetID(This,pId) ) + ( (This)->lpVtbl -> GetID(This,pId) ) #endif /* COBJMACROS */ @@ -5279,7 +5288,7 @@ EXTERN_C const IID IID_ICorDebugAppDomain; /* interface __MIDL_itf_cordebug_0000_0026 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -5291,62 +5300,62 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0026_v0_0_s_ifspec; #define __ICorDebugAppDomain2_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("096E81D5-ECDA-4202-83F5-C65980A9EF75") ICorDebugAppDomain2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetArrayOrPointerType( + virtual HRESULT STDMETHODCALLTYPE GetArrayOrPointerType( /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nRank, /* [in] */ ICorDebugType *pTypeArg, /* [out] */ ICorDebugType **ppType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionPointerType( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionPointerType( /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomain2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetArrayOrPointerType )( + + HRESULT ( STDMETHODCALLTYPE *GetArrayOrPointerType )( ICorDebugAppDomain2 * This, /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nRank, /* [in] */ ICorDebugType *pTypeArg, /* [out] */ ICorDebugType **ppType); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionPointerType )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionPointerType )( ICorDebugAppDomain2 * This, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType); - + END_INTERFACE } ICorDebugAppDomain2Vtbl; @@ -5355,26 +5364,26 @@ EXTERN_C const IID IID_ICorDebugAppDomain2; CONST_VTBL struct ICorDebugAppDomain2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain2_GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) \ - ( (This)->lpVtbl -> GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) ) + ( (This)->lpVtbl -> GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) ) #define ICorDebugAppDomain2_GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) \ - ( (This)->lpVtbl -> GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) ) + ( (This)->lpVtbl -> GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) ) #endif /* COBJMACROS */ @@ -5391,64 +5400,64 @@ EXTERN_C const IID IID_ICorDebugAppDomain2; #define __ICorDebugEnum_INTERFACE_DEFINED__ /* interface ICorDebugEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB01-8A68-11d2-983C-0000F808342D") ICorDebugEnum : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Skip( + virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; - + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE Clone( + + virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorDebugEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCount( + + virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugEnum * This, /* [out] */ ULONG *pcelt); - + END_INTERFACE } ICorDebugEnumVtbl; @@ -5457,32 +5466,32 @@ EXTERN_C const IID IID_ICorDebugEnum; CONST_VTBL struct ICorDebugEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #endif /* COBJMACROS */ @@ -5499,64 +5508,64 @@ EXTERN_C const IID IID_ICorDebugEnum; #define __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ /* interface ICorDebugGuidToTypeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("6164D242-1015-4BD6-8CBE-D0DBD4B8275A") ICorDebugGuidToTypeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugGuidToTypeEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGuidToTypeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGuidToTypeEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGuidToTypeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugGuidToTypeEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugGuidToTypeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugGuidToTypeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugGuidToTypeEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugGuidToTypeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugGuidToTypeEnumVtbl; @@ -5565,36 +5574,36 @@ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; CONST_VTBL struct ICorDebugGuidToTypeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugGuidToTypeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGuidToTypeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGuidToTypeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGuidToTypeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugGuidToTypeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugGuidToTypeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugGuidToTypeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugGuidToTypeEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -5611,56 +5620,56 @@ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; #define __ICorDebugAppDomain3_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("8CB96A16-B588-42E2-B71C-DD849FC2ECCC") ICorDebugAppDomain3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypesForIIDs( + virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypesForIIDs( /* [in] */ ULONG32 cReqTypes, /* [size_is][in] */ GUID *iidsToResolve, /* [out] */ ICorDebugTypeEnum **ppTypesEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypes( + + virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypes( /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomain3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypesForIIDs )( + + HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypesForIIDs )( ICorDebugAppDomain3 * This, /* [in] */ ULONG32 cReqTypes, /* [size_is][in] */ GUID *iidsToResolve, /* [out] */ ICorDebugTypeEnum **ppTypesEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypes )( + + HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypes )( ICorDebugAppDomain3 * This, /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum); - + END_INTERFACE } ICorDebugAppDomain3Vtbl; @@ -5669,26 +5678,26 @@ EXTERN_C const IID IID_ICorDebugAppDomain3; CONST_VTBL struct ICorDebugAppDomain3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain3_GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) \ - ( (This)->lpVtbl -> GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) ) + ( (This)->lpVtbl -> GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) ) #define ICorDebugAppDomain3_GetCachedWinRTTypes(This,ppGuidToTypeEnum) \ - ( (This)->lpVtbl -> GetCachedWinRTTypes(This,ppGuidToTypeEnum) ) + ( (This)->lpVtbl -> GetCachedWinRTTypes(This,ppGuidToTypeEnum) ) #endif /* COBJMACROS */ @@ -5705,47 +5714,47 @@ EXTERN_C const IID IID_ICorDebugAppDomain3; #define __ICorDebugAppDomain4_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FB99CC40-83BE-4724-AB3B-768E796EBAC2") ICorDebugAppDomain4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetObjectForCCW( + virtual HRESULT STDMETHODCALLTYPE GetObjectForCCW( /* [in] */ CORDB_ADDRESS ccwPointer, /* [out] */ ICorDebugValue **ppManagedObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomain4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain4 * This); - - HRESULT ( STDMETHODCALLTYPE *GetObjectForCCW )( + + HRESULT ( STDMETHODCALLTYPE *GetObjectForCCW )( ICorDebugAppDomain4 * This, /* [in] */ CORDB_ADDRESS ccwPointer, /* [out] */ ICorDebugValue **ppManagedObject); - + END_INTERFACE } ICorDebugAppDomain4Vtbl; @@ -5754,23 +5763,23 @@ EXTERN_C const IID IID_ICorDebugAppDomain4; CONST_VTBL struct ICorDebugAppDomain4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomain4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain4_GetObjectForCCW(This,ccwPointer,ppManagedObject) \ - ( (This)->lpVtbl -> GetObjectForCCW(This,ccwPointer,ppManagedObject) ) + ( (This)->lpVtbl -> GetObjectForCCW(This,ccwPointer,ppManagedObject) ) #endif /* COBJMACROS */ @@ -5784,10 +5793,10 @@ EXTERN_C const IID IID_ICorDebugAppDomain4; /* interface __MIDL_itf_cordebug_0000_0030 */ -/* [local] */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_c_ifspec; @@ -5797,81 +5806,81 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_s_ifspec; #define __ICorDebugAssembly_INTERFACE_DEFINED__ /* interface ICorDebugAssembly */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("df59507c-d47a-459e-bce2-6427eac8fd06") ICorDebugAssembly : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateModules( + + virtual HRESULT STDMETHODCALLTYPE EnumerateModules( /* [out] */ ICorDebugModuleEnum **ppModules) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeBase( + + virtual HRESULT STDMETHODCALLTYPE GetCodeBase( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssemblyVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly * This); - - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugAssembly * This, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( ICorDebugAssembly * This, /* [out] */ ICorDebugAppDomain **ppAppDomain); - - HRESULT ( STDMETHODCALLTYPE *EnumerateModules )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateModules )( ICorDebugAssembly * This, /* [out] */ ICorDebugModuleEnum **ppModules); - - HRESULT ( STDMETHODCALLTYPE *GetCodeBase )( + + HRESULT ( STDMETHODCALLTYPE *GetCodeBase )( ICorDebugAssembly * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugAssembly * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - + END_INTERFACE } ICorDebugAssemblyVtbl; @@ -5880,35 +5889,35 @@ EXTERN_C const IID IID_ICorDebugAssembly; CONST_VTBL struct ICorDebugAssemblyVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssembly_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugAssembly_GetAppDomain(This,ppAppDomain) \ - ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) + ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) #define ICorDebugAssembly_EnumerateModules(This,ppModules) \ - ( (This)->lpVtbl -> EnumerateModules(This,ppModules) ) + ( (This)->lpVtbl -> EnumerateModules(This,ppModules) ) #define ICorDebugAssembly_GetCodeBase(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetCodeBase(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetCodeBase(This,cchName,pcchName,szName) ) #define ICorDebugAssembly_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #endif /* COBJMACROS */ @@ -5922,7 +5931,7 @@ EXTERN_C const IID IID_ICorDebugAssembly; /* interface __MIDL_itf_cordebug_0000_0031 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -5934,45 +5943,45 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_s_ifspec; #define __ICorDebugAssembly2_INTERFACE_DEFINED__ /* interface ICorDebugAssembly2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("426d1f9e-6dd4-44c8-aec7-26cdbaf4e398") ICorDebugAssembly2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsFullyTrusted( + virtual HRESULT STDMETHODCALLTYPE IsFullyTrusted( /* [out] */ BOOL *pbFullyTrusted) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssembly2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly2 * This); - - HRESULT ( STDMETHODCALLTYPE *IsFullyTrusted )( + + HRESULT ( STDMETHODCALLTYPE *IsFullyTrusted )( ICorDebugAssembly2 * This, /* [out] */ BOOL *pbFullyTrusted); - + END_INTERFACE } ICorDebugAssembly2Vtbl; @@ -5981,23 +5990,23 @@ EXTERN_C const IID IID_ICorDebugAssembly2; CONST_VTBL struct ICorDebugAssembly2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssembly2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly2_IsFullyTrusted(This,pbFullyTrusted) \ - ( (This)->lpVtbl -> IsFullyTrusted(This,pbFullyTrusted) ) + ( (This)->lpVtbl -> IsFullyTrusted(This,pbFullyTrusted) ) #endif /* COBJMACROS */ @@ -6014,52 +6023,52 @@ EXTERN_C const IID IID_ICorDebugAssembly2; #define __ICorDebugAssembly3_INTERFACE_DEFINED__ /* interface ICorDebugAssembly3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("76361AB2-8C86-4FE9-96F2-F73D8843570A") ICorDebugAssembly3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContainerAssembly( + virtual HRESULT STDMETHODCALLTYPE GetContainerAssembly( ICorDebugAssembly **ppAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateContainedAssemblies( + + virtual HRESULT STDMETHODCALLTYPE EnumerateContainedAssemblies( ICorDebugAssemblyEnum **ppAssemblies) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssembly3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetContainerAssembly )( + + HRESULT ( STDMETHODCALLTYPE *GetContainerAssembly )( ICorDebugAssembly3 * This, ICorDebugAssembly **ppAssembly); - - HRESULT ( STDMETHODCALLTYPE *EnumerateContainedAssemblies )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateContainedAssemblies )( ICorDebugAssembly3 * This, ICorDebugAssemblyEnum **ppAssemblies); - + END_INTERFACE } ICorDebugAssembly3Vtbl; @@ -6068,26 +6077,26 @@ EXTERN_C const IID IID_ICorDebugAssembly3; CONST_VTBL struct ICorDebugAssembly3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssembly3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly3_GetContainerAssembly(This,ppAssembly) \ - ( (This)->lpVtbl -> GetContainerAssembly(This,ppAssembly) ) + ( (This)->lpVtbl -> GetContainerAssembly(This,ppAssembly) ) #define ICorDebugAssembly3_EnumerateContainedAssemblies(This,ppAssemblies) \ - ( (This)->lpVtbl -> EnumerateContainedAssemblies(This,ppAssemblies) ) + ( (This)->lpVtbl -> EnumerateContainedAssemblies(This,ppAssemblies) ) #endif /* COBJMACROS */ @@ -6101,7 +6110,7 @@ EXTERN_C const IID IID_ICorDebugAssembly3; /* interface __MIDL_itf_cordebug_0000_0033 */ -/* [local] */ +/* [local] */ #ifndef _DEF_COR_TYPEID_ #define _DEF_COR_TYPEID_ @@ -6128,64 +6137,64 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_s_ifspec; #define __ICorDebugHeapEnum_INTERFACE_DEFINED__ /* interface ICorDebugHeapEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("76D7DAB8-D044-11DF-9A15-7E29DFD72085") ICorDebugHeapEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugHeapEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugHeapEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugHeapEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugHeapEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugHeapEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugHeapEnumVtbl; @@ -6194,36 +6203,36 @@ EXTERN_C const IID IID_ICorDebugHeapEnum; CONST_VTBL struct ICorDebugHeapEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugHeapEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugHeapEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugHeapEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugHeapEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ @@ -6237,9 +6246,9 @@ EXTERN_C const IID IID_ICorDebugHeapEnum; /* interface __MIDL_itf_cordebug_0000_0034 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugGenerationTypes { CorDebug_Gen0 = 0, @@ -6257,11 +6266,11 @@ typedef struct _COR_SEGMENT ULONG heap; } COR_SEGMENT; -typedef +typedef enum CorDebugGCType { CorDebugWorkstationGC = 0, - CorDebugServerGC = ( CorDebugWorkstationGC + 1 ) + CorDebugServerGC = ( CorDebugWorkstationGC + 1 ) } CorDebugGCType; typedef struct _COR_HEAPINFO @@ -6282,64 +6291,64 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_s_ifspec; #define __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ /* interface ICorDebugHeapSegmentEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A2FA0F8E-D045-11DF-AC8E-CE2ADFD72085") ICorDebugHeapSegmentEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapSegmentEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapSegmentEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapSegmentEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapSegmentEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugHeapSegmentEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugHeapSegmentEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugHeapSegmentEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugHeapSegmentEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugHeapSegmentEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugHeapSegmentEnumVtbl; @@ -6348,36 +6357,36 @@ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; CONST_VTBL struct ICorDebugHeapSegmentEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapSegmentEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapSegmentEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapSegmentEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapSegmentEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugHeapSegmentEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugHeapSegmentEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugHeapSegmentEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugHeapSegmentEnum_Next(This,celt,segments,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,segments,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,segments,pceltFetched) ) #endif /* COBJMACROS */ @@ -6391,9 +6400,9 @@ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; /* interface __MIDL_itf_cordebug_0000_0035 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorGCReferenceType { CorHandleStrong = ( 1 << 0 ) , @@ -6434,64 +6443,64 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_s_ifspec; #define __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ /* interface ICorDebugGCReferenceEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C") ICorDebugGCReferenceEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugGCReferenceEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGCReferenceEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGCReferenceEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGCReferenceEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugGCReferenceEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugGCReferenceEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugGCReferenceEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugGCReferenceEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugGCReferenceEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugGCReferenceEnumVtbl; @@ -6500,36 +6509,36 @@ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; CONST_VTBL struct ICorDebugGCReferenceEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugGCReferenceEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGCReferenceEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGCReferenceEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGCReferenceEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugGCReferenceEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugGCReferenceEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugGCReferenceEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugGCReferenceEnum_Next(This,celt,roots,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,roots,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,roots,pceltFetched) ) #endif /* COBJMACROS */ @@ -6543,7 +6552,7 @@ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; /* interface __MIDL_itf_cordebug_0000_0036 */ -/* [local] */ +/* [local] */ #ifndef _DEF_COR_ARRAY_LAYOUT_ #define _DEF_COR_ARRAY_LAYOUT_ @@ -6584,7 +6593,7 @@ typedef struct COR_FIELD #endif // _DEF_COR_FIELD_ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_c_ifspec; @@ -6594,234 +6603,234 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_s_ifspec; #define __ICorDebugProcess_INTERFACE_DEFINED__ /* interface ICorDebugProcess */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3d6f5f64-7538-11d3-8d5b-00104b35e7ef") ICorDebugProcess : public ICorDebugController { public: - virtual HRESULT STDMETHODCALLTYPE GetID( + virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ DWORD *pdwProcessId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHandle( + + virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HPROCESS *phProcessHandle) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThread( + + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateObjects( + + virtual HRESULT STDMETHODCALLTYPE EnumerateObjects( /* [out] */ ICorDebugObjectEnum **ppObjects) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsTransitionStub( + + virtual HRESULT STDMETHODCALLTYPE IsTransitionStub( /* [in] */ CORDB_ADDRESS address, /* [out] */ BOOL *pbTransitionStub) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsOSSuspended( + + virtual HRESULT STDMETHODCALLTYPE IsOSSuspended( /* [in] */ DWORD threadID, /* [out] */ BOOL *pbSuspended) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE ReadMemory( + + virtual HRESULT STDMETHODCALLTYPE ReadMemory( /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ SIZE_T *read) = 0; - - virtual HRESULT STDMETHODCALLTYPE WriteMemory( + + virtual HRESULT STDMETHODCALLTYPE WriteMemory( /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [size_is][in] */ BYTE buffer[ ], /* [out] */ SIZE_T *written) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( + + virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( /* [in] */ DWORD threadID) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableLogMessages( + + virtual HRESULT STDMETHODCALLTYPE EnableLogMessages( /* [in] */ BOOL fOnOff) = 0; - - virtual HRESULT STDMETHODCALLTYPE ModifyLogSwitch( - /* [annotation][in] */ + + virtual HRESULT STDMETHODCALLTYPE ModifyLogSwitch( + /* [annotation][in] */ _In_ WCHAR *pLogSwitchName, /* [in] */ LONG lLevel) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateAppDomains( + + virtual HRESULT STDMETHODCALLTYPE EnumerateAppDomains( /* [out] */ ICorDebugAppDomainEnum **ppAppDomains) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE ThreadForFiberCookie( + + virtual HRESULT STDMETHODCALLTYPE ThreadForFiberCookie( /* [in] */ DWORD fiberCookie, /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHelperThreadID( + + virtual HRESULT STDMETHODCALLTYPE GetHelperThreadID( /* [out] */ DWORD *pThreadID) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcessVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess * This); - - HRESULT ( STDMETHODCALLTYPE *Stop )( + + HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugProcess * This, /* [in] */ DWORD dwTimeoutIgnored); - - HRESULT ( STDMETHODCALLTYPE *Continue )( + + HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugProcess * This, /* [in] */ BOOL fIsOutOfBand); - - HRESULT ( STDMETHODCALLTYPE *IsRunning )( + + HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugProcess * This, /* [out] */ BOOL *pbRunning); - - HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugProcess * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); - - HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugProcess * This, /* [out] */ ICorDebugThreadEnum **ppThreads); - - HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugProcess * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); - - HRESULT ( STDMETHODCALLTYPE *Detach )( + + HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugProcess * This); - - HRESULT ( STDMETHODCALLTYPE *Terminate )( + + HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugProcess * This, /* [in] */ UINT exitCode); - - HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugProcess * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - - HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugProcess * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); - - HRESULT ( STDMETHODCALLTYPE *GetID )( + + HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugProcess * This, /* [out] */ DWORD *pdwProcessId); - - HRESULT ( STDMETHODCALLTYPE *GetHandle )( + + HRESULT ( STDMETHODCALLTYPE *GetHandle )( ICorDebugProcess * This, /* [out] */ HPROCESS *phProcessHandle); - - HRESULT ( STDMETHODCALLTYPE *GetThread )( + + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugProcess * This, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugThread **ppThread); - - HRESULT ( STDMETHODCALLTYPE *EnumerateObjects )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateObjects )( ICorDebugProcess * This, /* [out] */ ICorDebugObjectEnum **ppObjects); - - HRESULT ( STDMETHODCALLTYPE *IsTransitionStub )( + + HRESULT ( STDMETHODCALLTYPE *IsTransitionStub )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [out] */ BOOL *pbTransitionStub); - - HRESULT ( STDMETHODCALLTYPE *IsOSSuspended )( + + HRESULT ( STDMETHODCALLTYPE *IsOSSuspended )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [out] */ BOOL *pbSuspended); - - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]); - - HRESULT ( STDMETHODCALLTYPE *ReadMemory )( + + HRESULT ( STDMETHODCALLTYPE *ReadMemory )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ SIZE_T *read); - - HRESULT ( STDMETHODCALLTYPE *WriteMemory )( + + HRESULT ( STDMETHODCALLTYPE *WriteMemory )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [size_is][in] */ BYTE buffer[ ], /* [out] */ SIZE_T *written); - - HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( + + HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( ICorDebugProcess * This, /* [in] */ DWORD threadID); - - HRESULT ( STDMETHODCALLTYPE *EnableLogMessages )( + + HRESULT ( STDMETHODCALLTYPE *EnableLogMessages )( ICorDebugProcess * This, /* [in] */ BOOL fOnOff); - - HRESULT ( STDMETHODCALLTYPE *ModifyLogSwitch )( + + HRESULT ( STDMETHODCALLTYPE *ModifyLogSwitch )( ICorDebugProcess * This, - /* [annotation][in] */ + /* [annotation][in] */ _In_ WCHAR *pLogSwitchName, /* [in] */ LONG lLevel); - - HRESULT ( STDMETHODCALLTYPE *EnumerateAppDomains )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateAppDomains )( ICorDebugProcess * This, /* [out] */ ICorDebugAppDomainEnum **ppAppDomains); - - HRESULT ( STDMETHODCALLTYPE *GetObject )( + + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugProcess * This, /* [out] */ ICorDebugValue **ppObject); - - HRESULT ( STDMETHODCALLTYPE *ThreadForFiberCookie )( + + HRESULT ( STDMETHODCALLTYPE *ThreadForFiberCookie )( ICorDebugProcess * This, /* [in] */ DWORD fiberCookie, /* [out] */ ICorDebugThread **ppThread); - - HRESULT ( STDMETHODCALLTYPE *GetHelperThreadID )( + + HRESULT ( STDMETHODCALLTYPE *GetHelperThreadID )( ICorDebugProcess * This, /* [out] */ DWORD *pThreadID); - + END_INTERFACE } ICorDebugProcessVtbl; @@ -6830,102 +6839,102 @@ EXTERN_C const IID IID_ICorDebugProcess; CONST_VTBL struct ICorDebugProcessVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess_Stop(This,dwTimeoutIgnored) \ - ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugProcess_Continue(This,fIsOutOfBand) \ - ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugProcess_IsRunning(This,pbRunning) \ - ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugProcess_HasQueuedCallbacks(This,pThread,pbQueued) \ - ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugProcess_EnumerateThreads(This,ppThreads) \ - ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugProcess_SetAllThreadsDebugState(This,state,pExceptThisThread) \ - ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugProcess_Detach(This) \ - ( (This)->lpVtbl -> Detach(This) ) + ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugProcess_Terminate(This,exitCode) \ - ( (This)->lpVtbl -> Terminate(This,exitCode) ) + ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugProcess_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugProcess_CommitChanges(This,cSnapshots,pSnapshots,pError) \ - ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugProcess_GetID(This,pdwProcessId) \ - ( (This)->lpVtbl -> GetID(This,pdwProcessId) ) + ( (This)->lpVtbl -> GetID(This,pdwProcessId) ) #define ICorDebugProcess_GetHandle(This,phProcessHandle) \ - ( (This)->lpVtbl -> GetHandle(This,phProcessHandle) ) + ( (This)->lpVtbl -> GetHandle(This,phProcessHandle) ) #define ICorDebugProcess_GetThread(This,dwThreadId,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,dwThreadId,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,dwThreadId,ppThread) ) #define ICorDebugProcess_EnumerateObjects(This,ppObjects) \ - ( (This)->lpVtbl -> EnumerateObjects(This,ppObjects) ) + ( (This)->lpVtbl -> EnumerateObjects(This,ppObjects) ) #define ICorDebugProcess_IsTransitionStub(This,address,pbTransitionStub) \ - ( (This)->lpVtbl -> IsTransitionStub(This,address,pbTransitionStub) ) + ( (This)->lpVtbl -> IsTransitionStub(This,address,pbTransitionStub) ) #define ICorDebugProcess_IsOSSuspended(This,threadID,pbSuspended) \ - ( (This)->lpVtbl -> IsOSSuspended(This,threadID,pbSuspended) ) + ( (This)->lpVtbl -> IsOSSuspended(This,threadID,pbSuspended) ) #define ICorDebugProcess_GetThreadContext(This,threadID,contextSize,context) \ - ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextSize,context) ) + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextSize,context) ) #define ICorDebugProcess_SetThreadContext(This,threadID,contextSize,context) \ - ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define ICorDebugProcess_ReadMemory(This,address,size,buffer,read) \ - ( (This)->lpVtbl -> ReadMemory(This,address,size,buffer,read) ) + ( (This)->lpVtbl -> ReadMemory(This,address,size,buffer,read) ) #define ICorDebugProcess_WriteMemory(This,address,size,buffer,written) \ - ( (This)->lpVtbl -> WriteMemory(This,address,size,buffer,written) ) + ( (This)->lpVtbl -> WriteMemory(This,address,size,buffer,written) ) #define ICorDebugProcess_ClearCurrentException(This,threadID) \ - ( (This)->lpVtbl -> ClearCurrentException(This,threadID) ) + ( (This)->lpVtbl -> ClearCurrentException(This,threadID) ) #define ICorDebugProcess_EnableLogMessages(This,fOnOff) \ - ( (This)->lpVtbl -> EnableLogMessages(This,fOnOff) ) + ( (This)->lpVtbl -> EnableLogMessages(This,fOnOff) ) #define ICorDebugProcess_ModifyLogSwitch(This,pLogSwitchName,lLevel) \ - ( (This)->lpVtbl -> ModifyLogSwitch(This,pLogSwitchName,lLevel) ) + ( (This)->lpVtbl -> ModifyLogSwitch(This,pLogSwitchName,lLevel) ) #define ICorDebugProcess_EnumerateAppDomains(This,ppAppDomains) \ - ( (This)->lpVtbl -> EnumerateAppDomains(This,ppAppDomains) ) + ( (This)->lpVtbl -> EnumerateAppDomains(This,ppAppDomains) ) #define ICorDebugProcess_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #define ICorDebugProcess_ThreadForFiberCookie(This,fiberCookie,ppThread) \ - ( (This)->lpVtbl -> ThreadForFiberCookie(This,fiberCookie,ppThread) ) + ( (This)->lpVtbl -> ThreadForFiberCookie(This,fiberCookie,ppThread) ) #define ICorDebugProcess_GetHelperThreadID(This,pThreadID) \ - ( (This)->lpVtbl -> GetHelperThreadID(This,pThreadID) ) + ( (This)->lpVtbl -> GetHelperThreadID(This,pThreadID) ) #endif /* COBJMACROS */ @@ -6939,7 +6948,7 @@ EXTERN_C const IID IID_ICorDebugProcess; /* interface __MIDL_itf_cordebug_0000_0037 */ -/* [local] */ +/* [local] */ #pragma warning(pop) @@ -6951,97 +6960,97 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0037_v0_0_s_ifspec; #define __ICorDebugProcess2_INTERFACE_DEFINED__ /* interface ICorDebugProcess2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AD1B3588-0EF0-4744-A496-AA09A9F80371") ICorDebugProcess2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetThreadForTaskID( + virtual HRESULT STDMETHODCALLTYPE GetThreadForTaskID( /* [in] */ TASKID taskid, /* [out] */ ICorDebugThread2 **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersion( + + virtual HRESULT STDMETHODCALLTYPE GetVersion( /* [out] */ COR_VERSION *version) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUnmanagedBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE SetUnmanagedBreakpoint( /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG32 bufsize, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *bufLen) = 0; - - virtual HRESULT STDMETHODCALLTYPE ClearUnmanagedBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE ClearUnmanagedBreakpoint( /* [in] */ CORDB_ADDRESS address) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDesiredNGENCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE SetDesiredNGENCompilerFlags( /* [in] */ DWORD pdwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDesiredNGENCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE GetDesiredNGENCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetReferenceValueFromGCHandle( + + virtual HRESULT STDMETHODCALLTYPE GetReferenceValueFromGCHandle( /* [in] */ UINT_PTR handle, /* [out] */ ICorDebugReferenceValue **pOutValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetThreadForTaskID )( + + HRESULT ( STDMETHODCALLTYPE *GetThreadForTaskID )( ICorDebugProcess2 * This, /* [in] */ TASKID taskid, /* [out] */ ICorDebugThread2 **ppThread); - - HRESULT ( STDMETHODCALLTYPE *GetVersion )( + + HRESULT ( STDMETHODCALLTYPE *GetVersion )( ICorDebugProcess2 * This, /* [out] */ COR_VERSION *version); - - HRESULT ( STDMETHODCALLTYPE *SetUnmanagedBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *SetUnmanagedBreakpoint )( ICorDebugProcess2 * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG32 bufsize, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *bufLen); - - HRESULT ( STDMETHODCALLTYPE *ClearUnmanagedBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *ClearUnmanagedBreakpoint )( ICorDebugProcess2 * This, /* [in] */ CORDB_ADDRESS address); - - HRESULT ( STDMETHODCALLTYPE *SetDesiredNGENCompilerFlags )( + + HRESULT ( STDMETHODCALLTYPE *SetDesiredNGENCompilerFlags )( ICorDebugProcess2 * This, /* [in] */ DWORD pdwFlags); - - HRESULT ( STDMETHODCALLTYPE *GetDesiredNGENCompilerFlags )( + + HRESULT ( STDMETHODCALLTYPE *GetDesiredNGENCompilerFlags )( ICorDebugProcess2 * This, /* [out] */ DWORD *pdwFlags); - - HRESULT ( STDMETHODCALLTYPE *GetReferenceValueFromGCHandle )( + + HRESULT ( STDMETHODCALLTYPE *GetReferenceValueFromGCHandle )( ICorDebugProcess2 * This, /* [in] */ UINT_PTR handle, /* [out] */ ICorDebugReferenceValue **pOutValue); - + END_INTERFACE } ICorDebugProcess2Vtbl; @@ -7050,41 +7059,41 @@ EXTERN_C const IID IID_ICorDebugProcess2; CONST_VTBL struct ICorDebugProcess2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess2_GetThreadForTaskID(This,taskid,ppThread) \ - ( (This)->lpVtbl -> GetThreadForTaskID(This,taskid,ppThread) ) + ( (This)->lpVtbl -> GetThreadForTaskID(This,taskid,ppThread) ) #define ICorDebugProcess2_GetVersion(This,version) \ - ( (This)->lpVtbl -> GetVersion(This,version) ) + ( (This)->lpVtbl -> GetVersion(This,version) ) #define ICorDebugProcess2_SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) \ - ( (This)->lpVtbl -> SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) ) + ( (This)->lpVtbl -> SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) ) #define ICorDebugProcess2_ClearUnmanagedBreakpoint(This,address) \ - ( (This)->lpVtbl -> ClearUnmanagedBreakpoint(This,address) ) + ( (This)->lpVtbl -> ClearUnmanagedBreakpoint(This,address) ) #define ICorDebugProcess2_SetDesiredNGENCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> SetDesiredNGENCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> SetDesiredNGENCompilerFlags(This,pdwFlags) ) #define ICorDebugProcess2_GetDesiredNGENCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetDesiredNGENCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetDesiredNGENCompilerFlags(This,pdwFlags) ) #define ICorDebugProcess2_GetReferenceValueFromGCHandle(This,handle,pOutValue) \ - ( (This)->lpVtbl -> GetReferenceValueFromGCHandle(This,handle,pOutValue) ) + ( (This)->lpVtbl -> GetReferenceValueFromGCHandle(This,handle,pOutValue) ) #endif /* COBJMACROS */ @@ -7101,47 +7110,47 @@ EXTERN_C const IID IID_ICorDebugProcess2; #define __ICorDebugProcess3_INTERFACE_DEFINED__ /* interface ICorDebugProcess3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2EE06488-C0D4-42B1-B26D-F3795EF606FB") ICorDebugProcess3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetEnableCustomNotification( + virtual HRESULT STDMETHODCALLTYPE SetEnableCustomNotification( ICorDebugClass *pClass, BOOL fEnable) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess3 * This); - - HRESULT ( STDMETHODCALLTYPE *SetEnableCustomNotification )( + + HRESULT ( STDMETHODCALLTYPE *SetEnableCustomNotification )( ICorDebugProcess3 * This, ICorDebugClass *pClass, BOOL fEnable); - + END_INTERFACE } ICorDebugProcess3Vtbl; @@ -7150,23 +7159,23 @@ EXTERN_C const IID IID_ICorDebugProcess3; CONST_VTBL struct ICorDebugProcess3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess3_SetEnableCustomNotification(This,pClass,fEnable) \ - ( (This)->lpVtbl -> SetEnableCustomNotification(This,pClass,fEnable) ) + ( (This)->lpVtbl -> SetEnableCustomNotification(This,pClass,fEnable) ) #endif /* COBJMACROS */ @@ -7183,142 +7192,142 @@ EXTERN_C const IID IID_ICorDebugProcess3; #define __ICorDebugProcess5_INTERFACE_DEFINED__ /* interface ICorDebugProcess5 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess5; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("21e9d9c0-fcb8-11df-8cff-0800200c9a66") ICorDebugProcess5 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetGCHeapInformation( + virtual HRESULT STDMETHODCALLTYPE GetGCHeapInformation( /* [out] */ COR_HEAPINFO *pHeapInfo) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateHeap( + + virtual HRESULT STDMETHODCALLTYPE EnumerateHeap( /* [out] */ ICorDebugHeapEnum **ppObjects) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateHeapRegions( + + virtual HRESULT STDMETHODCALLTYPE EnumerateHeapRegions( /* [out] */ ICorDebugHeapSegmentEnum **ppRegions) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [in] */ CORDB_ADDRESS addr, /* [out] */ ICorDebugObjectValue **pObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateGCReferences( + + virtual HRESULT STDMETHODCALLTYPE EnumerateGCReferences( /* [in] */ BOOL enumerateWeakReferences, /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateHandles( + + virtual HRESULT STDMETHODCALLTYPE EnumerateHandles( /* [in] */ CorGCReferenceType types, /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeID( + + virtual HRESULT STDMETHODCALLTYPE GetTypeID( /* [in] */ CORDB_ADDRESS obj, /* [out] */ COR_TYPEID *pId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeForTypeID( + + virtual HRESULT STDMETHODCALLTYPE GetTypeForTypeID( /* [in] */ COR_TYPEID id, /* [out] */ ICorDebugType **ppType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArrayLayout( + + virtual HRESULT STDMETHODCALLTYPE GetArrayLayout( /* [in] */ COR_TYPEID id, /* [out] */ COR_ARRAY_LAYOUT *pLayout) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeLayout( + + virtual HRESULT STDMETHODCALLTYPE GetTypeLayout( /* [in] */ COR_TYPEID id, /* [out] */ COR_TYPE_LAYOUT *pLayout) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTypeFields( + + virtual HRESULT STDMETHODCALLTYPE GetTypeFields( /* [in] */ COR_TYPEID id, ULONG32 celt, COR_FIELD fields[ ], ULONG32 *pceltNeeded) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableNGENPolicy( + + virtual HRESULT STDMETHODCALLTYPE EnableNGENPolicy( /* [in] */ CorDebugNGENPolicy ePolicy) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess5Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess5 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess5 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess5 * This); - - HRESULT ( STDMETHODCALLTYPE *GetGCHeapInformation )( + + HRESULT ( STDMETHODCALLTYPE *GetGCHeapInformation )( ICorDebugProcess5 * This, /* [out] */ COR_HEAPINFO *pHeapInfo); - - HRESULT ( STDMETHODCALLTYPE *EnumerateHeap )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateHeap )( ICorDebugProcess5 * This, /* [out] */ ICorDebugHeapEnum **ppObjects); - - HRESULT ( STDMETHODCALLTYPE *EnumerateHeapRegions )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateHeapRegions )( ICorDebugProcess5 * This, /* [out] */ ICorDebugHeapSegmentEnum **ppRegions); - - HRESULT ( STDMETHODCALLTYPE *GetObject )( + + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugProcess5 * This, /* [in] */ CORDB_ADDRESS addr, /* [out] */ ICorDebugObjectValue **pObject); - - HRESULT ( STDMETHODCALLTYPE *EnumerateGCReferences )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateGCReferences )( ICorDebugProcess5 * This, /* [in] */ BOOL enumerateWeakReferences, /* [out] */ ICorDebugGCReferenceEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *EnumerateHandles )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateHandles )( ICorDebugProcess5 * This, /* [in] */ CorGCReferenceType types, /* [out] */ ICorDebugGCReferenceEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( ICorDebugProcess5 * This, /* [in] */ CORDB_ADDRESS obj, /* [out] */ COR_TYPEID *pId); - - HRESULT ( STDMETHODCALLTYPE *GetTypeForTypeID )( + + HRESULT ( STDMETHODCALLTYPE *GetTypeForTypeID )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ ICorDebugType **ppType); - - HRESULT ( STDMETHODCALLTYPE *GetArrayLayout )( + + HRESULT ( STDMETHODCALLTYPE *GetArrayLayout )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ COR_ARRAY_LAYOUT *pLayout); - - HRESULT ( STDMETHODCALLTYPE *GetTypeLayout )( + + HRESULT ( STDMETHODCALLTYPE *GetTypeLayout )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ COR_TYPE_LAYOUT *pLayout); - - HRESULT ( STDMETHODCALLTYPE *GetTypeFields )( + + HRESULT ( STDMETHODCALLTYPE *GetTypeFields )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, ULONG32 celt, COR_FIELD fields[ ], ULONG32 *pceltNeeded); - - HRESULT ( STDMETHODCALLTYPE *EnableNGENPolicy )( + + HRESULT ( STDMETHODCALLTYPE *EnableNGENPolicy )( ICorDebugProcess5 * This, /* [in] */ CorDebugNGENPolicy ePolicy); - + END_INTERFACE } ICorDebugProcess5Vtbl; @@ -7327,56 +7336,56 @@ EXTERN_C const IID IID_ICorDebugProcess5; CONST_VTBL struct ICorDebugProcess5Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess5_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess5_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess5_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess5_GetGCHeapInformation(This,pHeapInfo) \ - ( (This)->lpVtbl -> GetGCHeapInformation(This,pHeapInfo) ) + ( (This)->lpVtbl -> GetGCHeapInformation(This,pHeapInfo) ) #define ICorDebugProcess5_EnumerateHeap(This,ppObjects) \ - ( (This)->lpVtbl -> EnumerateHeap(This,ppObjects) ) + ( (This)->lpVtbl -> EnumerateHeap(This,ppObjects) ) #define ICorDebugProcess5_EnumerateHeapRegions(This,ppRegions) \ - ( (This)->lpVtbl -> EnumerateHeapRegions(This,ppRegions) ) + ( (This)->lpVtbl -> EnumerateHeapRegions(This,ppRegions) ) #define ICorDebugProcess5_GetObject(This,addr,pObject) \ - ( (This)->lpVtbl -> GetObject(This,addr,pObject) ) + ( (This)->lpVtbl -> GetObject(This,addr,pObject) ) #define ICorDebugProcess5_EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) \ - ( (This)->lpVtbl -> EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) ) + ( (This)->lpVtbl -> EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) ) #define ICorDebugProcess5_EnumerateHandles(This,types,ppEnum) \ - ( (This)->lpVtbl -> EnumerateHandles(This,types,ppEnum) ) + ( (This)->lpVtbl -> EnumerateHandles(This,types,ppEnum) ) #define ICorDebugProcess5_GetTypeID(This,obj,pId) \ - ( (This)->lpVtbl -> GetTypeID(This,obj,pId) ) + ( (This)->lpVtbl -> GetTypeID(This,obj,pId) ) #define ICorDebugProcess5_GetTypeForTypeID(This,id,ppType) \ - ( (This)->lpVtbl -> GetTypeForTypeID(This,id,ppType) ) + ( (This)->lpVtbl -> GetTypeForTypeID(This,id,ppType) ) #define ICorDebugProcess5_GetArrayLayout(This,id,pLayout) \ - ( (This)->lpVtbl -> GetArrayLayout(This,id,pLayout) ) + ( (This)->lpVtbl -> GetArrayLayout(This,id,pLayout) ) #define ICorDebugProcess5_GetTypeLayout(This,id,pLayout) \ - ( (This)->lpVtbl -> GetTypeLayout(This,id,pLayout) ) + ( (This)->lpVtbl -> GetTypeLayout(This,id,pLayout) ) #define ICorDebugProcess5_GetTypeFields(This,id,celt,fields,pceltNeeded) \ - ( (This)->lpVtbl -> GetTypeFields(This,id,celt,fields,pceltNeeded) ) + ( (This)->lpVtbl -> GetTypeFields(This,id,celt,fields,pceltNeeded) ) #define ICorDebugProcess5_EnableNGENPolicy(This,ePolicy) \ - ( (This)->lpVtbl -> EnableNGENPolicy(This,ePolicy) ) + ( (This)->lpVtbl -> EnableNGENPolicy(This,ePolicy) ) #endif /* COBJMACROS */ @@ -7390,22 +7399,22 @@ EXTERN_C const IID IID_ICorDebugProcess5; /* interface __MIDL_itf_cordebug_0000_0040 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugRecordFormat { FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1, FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2 } CorDebugRecordFormat; -typedef +typedef enum CorDebugDecodeEventFlagsWindows { IS_FIRST_CHANCE = 1 } CorDebugDecodeEventFlagsWindows; -typedef +typedef enum CorDebugDebugEventKind { DEBUG_EVENT_KIND_MODULE_LOADED = 1, @@ -7416,7 +7425,7 @@ enum CorDebugDebugEventKind DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6 } CorDebugDebugEventKind; -typedef +typedef enum CorDebugStateChange { PROCESS_RUNNING = 0x1, @@ -7432,52 +7441,52 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_s_ifspec; #define __ICorDebugDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugDebugEvent */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("41BD395D-DE99-48F1-BF7A-CC0F44A6D281") ICorDebugDebugEvent : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetEventKind( + virtual HRESULT STDMETHODCALLTYPE GetEventKind( /* [out] */ CorDebugDebugEventKind *pDebugEventKind) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThread( + + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDebugEventVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDebugEvent * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDebugEvent * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDebugEvent * This); - - HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); - - HRESULT ( STDMETHODCALLTYPE *GetThread )( + + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); - + END_INTERFACE } ICorDebugDebugEventVtbl; @@ -7486,26 +7495,26 @@ EXTERN_C const IID IID_ICorDebugDebugEvent; CONST_VTBL struct ICorDebugDebugEventVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDebugEvent_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDebugEvent_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDebugEvent_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDebugEvent_GetEventKind(This,pDebugEventKind) \ - ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugDebugEvent_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #endif /* COBJMACROS */ @@ -7519,23 +7528,23 @@ EXTERN_C const IID IID_ICorDebugDebugEvent; /* interface __MIDL_itf_cordebug_0000_0041 */ -/* [local] */ +/* [local] */ -typedef +typedef enum CorDebugCodeInvokeKind { CODE_INVOKE_KIND_NONE = 0, CODE_INVOKE_KIND_RETURN = ( CODE_INVOKE_KIND_NONE + 1 ) , - CODE_INVOKE_KIND_TAILCALL = ( CODE_INVOKE_KIND_RETURN + 1 ) + CODE_INVOKE_KIND_TAILCALL = ( CODE_INVOKE_KIND_RETURN + 1 ) } CorDebugCodeInvokeKind; -typedef +typedef enum CorDebugCodeInvokePurpose { CODE_INVOKE_PURPOSE_NONE = 0, CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION = ( CODE_INVOKE_PURPOSE_NONE + 1 ) , CODE_INVOKE_PURPOSE_CLASS_INIT = ( CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION + 1 ) , - CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH = ( CODE_INVOKE_PURPOSE_CLASS_INIT + 1 ) + CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH = ( CODE_INVOKE_PURPOSE_CLASS_INIT + 1 ) } CorDebugCodeInvokePurpose; @@ -7547,65 +7556,65 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_s_ifspec; #define __ICorDebugProcess6_INTERFACE_DEFINED__ /* interface ICorDebugProcess6 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess6; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("11588775-7205-4CEB-A41A-93753C3153E9") ICorDebugProcess6 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE DecodeEvent( + virtual HRESULT STDMETHODCALLTYPE DecodeEvent( /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, /* [in] */ CorDebugRecordFormat format, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugDebugEvent **ppEvent) = 0; - - virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( + + virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( /* [in] */ CorDebugStateChange change) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCode( + + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [in] */ CORDB_ADDRESS codeAddress, /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableVirtualModuleSplitting( + + virtual HRESULT STDMETHODCALLTYPE EnableVirtualModuleSplitting( BOOL enableSplitting) = 0; - - virtual HRESULT STDMETHODCALLTYPE MarkDebuggerAttached( + + virtual HRESULT STDMETHODCALLTYPE MarkDebuggerAttached( BOOL fIsAttached) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetExportStepInfo( + + virtual HRESULT STDMETHODCALLTYPE GetExportStepInfo( /* [in] */ LPCWSTR pszExportName, /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess6Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess6 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess6 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess6 * This); - - HRESULT ( STDMETHODCALLTYPE *DecodeEvent )( + + HRESULT ( STDMETHODCALLTYPE *DecodeEvent )( ICorDebugProcess6 * This, /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, @@ -7613,30 +7622,30 @@ EXTERN_C const IID IID_ICorDebugProcess6; /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugDebugEvent **ppEvent); - - HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( + + HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( ICorDebugProcess6 * This, /* [in] */ CorDebugStateChange change); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugProcess6 * This, /* [in] */ CORDB_ADDRESS codeAddress, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *EnableVirtualModuleSplitting )( + + HRESULT ( STDMETHODCALLTYPE *EnableVirtualModuleSplitting )( ICorDebugProcess6 * This, BOOL enableSplitting); - - HRESULT ( STDMETHODCALLTYPE *MarkDebuggerAttached )( + + HRESULT ( STDMETHODCALLTYPE *MarkDebuggerAttached )( ICorDebugProcess6 * This, BOOL fIsAttached); - - HRESULT ( STDMETHODCALLTYPE *GetExportStepInfo )( + + HRESULT ( STDMETHODCALLTYPE *GetExportStepInfo )( ICorDebugProcess6 * This, /* [in] */ LPCWSTR pszExportName, /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose); - + END_INTERFACE } ICorDebugProcess6Vtbl; @@ -7645,38 +7654,38 @@ EXTERN_C const IID IID_ICorDebugProcess6; CONST_VTBL struct ICorDebugProcess6Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess6_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess6_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess6_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess6_DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) \ - ( (This)->lpVtbl -> DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) ) + ( (This)->lpVtbl -> DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) ) #define ICorDebugProcess6_ProcessStateChanged(This,change) \ - ( (This)->lpVtbl -> ProcessStateChanged(This,change) ) + ( (This)->lpVtbl -> ProcessStateChanged(This,change) ) #define ICorDebugProcess6_GetCode(This,codeAddress,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,codeAddress,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,codeAddress,ppCode) ) #define ICorDebugProcess6_EnableVirtualModuleSplitting(This,enableSplitting) \ - ( (This)->lpVtbl -> EnableVirtualModuleSplitting(This,enableSplitting) ) + ( (This)->lpVtbl -> EnableVirtualModuleSplitting(This,enableSplitting) ) #define ICorDebugProcess6_MarkDebuggerAttached(This,fIsAttached) \ - ( (This)->lpVtbl -> MarkDebuggerAttached(This,fIsAttached) ) + ( (This)->lpVtbl -> MarkDebuggerAttached(This,fIsAttached) ) #define ICorDebugProcess6_GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) \ - ( (This)->lpVtbl -> GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) ) + ( (This)->lpVtbl -> GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) ) #endif /* COBJMACROS */ @@ -7690,13 +7699,13 @@ EXTERN_C const IID IID_ICorDebugProcess6; /* interface __MIDL_itf_cordebug_0000_0042 */ -/* [local] */ +/* [local] */ -typedef +typedef enum WriteableMetadataUpdateMode { LegacyCompatPolicy = 0, - AlwaysShowUpdates = ( LegacyCompatPolicy + 1 ) + AlwaysShowUpdates = ( LegacyCompatPolicy + 1 ) } WriteableMetadataUpdateMode; @@ -7708,45 +7717,45 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0042_v0_0_s_ifspec; #define __ICorDebugProcess7_INTERFACE_DEFINED__ /* interface ICorDebugProcess7 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess7; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("9B2C54E4-119F-4D6F-B402-527603266D69") ICorDebugProcess7 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetWriteableMetadataUpdateMode( + virtual HRESULT STDMETHODCALLTYPE SetWriteableMetadataUpdateMode( WriteableMetadataUpdateMode flags) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess7Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess7 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess7 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess7 * This); - - HRESULT ( STDMETHODCALLTYPE *SetWriteableMetadataUpdateMode )( + + HRESULT ( STDMETHODCALLTYPE *SetWriteableMetadataUpdateMode )( ICorDebugProcess7 * This, WriteableMetadataUpdateMode flags); - + END_INTERFACE } ICorDebugProcess7Vtbl; @@ -7755,23 +7764,23 @@ EXTERN_C const IID IID_ICorDebugProcess7; CONST_VTBL struct ICorDebugProcess7Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess7_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess7_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess7_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess7_SetWriteableMetadataUpdateMode(This,flags) \ - ( (This)->lpVtbl -> SetWriteableMetadataUpdateMode(This,flags) ) + ( (This)->lpVtbl -> SetWriteableMetadataUpdateMode(This,flags) ) #endif /* COBJMACROS */ @@ -7788,45 +7797,45 @@ EXTERN_C const IID IID_ICorDebugProcess7; #define __ICorDebugProcess8_INTERFACE_DEFINED__ /* interface ICorDebugProcess8 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess8; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2E6F28C1-85EB-4141-80AD-0A90944B9639") ICorDebugProcess8 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnableExceptionCallbacksOutsideOfMyCode( + virtual HRESULT STDMETHODCALLTYPE EnableExceptionCallbacksOutsideOfMyCode( /* [in] */ BOOL enableExceptionsOutsideOfJMC) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess8Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess8 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess8 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess8 * This); - - HRESULT ( STDMETHODCALLTYPE *EnableExceptionCallbacksOutsideOfMyCode )( + + HRESULT ( STDMETHODCALLTYPE *EnableExceptionCallbacksOutsideOfMyCode )( ICorDebugProcess8 * This, /* [in] */ BOOL enableExceptionsOutsideOfJMC); - + END_INTERFACE } ICorDebugProcess8Vtbl; @@ -7835,23 +7844,23 @@ EXTERN_C const IID IID_ICorDebugProcess8; CONST_VTBL struct ICorDebugProcess8Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess8_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess8_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess8_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess8_EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) \ - ( (This)->lpVtbl -> EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) ) + ( (This)->lpVtbl -> EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) ) #endif /* COBJMACROS */ @@ -7868,45 +7877,45 @@ EXTERN_C const IID IID_ICorDebugProcess8; #define __ICorDebugProcess10_INTERFACE_DEFINED__ /* interface ICorDebugProcess10 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess10; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("8F378F6F-1017-4461-9890-ECF64C54079F") ICorDebugProcess10 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents( + virtual HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents( BOOL fEnable) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess10Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess10 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess10 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess10 * This); - - HRESULT ( STDMETHODCALLTYPE *EnableGCNotificationEvents )( + + HRESULT ( STDMETHODCALLTYPE *EnableGCNotificationEvents )( ICorDebugProcess10 * This, BOOL fEnable); - + END_INTERFACE } ICorDebugProcess10Vtbl; @@ -7915,23 +7924,23 @@ EXTERN_C const IID IID_ICorDebugProcess10; CONST_VTBL struct ICorDebugProcess10Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess10_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess10_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess10_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess10_EnableGCNotificationEvents(This,fEnable) \ - ( (This)->lpVtbl -> EnableGCNotificationEvents(This,fEnable) ) + ( (This)->lpVtbl -> EnableGCNotificationEvents(This,fEnable) ) #endif /* COBJMACROS */ @@ -7945,7 +7954,7 @@ EXTERN_C const IID IID_ICorDebugProcess10; /* interface __MIDL_itf_cordebug_0000_0045 */ -/* [local] */ +/* [local] */ typedef struct _COR_MEMORY_RANGE { @@ -7962,64 +7971,64 @@ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0045_v0_0_s_ifspec; #define __ICorDebugMemoryRangeEnum_INTERFACE_DEFINED__ /* interface ICorDebugMemoryRangeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D1A0BCFC-5865-4437-BE3F-36F022951F8A") ICorDebugMemoryRangeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_MEMORY_RANGE objects[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMemoryRangeEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMemoryRangeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMemoryRangeEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMemoryRangeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugMemoryRangeEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugMemoryRangeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugMemoryRangeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugMemoryRangeEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugMemoryRangeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_MEMORY_RANGE objects[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugMemoryRangeEnumVtbl; @@ -8028,36 +8037,36 @@ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; CONST_VTBL struct ICorDebugMemoryRangeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMemoryRangeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMemoryRangeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMemoryRangeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMemoryRangeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugMemoryRangeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugMemoryRangeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugMemoryRangeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugMemoryRangeEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ @@ -8074,45 +8083,45 @@ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; #define __ICorDebugProcess11_INTERFACE_DEFINED__ /* interface ICorDebugProcess11 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess11; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("344B37AA-F2C0-4D3B-9909-91CCF787DA8C") ICorDebugProcess11 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateLoaderHeapMemoryRegions( + virtual HRESULT STDMETHODCALLTYPE EnumerateLoaderHeapMemoryRegions( /* [out] */ ICorDebugMemoryRangeEnum **ppRanges) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcess11Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess11 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess11 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess11 * This); - - HRESULT ( STDMETHODCALLTYPE *EnumerateLoaderHeapMemoryRegions )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateLoaderHeapMemoryRegions )( ICorDebugProcess11 * This, /* [out] */ ICorDebugMemoryRangeEnum **ppRanges); - + END_INTERFACE } ICorDebugProcess11Vtbl; @@ -8121,23 +8130,23 @@ EXTERN_C const IID IID_ICorDebugProcess11; CONST_VTBL struct ICorDebugProcess11Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcess11_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess11_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess11_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess11_EnumerateLoaderHeapMemoryRegions(This,ppRanges) \ - ( (This)->lpVtbl -> EnumerateLoaderHeapMemoryRegions(This,ppRanges) ) + ( (This)->lpVtbl -> EnumerateLoaderHeapMemoryRegions(This,ppRanges) ) #endif /* COBJMACROS */ @@ -8154,53 +8163,53 @@ EXTERN_C const IID IID_ICorDebugProcess11; #define __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugModuleDebugEvent */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("51A15E8D-9FFF-4864-9B87-F4FBDEA747A2") ICorDebugModuleDebugEvent : public ICorDebugDebugEvent { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleDebugEventVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleDebugEvent * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleDebugEvent * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleDebugEvent * This); - - HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugModuleDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); - - HRESULT ( STDMETHODCALLTYPE *GetThread )( + + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugModuleDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); - - HRESULT ( STDMETHODCALLTYPE *GetModule )( + + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugModuleDebugEvent * This, /* [out] */ ICorDebugModule **ppModule); - + END_INTERFACE } ICorDebugModuleDebugEventVtbl; @@ -8209,30 +8218,30 @@ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; CONST_VTBL struct ICorDebugModuleDebugEventVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModuleDebugEvent_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleDebugEvent_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleDebugEvent_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleDebugEvent_GetEventKind(This,pDebugEventKind) \ - ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugModuleDebugEvent_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugModuleDebugEvent_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #endif /* COBJMACROS */ @@ -8249,67 +8258,67 @@ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; #define __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugExceptionDebugEvent */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AF79EC94-4752-419C-A626-5FB1CC1A5AB7") ICorDebugExceptionDebugEvent : public ICorDebugDebugEvent { public: - virtual HRESULT STDMETHODCALLTYPE GetStackPointer( + virtual HRESULT STDMETHODCALLTYPE GetStackPointer( /* [out] */ CORDB_ADDRESS *pStackPointer) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetNativeIP( + + virtual HRESULT STDMETHODCALLTYPE GetNativeIP( /* [out] */ CORDB_ADDRESS *pIP) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFlags( + + virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ CorDebugExceptionFlags *pdwFlags) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugExceptionDebugEventVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionDebugEvent * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionDebugEvent * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionDebugEvent * This); - - HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugExceptionDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); - - HRESULT ( STDMETHODCALLTYPE *GetThread )( + + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugExceptionDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); - - HRESULT ( STDMETHODCALLTYPE *GetStackPointer )( + + HRESULT ( STDMETHODCALLTYPE *GetStackPointer )( ICorDebugExceptionDebugEvent * This, /* [out] */ CORDB_ADDRESS *pStackPointer); - - HRESULT ( STDMETHODCALLTYPE *GetNativeIP )( + + HRESULT ( STDMETHODCALLTYPE *GetNativeIP )( ICorDebugExceptionDebugEvent * This, /* [out] */ CORDB_ADDRESS *pIP); - - HRESULT ( STDMETHODCALLTYPE *GetFlags )( + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( ICorDebugExceptionDebugEvent * This, /* [out] */ CorDebugExceptionFlags *pdwFlags); - + END_INTERFACE } ICorDebugExceptionDebugEventVtbl; @@ -8318,36 +8327,36 @@ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; CONST_VTBL struct ICorDebugExceptionDebugEventVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugExceptionDebugEvent_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionDebugEvent_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionDebugEvent_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionDebugEvent_GetEventKind(This,pDebugEventKind) \ - ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugExceptionDebugEvent_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugExceptionDebugEvent_GetStackPointer(This,pStackPointer) \ - ( (This)->lpVtbl -> GetStackPointer(This,pStackPointer) ) + ( (This)->lpVtbl -> GetStackPointer(This,pStackPointer) ) #define ICorDebugExceptionDebugEvent_GetNativeIP(This,pIP) \ - ( (This)->lpVtbl -> GetNativeIP(This,pIP) ) + ( (This)->lpVtbl -> GetNativeIP(This,pIP) ) #define ICorDebugExceptionDebugEvent_GetFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetFlags(This,pdwFlags) ) #endif /* COBJMACROS */ @@ -8364,52 +8373,52 @@ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; #define __ICorDebugBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAE8-8A68-11d2-983C-0000F808342D") ICorDebugBreakpoint : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE Activate( + virtual HRESULT STDMETHODCALLTYPE Activate( /* [in] */ BOOL bActive) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsActive( + + virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBreakpointVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBreakpoint * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBreakpoint * This); - - HRESULT ( STDMETHODCALLTYPE *Activate )( + + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugBreakpoint * This, /* [in] */ BOOL bActive); - - HRESULT ( STDMETHODCALLTYPE *IsActive )( + + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugBreakpoint * This, /* [out] */ BOOL *pbActive); - + END_INTERFACE } ICorDebugBreakpointVtbl; @@ -8418,26 +8427,26 @@ EXTERN_C const IID IID_ICorDebugBreakpoint; CONST_VTBL struct ICorDebugBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #endif /* COBJMACROS */ @@ -8454,60 +8463,60 @@ EXTERN_C const IID IID_ICorDebugBreakpoint; #define __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugFunctionBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAE9-8A68-11d2-983C-0000F808342D") ICorDebugFunctionBreakpoint : public ICorDebugBreakpoint { public: - virtual HRESULT STDMETHODCALLTYPE GetFunction( + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOffset( + + virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ ULONG32 *pnOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunctionBreakpointVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunctionBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunctionBreakpoint * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunctionBreakpoint * This); - - HRESULT ( STDMETHODCALLTYPE *Activate )( + + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugFunctionBreakpoint * This, /* [in] */ BOOL bActive); - - HRESULT ( STDMETHODCALLTYPE *IsActive )( + + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugFunctionBreakpoint * This, /* [out] */ BOOL *pbActive); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugFunctionBreakpoint * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetOffset )( + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugFunctionBreakpoint * This, /* [out] */ ULONG32 *pnOffset); - + END_INTERFACE } ICorDebugFunctionBreakpointVtbl; @@ -8516,33 +8525,33 @@ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; CONST_VTBL struct ICorDebugFunctionBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunctionBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunctionBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunctionBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunctionBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugFunctionBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugFunctionBreakpoint_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugFunctionBreakpoint_GetOffset(This,pnOffset) \ - ( (This)->lpVtbl -> GetOffset(This,pnOffset) ) + ( (This)->lpVtbl -> GetOffset(This,pnOffset) ) #endif /* COBJMACROS */ @@ -8559,53 +8568,53 @@ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; #define __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugModuleBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEA-8A68-11d2-983C-0000F808342D") ICorDebugModuleBreakpoint : public ICorDebugBreakpoint { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleBreakpointVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleBreakpoint * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleBreakpoint * This); - - HRESULT ( STDMETHODCALLTYPE *Activate )( + + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugModuleBreakpoint * This, /* [in] */ BOOL bActive); - - HRESULT ( STDMETHODCALLTYPE *IsActive )( + + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugModuleBreakpoint * This, /* [out] */ BOOL *pbActive); - - HRESULT ( STDMETHODCALLTYPE *GetModule )( + + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugModuleBreakpoint * This, /* [out] */ ICorDebugModule **ppModule); - + END_INTERFACE } ICorDebugModuleBreakpointVtbl; @@ -8614,30 +8623,30 @@ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; CONST_VTBL struct ICorDebugModuleBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModuleBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugModuleBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugModuleBreakpoint_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #endif /* COBJMACROS */ @@ -8654,53 +8663,53 @@ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; #define __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugValueBreakpoint */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValueBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEB-8A68-11d2-983C-0000F808342D") ICorDebugValueBreakpoint : public ICorDebugBreakpoint { public: - virtual HRESULT STDMETHODCALLTYPE GetValue( + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValueBreakpointVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValueBreakpoint * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValueBreakpoint * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValueBreakpoint * This); - - HRESULT ( STDMETHODCALLTYPE *Activate )( + + HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugValueBreakpoint * This, /* [in] */ BOOL bActive); - - HRESULT ( STDMETHODCALLTYPE *IsActive )( + + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugValueBreakpoint * This, /* [out] */ BOOL *pbActive); - - HRESULT ( STDMETHODCALLTYPE *GetValue )( + + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugValueBreakpoint * This, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugValueBreakpointVtbl; @@ -8709,30 +8718,30 @@ EXTERN_C const IID IID_ICorDebugValueBreakpoint; CONST_VTBL struct ICorDebugValueBreakpointVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValueBreakpoint_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValueBreakpoint_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValueBreakpoint_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValueBreakpoint_Activate(This,bActive) \ - ( (This)->lpVtbl -> Activate(This,bActive) ) + ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugValueBreakpoint_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugValueBreakpoint_GetValue(This,ppValue) \ - ( (This)->lpVtbl -> GetValue(This,ppValue) ) + ( (This)->lpVtbl -> GetValue(This,ppValue) ) #endif /* COBJMACROS */ @@ -8749,9 +8758,9 @@ EXTERN_C const IID IID_ICorDebugValueBreakpoint; #define __ICorDebugStepper_INTERFACE_DEFINED__ /* interface ICorDebugStepper */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugIntercept { INTERCEPT_NONE = 0, @@ -8763,7 +8772,7 @@ enum CorDebugIntercept INTERCEPT_ALL = 0xffff } CorDebugIntercept; -typedef +typedef enum CorDebugUnmappedStop { STOP_NONE = 0, @@ -8785,88 +8794,88 @@ typedef struct COR_DEBUG_STEP_RANGE EXTERN_C const IID IID_ICorDebugStepper; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEC-8A68-11d2-983C-0000F808342D") ICorDebugStepper : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsActive( + virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; - + virtual HRESULT STDMETHODCALLTYPE Deactivate( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetInterceptMask( + + virtual HRESULT STDMETHODCALLTYPE SetInterceptMask( /* [in] */ CorDebugIntercept mask) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetUnmappedStopMask( + + virtual HRESULT STDMETHODCALLTYPE SetUnmappedStopMask( /* [in] */ CorDebugUnmappedStop mask) = 0; - - virtual HRESULT STDMETHODCALLTYPE Step( + + virtual HRESULT STDMETHODCALLTYPE Step( /* [in] */ BOOL bStepIn) = 0; - - virtual HRESULT STDMETHODCALLTYPE StepRange( + + virtual HRESULT STDMETHODCALLTYPE StepRange( /* [in] */ BOOL bStepIn, /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], /* [in] */ ULONG32 cRangeCount) = 0; - + virtual HRESULT STDMETHODCALLTYPE StepOut( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetRangeIL( + + virtual HRESULT STDMETHODCALLTYPE SetRangeIL( /* [in] */ BOOL bIL) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStepperVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepper * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepper * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepper * This); - - HRESULT ( STDMETHODCALLTYPE *IsActive )( + + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugStepper * This, /* [out] */ BOOL *pbActive); - - HRESULT ( STDMETHODCALLTYPE *Deactivate )( + + HRESULT ( STDMETHODCALLTYPE *Deactivate )( ICorDebugStepper * This); - - HRESULT ( STDMETHODCALLTYPE *SetInterceptMask )( + + HRESULT ( STDMETHODCALLTYPE *SetInterceptMask )( ICorDebugStepper * This, /* [in] */ CorDebugIntercept mask); - - HRESULT ( STDMETHODCALLTYPE *SetUnmappedStopMask )( + + HRESULT ( STDMETHODCALLTYPE *SetUnmappedStopMask )( ICorDebugStepper * This, /* [in] */ CorDebugUnmappedStop mask); - - HRESULT ( STDMETHODCALLTYPE *Step )( + + HRESULT ( STDMETHODCALLTYPE *Step )( ICorDebugStepper * This, /* [in] */ BOOL bStepIn); - - HRESULT ( STDMETHODCALLTYPE *StepRange )( + + HRESULT ( STDMETHODCALLTYPE *StepRange )( ICorDebugStepper * This, /* [in] */ BOOL bStepIn, /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], /* [in] */ ULONG32 cRangeCount); - - HRESULT ( STDMETHODCALLTYPE *StepOut )( + + HRESULT ( STDMETHODCALLTYPE *StepOut )( ICorDebugStepper * This); - - HRESULT ( STDMETHODCALLTYPE *SetRangeIL )( + + HRESULT ( STDMETHODCALLTYPE *SetRangeIL )( ICorDebugStepper * This, /* [in] */ BOOL bIL); - + END_INTERFACE } ICorDebugStepperVtbl; @@ -8875,44 +8884,44 @@ EXTERN_C const IID IID_ICorDebugStepper; CONST_VTBL struct ICorDebugStepperVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStepper_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepper_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepper_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepper_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugStepper_Deactivate(This) \ - ( (This)->lpVtbl -> Deactivate(This) ) + ( (This)->lpVtbl -> Deactivate(This) ) #define ICorDebugStepper_SetInterceptMask(This,mask) \ - ( (This)->lpVtbl -> SetInterceptMask(This,mask) ) + ( (This)->lpVtbl -> SetInterceptMask(This,mask) ) #define ICorDebugStepper_SetUnmappedStopMask(This,mask) \ - ( (This)->lpVtbl -> SetUnmappedStopMask(This,mask) ) + ( (This)->lpVtbl -> SetUnmappedStopMask(This,mask) ) #define ICorDebugStepper_Step(This,bStepIn) \ - ( (This)->lpVtbl -> Step(This,bStepIn) ) + ( (This)->lpVtbl -> Step(This,bStepIn) ) #define ICorDebugStepper_StepRange(This,bStepIn,ranges,cRangeCount) \ - ( (This)->lpVtbl -> StepRange(This,bStepIn,ranges,cRangeCount) ) + ( (This)->lpVtbl -> StepRange(This,bStepIn,ranges,cRangeCount) ) #define ICorDebugStepper_StepOut(This) \ - ( (This)->lpVtbl -> StepOut(This) ) + ( (This)->lpVtbl -> StepOut(This) ) #define ICorDebugStepper_SetRangeIL(This,bIL) \ - ( (This)->lpVtbl -> SetRangeIL(This,bIL) ) + ( (This)->lpVtbl -> SetRangeIL(This,bIL) ) #endif /* COBJMACROS */ @@ -8929,45 +8938,45 @@ EXTERN_C const IID IID_ICorDebugStepper; #define __ICorDebugStepper2_INTERFACE_DEFINED__ /* interface ICorDebugStepper2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStepper2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7") ICorDebugStepper2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetJMC( + virtual HRESULT STDMETHODCALLTYPE SetJMC( /* [in] */ BOOL fIsJMCStepper) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStepper2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepper2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepper2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepper2 * This); - - HRESULT ( STDMETHODCALLTYPE *SetJMC )( + + HRESULT ( STDMETHODCALLTYPE *SetJMC )( ICorDebugStepper2 * This, /* [in] */ BOOL fIsJMCStepper); - + END_INTERFACE } ICorDebugStepper2Vtbl; @@ -8976,23 +8985,23 @@ EXTERN_C const IID IID_ICorDebugStepper2; CONST_VTBL struct ICorDebugStepper2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStepper2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepper2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepper2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepper2_SetJMC(This,fIsJMCStepper) \ - ( (This)->lpVtbl -> SetJMC(This,fIsJMCStepper) ) + ( (This)->lpVtbl -> SetJMC(This,fIsJMCStepper) ) #endif /* COBJMACROS */ @@ -9009,9 +9018,9 @@ EXTERN_C const IID IID_ICorDebugStepper2; #define __ICorDebugRegisterSet_INTERFACE_DEFINED__ /* interface ICorDebugRegisterSet */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugRegister { REGISTER_INSTRUCTION_POINTER = 0, @@ -9182,86 +9191,86 @@ enum CorDebugRegister REGISTER_ARM64_V28 = ( REGISTER_ARM64_V27 + 1 ) , REGISTER_ARM64_V29 = ( REGISTER_ARM64_V28 + 1 ) , REGISTER_ARM64_V30 = ( REGISTER_ARM64_V29 + 1 ) , - REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) + REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) } CorDebugRegister; EXTERN_C const IID IID_ICorDebugRegisterSet; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB0B-8A68-11d2-983C-0000F808342D") ICorDebugRegisterSet : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( + virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( /* [out] */ ULONG64 *pAvailable) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisters( + + virtual HRESULT STDMETHODCALLTYPE GetRegisters( /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetRegisters( + + virtual HRESULT STDMETHODCALLTYPE SetRegisters( /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRegisterSetVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRegisterSet * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRegisterSet * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRegisterSet * This); - - HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( + + HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( ICorDebugRegisterSet * This, /* [out] */ ULONG64 *pAvailable); - - HRESULT ( STDMETHODCALLTYPE *GetRegisters )( + + HRESULT ( STDMETHODCALLTYPE *GetRegisters )( ICorDebugRegisterSet * This, /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetRegisters )( + + HRESULT ( STDMETHODCALLTYPE *SetRegisters )( ICorDebugRegisterSet * This, /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugRegisterSet * This, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugRegisterSet * This, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]); - + END_INTERFACE } ICorDebugRegisterSetVtbl; @@ -9270,35 +9279,35 @@ EXTERN_C const IID IID_ICorDebugRegisterSet; CONST_VTBL struct ICorDebugRegisterSetVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRegisterSet_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRegisterSet_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRegisterSet_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRegisterSet_GetRegistersAvailable(This,pAvailable) \ - ( (This)->lpVtbl -> GetRegistersAvailable(This,pAvailable) ) + ( (This)->lpVtbl -> GetRegistersAvailable(This,pAvailable) ) #define ICorDebugRegisterSet_GetRegisters(This,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> GetRegisters(This,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> GetRegisters(This,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet_SetRegisters(This,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> SetRegisters(This,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> SetRegisters(This,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet_GetThreadContext(This,contextSize,context) \ - ( (This)->lpVtbl -> GetThreadContext(This,contextSize,context) ) + ( (This)->lpVtbl -> GetThreadContext(This,contextSize,context) ) #define ICorDebugRegisterSet_SetThreadContext(This,contextSize,context) \ - ( (This)->lpVtbl -> SetThreadContext(This,contextSize,context) ) + ( (This)->lpVtbl -> SetThreadContext(This,contextSize,context) ) #endif /* COBJMACROS */ @@ -9315,73 +9324,73 @@ EXTERN_C const IID IID_ICorDebugRegisterSet; #define __ICorDebugRegisterSet2_INTERFACE_DEFINED__ /* interface ICorDebugRegisterSet2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRegisterSet2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("6DC7BA3F-89BA-4459-9EC1-9D60937B468D") ICorDebugRegisterSet2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( + virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( /* [in] */ ULONG32 numChunks, /* [size_is][out] */ BYTE availableRegChunks[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisters( + + virtual HRESULT STDMETHODCALLTYPE GetRegisters( /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetRegisters( + + virtual HRESULT STDMETHODCALLTYPE SetRegisters( /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugRegisterSet2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRegisterSet2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRegisterSet2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRegisterSet2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( + + HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 numChunks, /* [size_is][out] */ BYTE availableRegChunks[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetRegisters )( + + HRESULT ( STDMETHODCALLTYPE *GetRegisters )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetRegisters )( + + HRESULT ( STDMETHODCALLTYPE *SetRegisters )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); - + END_INTERFACE } ICorDebugRegisterSet2Vtbl; @@ -9390,29 +9399,29 @@ EXTERN_C const IID IID_ICorDebugRegisterSet2; CONST_VTBL struct ICorDebugRegisterSet2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRegisterSet2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRegisterSet2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRegisterSet2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRegisterSet2_GetRegistersAvailable(This,numChunks,availableRegChunks) \ - ( (This)->lpVtbl -> GetRegistersAvailable(This,numChunks,availableRegChunks) ) + ( (This)->lpVtbl -> GetRegistersAvailable(This,numChunks,availableRegChunks) ) #define ICorDebugRegisterSet2_GetRegisters(This,maskCount,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> GetRegisters(This,maskCount,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> GetRegisters(This,maskCount,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet2_SetRegisters(This,maskCount,mask,regCount,regBuffer) \ - ( (This)->lpVtbl -> SetRegisters(This,maskCount,mask,regCount,regBuffer) ) + ( (This)->lpVtbl -> SetRegisters(This,maskCount,mask,regCount,regBuffer) ) #endif /* COBJMACROS */ @@ -9429,9 +9438,9 @@ EXTERN_C const IID IID_ICorDebugRegisterSet2; #define __ICorDebugThread_INTERFACE_DEFINED__ /* interface ICorDebugThread */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugUserState { USER_STOP_REQUESTED = 0x1, @@ -9449,142 +9458,142 @@ enum CorDebugUserState EXTERN_C const IID IID_ICorDebugThread; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("938c6d66-7fb6-4f69-b389-425b8987329b") ICorDebugThread : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetID( + + virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ DWORD *pdwThreadId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetHandle( + + virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HTHREAD *phThreadHandle) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetDebugState( + + virtual HRESULT STDMETHODCALLTYPE SetDebugState( /* [in] */ CorDebugThreadState state) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDebugState( + + virtual HRESULT STDMETHODCALLTYPE GetDebugState( /* [out] */ CorDebugThreadState *pState) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetUserState( + + virtual HRESULT STDMETHODCALLTYPE GetUserState( /* [out] */ CorDebugUserState *pState) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentException( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentException( /* [out] */ ICorDebugValue **ppExceptionObject) = 0; - + virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateStepper( + + virtual HRESULT STDMETHODCALLTYPE CreateStepper( /* [out] */ ICorDebugStepper **ppStepper) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateChains( + + virtual HRESULT STDMETHODCALLTYPE EnumerateChains( /* [out] */ ICorDebugChainEnum **ppChains) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveChain( + + virtual HRESULT STDMETHODCALLTYPE GetActiveChain( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( + + virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateEval( + + virtual HRESULT STDMETHODCALLTYPE CreateEval( /* [out] */ ICorDebugEval **ppEval) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetObject( + + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThreadVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread * This); - - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugThread * This, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *GetID )( + + HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugThread * This, /* [out] */ DWORD *pdwThreadId); - - HRESULT ( STDMETHODCALLTYPE *GetHandle )( + + HRESULT ( STDMETHODCALLTYPE *GetHandle )( ICorDebugThread * This, /* [out] */ HTHREAD *phThreadHandle); - - HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( ICorDebugThread * This, /* [out] */ ICorDebugAppDomain **ppAppDomain); - - HRESULT ( STDMETHODCALLTYPE *SetDebugState )( + + HRESULT ( STDMETHODCALLTYPE *SetDebugState )( ICorDebugThread * This, /* [in] */ CorDebugThreadState state); - - HRESULT ( STDMETHODCALLTYPE *GetDebugState )( + + HRESULT ( STDMETHODCALLTYPE *GetDebugState )( ICorDebugThread * This, /* [out] */ CorDebugThreadState *pState); - - HRESULT ( STDMETHODCALLTYPE *GetUserState )( + + HRESULT ( STDMETHODCALLTYPE *GetUserState )( ICorDebugThread * This, /* [out] */ CorDebugUserState *pState); - - HRESULT ( STDMETHODCALLTYPE *GetCurrentException )( + + HRESULT ( STDMETHODCALLTYPE *GetCurrentException )( ICorDebugThread * This, /* [out] */ ICorDebugValue **ppExceptionObject); - - HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( + + HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( ICorDebugThread * This); - - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugThread * This, /* [out] */ ICorDebugStepper **ppStepper); - - HRESULT ( STDMETHODCALLTYPE *EnumerateChains )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateChains )( ICorDebugThread * This, /* [out] */ ICorDebugChainEnum **ppChains); - - HRESULT ( STDMETHODCALLTYPE *GetActiveChain )( + + HRESULT ( STDMETHODCALLTYPE *GetActiveChain )( ICorDebugThread * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( + + HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( ICorDebugThread * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugThread * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); - - HRESULT ( STDMETHODCALLTYPE *CreateEval )( + + HRESULT ( STDMETHODCALLTYPE *CreateEval )( ICorDebugThread * This, /* [out] */ ICorDebugEval **ppEval); - - HRESULT ( STDMETHODCALLTYPE *GetObject )( + + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugThread * This, /* [out] */ ICorDebugValue **ppObject); - + END_INTERFACE } ICorDebugThreadVtbl; @@ -9593,68 +9602,68 @@ EXTERN_C const IID IID_ICorDebugThread; CONST_VTBL struct ICorDebugThreadVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugThread_GetID(This,pdwThreadId) \ - ( (This)->lpVtbl -> GetID(This,pdwThreadId) ) + ( (This)->lpVtbl -> GetID(This,pdwThreadId) ) #define ICorDebugThread_GetHandle(This,phThreadHandle) \ - ( (This)->lpVtbl -> GetHandle(This,phThreadHandle) ) + ( (This)->lpVtbl -> GetHandle(This,phThreadHandle) ) #define ICorDebugThread_GetAppDomain(This,ppAppDomain) \ - ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) + ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) #define ICorDebugThread_SetDebugState(This,state) \ - ( (This)->lpVtbl -> SetDebugState(This,state) ) + ( (This)->lpVtbl -> SetDebugState(This,state) ) #define ICorDebugThread_GetDebugState(This,pState) \ - ( (This)->lpVtbl -> GetDebugState(This,pState) ) + ( (This)->lpVtbl -> GetDebugState(This,pState) ) #define ICorDebugThread_GetUserState(This,pState) \ - ( (This)->lpVtbl -> GetUserState(This,pState) ) + ( (This)->lpVtbl -> GetUserState(This,pState) ) #define ICorDebugThread_GetCurrentException(This,ppExceptionObject) \ - ( (This)->lpVtbl -> GetCurrentException(This,ppExceptionObject) ) + ( (This)->lpVtbl -> GetCurrentException(This,ppExceptionObject) ) #define ICorDebugThread_ClearCurrentException(This) \ - ( (This)->lpVtbl -> ClearCurrentException(This) ) + ( (This)->lpVtbl -> ClearCurrentException(This) ) #define ICorDebugThread_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugThread_EnumerateChains(This,ppChains) \ - ( (This)->lpVtbl -> EnumerateChains(This,ppChains) ) + ( (This)->lpVtbl -> EnumerateChains(This,ppChains) ) #define ICorDebugThread_GetActiveChain(This,ppChain) \ - ( (This)->lpVtbl -> GetActiveChain(This,ppChain) ) + ( (This)->lpVtbl -> GetActiveChain(This,ppChain) ) #define ICorDebugThread_GetActiveFrame(This,ppFrame) \ - ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) + ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) #define ICorDebugThread_GetRegisterSet(This,ppRegisters) \ - ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugThread_CreateEval(This,ppEval) \ - ( (This)->lpVtbl -> CreateEval(This,ppEval) ) + ( (This)->lpVtbl -> CreateEval(This,ppEval) ) #define ICorDebugThread_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #endif /* COBJMACROS */ @@ -9671,7 +9680,7 @@ EXTERN_C const IID IID_ICorDebugThread; #define __ICorDebugThread2_INTERFACE_DEFINED__ /* interface ICorDebugThread2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ typedef struct _COR_ACTIVE_FUNCTION { @@ -9686,71 +9695,71 @@ typedef struct _COR_ACTIVE_FUNCTION EXTERN_C const IID IID_ICorDebugThread2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("2BD956D9-7B07-4bef-8A98-12AA862417C5") ICorDebugThread2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetActiveFunctions( + virtual HRESULT STDMETHODCALLTYPE GetActiveFunctions( /* [in] */ ULONG32 cFunctions, /* [out] */ ULONG32 *pcFunctions, /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetConnectionID( + + virtual HRESULT STDMETHODCALLTYPE GetConnectionID( /* [out] */ CONNID *pdwConnectionId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetTaskID( + + virtual HRESULT STDMETHODCALLTYPE GetTaskID( /* [out] */ TASKID *pTaskId) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVolatileOSThreadID( + + virtual HRESULT STDMETHODCALLTYPE GetVolatileOSThreadID( /* [out] */ DWORD *pdwTid) = 0; - - virtual HRESULT STDMETHODCALLTYPE InterceptCurrentException( + + virtual HRESULT STDMETHODCALLTYPE InterceptCurrentException( /* [in] */ ICorDebugFrame *pFrame) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetActiveFunctions )( + + HRESULT ( STDMETHODCALLTYPE *GetActiveFunctions )( ICorDebugThread2 * This, /* [in] */ ULONG32 cFunctions, /* [out] */ ULONG32 *pcFunctions, /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetConnectionID )( + + HRESULT ( STDMETHODCALLTYPE *GetConnectionID )( ICorDebugThread2 * This, /* [out] */ CONNID *pdwConnectionId); - - HRESULT ( STDMETHODCALLTYPE *GetTaskID )( + + HRESULT ( STDMETHODCALLTYPE *GetTaskID )( ICorDebugThread2 * This, /* [out] */ TASKID *pTaskId); - - HRESULT ( STDMETHODCALLTYPE *GetVolatileOSThreadID )( + + HRESULT ( STDMETHODCALLTYPE *GetVolatileOSThreadID )( ICorDebugThread2 * This, /* [out] */ DWORD *pdwTid); - - HRESULT ( STDMETHODCALLTYPE *InterceptCurrentException )( + + HRESULT ( STDMETHODCALLTYPE *InterceptCurrentException )( ICorDebugThread2 * This, /* [in] */ ICorDebugFrame *pFrame); - + END_INTERFACE } ICorDebugThread2Vtbl; @@ -9759,35 +9768,35 @@ EXTERN_C const IID IID_ICorDebugThread2; CONST_VTBL struct ICorDebugThread2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread2_GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) \ - ( (This)->lpVtbl -> GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) ) + ( (This)->lpVtbl -> GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) ) #define ICorDebugThread2_GetConnectionID(This,pdwConnectionId) \ - ( (This)->lpVtbl -> GetConnectionID(This,pdwConnectionId) ) + ( (This)->lpVtbl -> GetConnectionID(This,pdwConnectionId) ) #define ICorDebugThread2_GetTaskID(This,pTaskId) \ - ( (This)->lpVtbl -> GetTaskID(This,pTaskId) ) + ( (This)->lpVtbl -> GetTaskID(This,pTaskId) ) #define ICorDebugThread2_GetVolatileOSThreadID(This,pdwTid) \ - ( (This)->lpVtbl -> GetVolatileOSThreadID(This,pdwTid) ) + ( (This)->lpVtbl -> GetVolatileOSThreadID(This,pdwTid) ) #define ICorDebugThread2_InterceptCurrentException(This,pFrame) \ - ( (This)->lpVtbl -> InterceptCurrentException(This,pFrame) ) + ( (This)->lpVtbl -> InterceptCurrentException(This,pFrame) ) #endif /* COBJMACROS */ @@ -9804,56 +9813,56 @@ EXTERN_C const IID IID_ICorDebugThread2; #define __ICorDebugThread3_INTERFACE_DEFINED__ /* interface ICorDebugThread3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5") ICorDebugThread3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( + virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( /* [out] */ ICorDebugStackWalk **ppStackWalk) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveInternalFrames( + + virtual HRESULT STDMETHODCALLTYPE GetActiveInternalFrames( /* [in] */ ULONG32 cInternalFrames, /* [out] */ ULONG32 *pcInternalFrames, /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread3 * This); - - HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( + + HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( ICorDebugThread3 * This, /* [out] */ ICorDebugStackWalk **ppStackWalk); - - HRESULT ( STDMETHODCALLTYPE *GetActiveInternalFrames )( + + HRESULT ( STDMETHODCALLTYPE *GetActiveInternalFrames )( ICorDebugThread3 * This, /* [in] */ ULONG32 cInternalFrames, /* [out] */ ULONG32 *pcInternalFrames, /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]); - + END_INTERFACE } ICorDebugThread3Vtbl; @@ -9862,26 +9871,26 @@ EXTERN_C const IID IID_ICorDebugThread3; CONST_VTBL struct ICorDebugThread3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread3_CreateStackWalk(This,ppStackWalk) \ - ( (This)->lpVtbl -> CreateStackWalk(This,ppStackWalk) ) + ( (This)->lpVtbl -> CreateStackWalk(This,ppStackWalk) ) #define ICorDebugThread3_GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) \ - ( (This)->lpVtbl -> GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) ) + ( (This)->lpVtbl -> GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) ) #endif /* COBJMACROS */ @@ -9898,57 +9907,57 @@ EXTERN_C const IID IID_ICorDebugThread3; #define __ICorDebugThread4_INTERFACE_DEFINED__ /* interface ICorDebugThread4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("1A1F204B-1C66-4637-823F-3EE6C744A69C") ICorDebugThread4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE HasUnhandledException( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBlockingObjects( + + virtual HRESULT STDMETHODCALLTYPE GetBlockingObjects( /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentCustomDebuggerNotification( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentCustomDebuggerNotification( /* [out] */ ICorDebugValue **ppNotificationObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThread4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread4 * This); - - HRESULT ( STDMETHODCALLTYPE *HasUnhandledException )( + + HRESULT ( STDMETHODCALLTYPE *HasUnhandledException )( ICorDebugThread4 * This); - - HRESULT ( STDMETHODCALLTYPE *GetBlockingObjects )( + + HRESULT ( STDMETHODCALLTYPE *GetBlockingObjects )( ICorDebugThread4 * This, /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCurrentCustomDebuggerNotification )( + + HRESULT ( STDMETHODCALLTYPE *GetCurrentCustomDebuggerNotification )( ICorDebugThread4 * This, /* [out] */ ICorDebugValue **ppNotificationObject); - + END_INTERFACE } ICorDebugThread4Vtbl; @@ -9957,29 +9966,29 @@ EXTERN_C const IID IID_ICorDebugThread4; CONST_VTBL struct ICorDebugThread4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThread4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread4_HasUnhandledException(This) \ - ( (This)->lpVtbl -> HasUnhandledException(This) ) + ( (This)->lpVtbl -> HasUnhandledException(This) ) #define ICorDebugThread4_GetBlockingObjects(This,ppBlockingObjectEnum) \ - ( (This)->lpVtbl -> GetBlockingObjects(This,ppBlockingObjectEnum) ) + ( (This)->lpVtbl -> GetBlockingObjects(This,ppBlockingObjectEnum) ) #define ICorDebugThread4_GetCurrentCustomDebuggerNotification(This,ppNotificationObject) \ - ( (This)->lpVtbl -> GetCurrentCustomDebuggerNotification(This,ppNotificationObject) ) + ( (This)->lpVtbl -> GetCurrentCustomDebuggerNotification(This,ppNotificationObject) ) #endif /* COBJMACROS */ @@ -9992,13 +10001,95 @@ EXTERN_C const IID IID_ICorDebugThread4; #endif /* __ICorDebugThread4_INTERFACE_DEFINED__ */ +#ifndef __ICorDebugThread5_INTERFACE_DEFINED__ +#define __ICorDebugThread5_INTERFACE_DEFINED__ + +/* interface ICorDebugThread5 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugThread5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F98421C4-E506-4D24-916F-0237EE853EC6") + ICorDebugThread5 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetBytesAllocated( + /* [out] */ ULONG64 *pSohAllocatedBytes, + /* [out] */ ULONG64 *pUohAllocatedBytes) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugThread5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugThread5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugThread5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugThread5 * This); + + HRESULT ( STDMETHODCALLTYPE *GetBytesAllocated )( + ICorDebugThread5 * This, + /* [out] */ ULONG64 *pSohAllocatedBytes, + /* [out] */ ULONG64 *pUohAllocatedBytes); + + END_INTERFACE + } ICorDebugThread5Vtbl; + + interface ICorDebugThread5 + { + CONST_VTBL struct ICorDebugThread5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugThread5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugThread5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugThread5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugThread5_GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) \ + ( (This)->lpVtbl -> GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugThread5_INTERFACE_DEFINED__ */ + + #ifndef __ICorDebugStackWalk_INTERFACE_DEFINED__ #define __ICorDebugStackWalk_INTERFACE_DEFINED__ /* interface ICorDebugStackWalk */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugSetContextFlag { SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1, @@ -10009,68 +10100,68 @@ enum CorDebugSetContextFlag EXTERN_C const IID IID_ICorDebugStackWalk; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A0647DE9-55DE-4816-929C-385271C64CF7") ICorDebugStackWalk : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetContext( + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetContext( + + virtual HRESULT STDMETHODCALLTYPE SetContext( /* [in] */ CorDebugSetContextFlag flag, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) = 0; - + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFrame( + + virtual HRESULT STDMETHODCALLTYPE GetFrame( /* [out] */ ICorDebugFrame **pFrame) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStackWalkVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStackWalk * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStackWalk * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStackWalk * This); - - HRESULT ( STDMETHODCALLTYPE *GetContext )( + + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugStackWalk * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetContext )( + + HRESULT ( STDMETHODCALLTYPE *SetContext )( ICorDebugStackWalk * This, /* [in] */ CorDebugSetContextFlag flag, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugStackWalk * This); - - HRESULT ( STDMETHODCALLTYPE *GetFrame )( + + HRESULT ( STDMETHODCALLTYPE *GetFrame )( ICorDebugStackWalk * This, /* [out] */ ICorDebugFrame **pFrame); - + END_INTERFACE } ICorDebugStackWalkVtbl; @@ -10079,32 +10170,32 @@ EXTERN_C const IID IID_ICorDebugStackWalk; CONST_VTBL struct ICorDebugStackWalkVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStackWalk_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStackWalk_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStackWalk_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStackWalk_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ - ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) + ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) #define ICorDebugStackWalk_SetContext(This,flag,contextSize,context) \ - ( (This)->lpVtbl -> SetContext(This,flag,contextSize,context) ) + ( (This)->lpVtbl -> SetContext(This,flag,contextSize,context) ) #define ICorDebugStackWalk_Next(This) \ - ( (This)->lpVtbl -> Next(This) ) + ( (This)->lpVtbl -> Next(This) ) #define ICorDebugStackWalk_GetFrame(This,pFrame) \ - ( (This)->lpVtbl -> GetFrame(This,pFrame) ) + ( (This)->lpVtbl -> GetFrame(This,pFrame) ) #endif /* COBJMACROS */ @@ -10121,9 +10212,9 @@ EXTERN_C const IID IID_ICorDebugStackWalk; #define __ICorDebugChain_INTERFACE_DEFINED__ /* interface ICorDebugChain */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugChainReason { CHAIN_NONE = 0, @@ -10145,118 +10236,118 @@ enum CorDebugChainReason EXTERN_C const IID IID_ICorDebugChain; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEE-8A68-11d2-983C-0000F808342D") ICorDebugChain : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetThread( + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackRange( + + virtual HRESULT STDMETHODCALLTYPE GetStackRange( /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetContext( + + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [out] */ ICorDebugContext **ppContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCaller( + + virtual HRESULT STDMETHODCALLTYPE GetCaller( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCallee( + + virtual HRESULT STDMETHODCALLTYPE GetCallee( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetPrevious( + + virtual HRESULT STDMETHODCALLTYPE GetPrevious( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetNext( + + virtual HRESULT STDMETHODCALLTYPE GetNext( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsManaged( + + virtual HRESULT STDMETHODCALLTYPE IsManaged( /* [out] */ BOOL *pManaged) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateFrames( + + virtual HRESULT STDMETHODCALLTYPE EnumerateFrames( /* [out] */ ICorDebugFrameEnum **ppFrames) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( + + virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetReason( + + virtual HRESULT STDMETHODCALLTYPE GetReason( /* [out] */ CorDebugChainReason *pReason) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugChainVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugChain * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugChain * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugChain * This); - - HRESULT ( STDMETHODCALLTYPE *GetThread )( + + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugChain * This, /* [out] */ ICorDebugThread **ppThread); - - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugChain * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - - HRESULT ( STDMETHODCALLTYPE *GetContext )( + + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugChain * This, /* [out] */ ICorDebugContext **ppContext); - - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetPrevious )( + + HRESULT ( STDMETHODCALLTYPE *GetPrevious )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetNext )( + + HRESULT ( STDMETHODCALLTYPE *GetNext )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *IsManaged )( + + HRESULT ( STDMETHODCALLTYPE *IsManaged )( ICorDebugChain * This, /* [out] */ BOOL *pManaged); - - HRESULT ( STDMETHODCALLTYPE *EnumerateFrames )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateFrames )( ICorDebugChain * This, /* [out] */ ICorDebugFrameEnum **ppFrames); - - HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( + + HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( ICorDebugChain * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugChain * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); - - HRESULT ( STDMETHODCALLTYPE *GetReason )( + + HRESULT ( STDMETHODCALLTYPE *GetReason )( ICorDebugChain * This, /* [out] */ CorDebugChainReason *pReason); - + END_INTERFACE } ICorDebugChainVtbl; @@ -10265,56 +10356,56 @@ EXTERN_C const IID IID_ICorDebugChain; CONST_VTBL struct ICorDebugChainVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugChain_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugChain_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugChain_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugChain_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugChain_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugChain_GetContext(This,ppContext) \ - ( (This)->lpVtbl -> GetContext(This,ppContext) ) + ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugChain_GetCaller(This,ppChain) \ - ( (This)->lpVtbl -> GetCaller(This,ppChain) ) + ( (This)->lpVtbl -> GetCaller(This,ppChain) ) #define ICorDebugChain_GetCallee(This,ppChain) \ - ( (This)->lpVtbl -> GetCallee(This,ppChain) ) + ( (This)->lpVtbl -> GetCallee(This,ppChain) ) #define ICorDebugChain_GetPrevious(This,ppChain) \ - ( (This)->lpVtbl -> GetPrevious(This,ppChain) ) + ( (This)->lpVtbl -> GetPrevious(This,ppChain) ) #define ICorDebugChain_GetNext(This,ppChain) \ - ( (This)->lpVtbl -> GetNext(This,ppChain) ) + ( (This)->lpVtbl -> GetNext(This,ppChain) ) #define ICorDebugChain_IsManaged(This,pManaged) \ - ( (This)->lpVtbl -> IsManaged(This,pManaged) ) + ( (This)->lpVtbl -> IsManaged(This,pManaged) ) #define ICorDebugChain_EnumerateFrames(This,ppFrames) \ - ( (This)->lpVtbl -> EnumerateFrames(This,ppFrames) ) + ( (This)->lpVtbl -> EnumerateFrames(This,ppFrames) ) #define ICorDebugChain_GetActiveFrame(This,ppFrame) \ - ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) + ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) #define ICorDebugChain_GetRegisterSet(This,ppRegisters) \ - ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugChain_GetReason(This,pReason) \ - ( (This)->lpVtbl -> GetReason(This,pReason) ) + ( (This)->lpVtbl -> GetReason(This,pReason) ) #endif /* COBJMACROS */ @@ -10331,96 +10422,96 @@ EXTERN_C const IID IID_ICorDebugChain; #define __ICorDebugFrame_INTERFACE_DEFINED__ /* interface ICorDebugFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAEF-8A68-11d2-983C-0000F808342D") ICorDebugFrame : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetChain( + virtual HRESULT STDMETHODCALLTYPE GetChain( /* [out] */ ICorDebugChain **ppChain) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCode( + + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunction( + + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionToken( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionToken( /* [out] */ mdMethodDef *pToken) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackRange( + + virtual HRESULT STDMETHODCALLTYPE GetStackRange( /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCaller( + + virtual HRESULT STDMETHODCALLTYPE GetCaller( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCallee( + + virtual HRESULT STDMETHODCALLTYPE GetCallee( /* [out] */ ICorDebugFrame **ppFrame) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateStepper( + + virtual HRESULT STDMETHODCALLTYPE CreateStepper( /* [out] */ ICorDebugStepper **ppStepper) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFrameVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFrame * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFrame * This); - - HRESULT ( STDMETHODCALLTYPE *GetChain )( + + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugFrame * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugFrame * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugFrame * This, /* [out] */ mdMethodDef *pToken); - - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + END_INTERFACE } ICorDebugFrameVtbl; @@ -10429,44 +10520,44 @@ EXTERN_C const IID IID_ICorDebugFrame; CONST_VTBL struct ICorDebugFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #endif /* COBJMACROS */ @@ -10483,9 +10574,9 @@ EXTERN_C const IID IID_ICorDebugFrame; #define __ICorDebugInternalFrame_INTERFACE_DEFINED__ /* interface ICorDebugInternalFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugInternalFrameType { STUBFRAME_NONE = 0, @@ -10505,72 +10596,72 @@ enum CorDebugInternalFrameType EXTERN_C const IID IID_ICorDebugInternalFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4") ICorDebugInternalFrame : public ICorDebugFrame { public: - virtual HRESULT STDMETHODCALLTYPE GetFrameType( + virtual HRESULT STDMETHODCALLTYPE GetFrameType( /* [out] */ CorDebugInternalFrameType *pType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugInternalFrameVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInternalFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInternalFrame * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInternalFrame * This); - - HRESULT ( STDMETHODCALLTYPE *GetChain )( + + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugInternalFrame * This, /* [out] */ mdMethodDef *pToken); - - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugInternalFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - - HRESULT ( STDMETHODCALLTYPE *GetFrameType )( + + HRESULT ( STDMETHODCALLTYPE *GetFrameType )( ICorDebugInternalFrame * This, /* [out] */ CorDebugInternalFrameType *pType); - + END_INTERFACE } ICorDebugInternalFrameVtbl; @@ -10579,48 +10670,48 @@ EXTERN_C const IID IID_ICorDebugInternalFrame; CONST_VTBL struct ICorDebugInternalFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugInternalFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInternalFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInternalFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInternalFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugInternalFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugInternalFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugInternalFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugInternalFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugInternalFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugInternalFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugInternalFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugInternalFrame_GetFrameType(This,pType) \ - ( (This)->lpVtbl -> GetFrameType(This,pType) ) + ( (This)->lpVtbl -> GetFrameType(This,pType) ) #endif /* COBJMACROS */ @@ -10637,54 +10728,54 @@ EXTERN_C const IID IID_ICorDebugInternalFrame; #define __ICorDebugInternalFrame2_INTERFACE_DEFINED__ /* interface ICorDebugInternalFrame2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugInternalFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("C0815BDC-CFAB-447e-A779-C116B454EB5B") ICorDebugInternalFrame2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetAddress( + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsCloserToLeaf( + + virtual HRESULT STDMETHODCALLTYPE IsCloserToLeaf( /* [in] */ ICorDebugFrame *pFrameToCompare, /* [out] */ BOOL *pIsCloser) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugInternalFrame2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInternalFrame2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInternalFrame2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInternalFrame2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugInternalFrame2 * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *IsCloserToLeaf )( + + HRESULT ( STDMETHODCALLTYPE *IsCloserToLeaf )( ICorDebugInternalFrame2 * This, /* [in] */ ICorDebugFrame *pFrameToCompare, /* [out] */ BOOL *pIsCloser); - + END_INTERFACE } ICorDebugInternalFrame2Vtbl; @@ -10693,26 +10784,26 @@ EXTERN_C const IID IID_ICorDebugInternalFrame2; CONST_VTBL struct ICorDebugInternalFrame2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugInternalFrame2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInternalFrame2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInternalFrame2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInternalFrame2_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugInternalFrame2_IsCloserToLeaf(This,pFrameToCompare,pIsCloser) \ - ( (This)->lpVtbl -> IsCloserToLeaf(This,pFrameToCompare,pIsCloser) ) + ( (This)->lpVtbl -> IsCloserToLeaf(This,pFrameToCompare,pIsCloser) ) #endif /* COBJMACROS */ @@ -10729,9 +10820,9 @@ EXTERN_C const IID IID_ICorDebugInternalFrame2; #define __ICorDebugILFrame_INTERFACE_DEFINED__ /* interface ICorDebugILFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugMappingResult { MAPPING_PROLOG = 0x1, @@ -10746,136 +10837,136 @@ enum CorDebugMappingResult EXTERN_C const IID IID_ICorDebugILFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("03E26311-4F76-11d3-88C6-006097945418") ICorDebugILFrame : public ICorDebugFrame { public: - virtual HRESULT STDMETHODCALLTYPE GetIP( + virtual HRESULT STDMETHODCALLTYPE GetIP( /* [out] */ ULONG32 *pnOffset, /* [out] */ CorDebugMappingResult *pMappingResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetIP( + + virtual HRESULT STDMETHODCALLTYPE SetIP( /* [in] */ ULONG32 nOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariables( + + virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariables( /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalVariable( + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariable( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateArguments( + + virtual HRESULT STDMETHODCALLTYPE EnumerateArguments( /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgument( + + virtual HRESULT STDMETHODCALLTYPE GetArgument( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackDepth( + + virtual HRESULT STDMETHODCALLTYPE GetStackDepth( /* [out] */ ULONG32 *pDepth) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackValue( + + virtual HRESULT STDMETHODCALLTYPE GetStackValue( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanSetIP( + + virtual HRESULT STDMETHODCALLTYPE CanSetIP( /* [in] */ ULONG32 nOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrameVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame * This); - - HRESULT ( STDMETHODCALLTYPE *GetChain )( + + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugILFrame * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugILFrame * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugILFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugILFrame * This, /* [out] */ mdMethodDef *pToken); - - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugILFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugILFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugILFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugILFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - - HRESULT ( STDMETHODCALLTYPE *GetIP )( + + HRESULT ( STDMETHODCALLTYPE *GetIP )( ICorDebugILFrame * This, /* [out] */ ULONG32 *pnOffset, /* [out] */ CorDebugMappingResult *pMappingResult); - - HRESULT ( STDMETHODCALLTYPE *SetIP )( + + HRESULT ( STDMETHODCALLTYPE *SetIP )( ICorDebugILFrame * This, /* [in] */ ULONG32 nOffset); - - HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariables )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariables )( ICorDebugILFrame * This, /* [out] */ ICorDebugValueEnum **ppValueEnum); - - HRESULT ( STDMETHODCALLTYPE *GetLocalVariable )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariable )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *EnumerateArguments )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateArguments )( ICorDebugILFrame * This, /* [out] */ ICorDebugValueEnum **ppValueEnum); - - HRESULT ( STDMETHODCALLTYPE *GetArgument )( + + HRESULT ( STDMETHODCALLTYPE *GetArgument )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetStackDepth )( + + HRESULT ( STDMETHODCALLTYPE *GetStackDepth )( ICorDebugILFrame * This, /* [out] */ ULONG32 *pDepth); - - HRESULT ( STDMETHODCALLTYPE *GetStackValue )( + + HRESULT ( STDMETHODCALLTYPE *GetStackValue )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *CanSetIP )( + + HRESULT ( STDMETHODCALLTYPE *CanSetIP )( ICorDebugILFrame * This, /* [in] */ ULONG32 nOffset); - + END_INTERFACE } ICorDebugILFrameVtbl; @@ -10884,72 +10975,72 @@ EXTERN_C const IID IID_ICorDebugILFrame; CONST_VTBL struct ICorDebugILFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugILFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugILFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugILFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugILFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugILFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugILFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugILFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugILFrame_GetIP(This,pnOffset,pMappingResult) \ - ( (This)->lpVtbl -> GetIP(This,pnOffset,pMappingResult) ) + ( (This)->lpVtbl -> GetIP(This,pnOffset,pMappingResult) ) #define ICorDebugILFrame_SetIP(This,nOffset) \ - ( (This)->lpVtbl -> SetIP(This,nOffset) ) + ( (This)->lpVtbl -> SetIP(This,nOffset) ) #define ICorDebugILFrame_EnumerateLocalVariables(This,ppValueEnum) \ - ( (This)->lpVtbl -> EnumerateLocalVariables(This,ppValueEnum) ) + ( (This)->lpVtbl -> EnumerateLocalVariables(This,ppValueEnum) ) #define ICorDebugILFrame_GetLocalVariable(This,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetLocalVariable(This,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetLocalVariable(This,dwIndex,ppValue) ) #define ICorDebugILFrame_EnumerateArguments(This,ppValueEnum) \ - ( (This)->lpVtbl -> EnumerateArguments(This,ppValueEnum) ) + ( (This)->lpVtbl -> EnumerateArguments(This,ppValueEnum) ) #define ICorDebugILFrame_GetArgument(This,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetArgument(This,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetArgument(This,dwIndex,ppValue) ) #define ICorDebugILFrame_GetStackDepth(This,pDepth) \ - ( (This)->lpVtbl -> GetStackDepth(This,pDepth) ) + ( (This)->lpVtbl -> GetStackDepth(This,pDepth) ) #define ICorDebugILFrame_GetStackValue(This,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetStackValue(This,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetStackValue(This,dwIndex,ppValue) ) #define ICorDebugILFrame_CanSetIP(This,nOffset) \ - ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) + ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) #endif /* COBJMACROS */ @@ -10966,52 +11057,52 @@ EXTERN_C const IID IID_ICorDebugILFrame; #define __ICorDebugILFrame2_INTERFACE_DEFINED__ /* interface ICorDebugILFrame2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5D88A994-6C30-479b-890F-BCEF88B129A5") ICorDebugILFrame2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE RemapFunction( + virtual HRESULT STDMETHODCALLTYPE RemapFunction( /* [in] */ ULONG32 newILOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( + + virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrame2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame2 * This); - - HRESULT ( STDMETHODCALLTYPE *RemapFunction )( + + HRESULT ( STDMETHODCALLTYPE *RemapFunction )( ICorDebugILFrame2 * This, /* [in] */ ULONG32 newILOffset); - - HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( ICorDebugILFrame2 * This, /* [out] */ ICorDebugTypeEnum **ppTyParEnum); - + END_INTERFACE } ICorDebugILFrame2Vtbl; @@ -11020,26 +11111,26 @@ EXTERN_C const IID IID_ICorDebugILFrame2; CONST_VTBL struct ICorDebugILFrame2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame2_RemapFunction(This,newILOffset) \ - ( (This)->lpVtbl -> RemapFunction(This,newILOffset) ) + ( (This)->lpVtbl -> RemapFunction(This,newILOffset) ) #define ICorDebugILFrame2_EnumerateTypeParameters(This,ppTyParEnum) \ - ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) + ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) #endif /* COBJMACROS */ @@ -11056,47 +11147,47 @@ EXTERN_C const IID IID_ICorDebugILFrame2; #define __ICorDebugILFrame3_INTERFACE_DEFINED__ /* interface ICorDebugILFrame3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("9A9E2ED6-04DF-4FE0-BB50-CAB64126AD24") ICorDebugILFrame3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetReturnValueForILOffset( + virtual HRESULT STDMETHODCALLTYPE GetReturnValueForILOffset( ULONG32 ILoffset, /* [out] */ ICorDebugValue **ppReturnValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrame3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetReturnValueForILOffset )( + + HRESULT ( STDMETHODCALLTYPE *GetReturnValueForILOffset )( ICorDebugILFrame3 * This, ULONG32 ILoffset, /* [out] */ ICorDebugValue **ppReturnValue); - + END_INTERFACE } ICorDebugILFrame3Vtbl; @@ -11105,23 +11196,23 @@ EXTERN_C const IID IID_ICorDebugILFrame3; CONST_VTBL struct ICorDebugILFrame3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame3_GetReturnValueForILOffset(This,ILoffset,ppReturnValue) \ - ( (This)->lpVtbl -> GetReturnValueForILOffset(This,ILoffset,ppReturnValue) ) + ( (This)->lpVtbl -> GetReturnValueForILOffset(This,ILoffset,ppReturnValue) ) #endif /* COBJMACROS */ @@ -11134,10 +11225,10 @@ EXTERN_C const IID IID_ICorDebugILFrame3; #endif /* __ICorDebugILFrame3_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0069 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0070 */ +/* [local] */ -typedef +typedef enum ILCodeKind { ILCODE_ORIGINAL_IL = 0x1, @@ -11146,74 +11237,74 @@ enum ILCodeKind -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0069_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0069_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_s_ifspec; #ifndef __ICorDebugILFrame4_INTERFACE_DEFINED__ #define __ICorDebugILFrame4_INTERFACE_DEFINED__ /* interface ICorDebugILFrame4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AD914A30-C6D1-4AC5-9C5E-577F3BAA8A45") ICorDebugILFrame4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariablesEx( + virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariablesEx( /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalVariableEx( + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariableEx( /* [in] */ ILCodeKind flags, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCodeEx( + + virtual HRESULT STDMETHODCALLTYPE GetCodeEx( /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugCode **ppCode) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILFrame4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame4 * This); - - HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariablesEx )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariablesEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugValueEnum **ppValueEnum); - - HRESULT ( STDMETHODCALLTYPE *GetLocalVariableEx )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariableEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetCodeEx )( + + HRESULT ( STDMETHODCALLTYPE *GetCodeEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugCode **ppCode); - + END_INTERFACE } ICorDebugILFrame4Vtbl; @@ -11222,29 +11313,29 @@ EXTERN_C const IID IID_ICorDebugILFrame4; CONST_VTBL struct ICorDebugILFrame4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILFrame4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame4_EnumerateLocalVariablesEx(This,flags,ppValueEnum) \ - ( (This)->lpVtbl -> EnumerateLocalVariablesEx(This,flags,ppValueEnum) ) + ( (This)->lpVtbl -> EnumerateLocalVariablesEx(This,flags,ppValueEnum) ) #define ICorDebugILFrame4_GetLocalVariableEx(This,flags,dwIndex,ppValue) \ - ( (This)->lpVtbl -> GetLocalVariableEx(This,flags,dwIndex,ppValue) ) + ( (This)->lpVtbl -> GetLocalVariableEx(This,flags,dwIndex,ppValue) ) #define ICorDebugILFrame4_GetCodeEx(This,flags,ppCode) \ - ( (This)->lpVtbl -> GetCodeEx(This,flags,ppCode) ) + ( (This)->lpVtbl -> GetCodeEx(This,flags,ppCode) ) #endif /* COBJMACROS */ @@ -11261,170 +11352,170 @@ EXTERN_C const IID IID_ICorDebugILFrame4; #define __ICorDebugNativeFrame_INTERFACE_DEFINED__ /* interface ICorDebugNativeFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugNativeFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("03E26314-4F76-11d3-88C6-006097945418") ICorDebugNativeFrame : public ICorDebugFrame { public: - virtual HRESULT STDMETHODCALLTYPE GetIP( + virtual HRESULT STDMETHODCALLTYPE GetIP( /* [out] */ ULONG32 *pnOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetIP( + + virtual HRESULT STDMETHODCALLTYPE SetIP( /* [in] */ ULONG32 nOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterValue( /* [in] */ CorDebugRegister reg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalDoubleRegisterValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalDoubleRegisterValue( /* [in] */ CorDebugRegister highWordReg, /* [in] */ CorDebugRegister lowWordReg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryValue( /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterMemoryValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterMemoryValue( /* [in] */ CorDebugRegister highWordReg, /* [in] */ CORDB_ADDRESS lowWordAddress, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryRegisterValue( + + virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryRegisterValue( /* [in] */ CORDB_ADDRESS highWordAddress, /* [in] */ CorDebugRegister lowWordRegister, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE CanSetIP( + + virtual HRESULT STDMETHODCALLTYPE CanSetIP( /* [in] */ ULONG32 nOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugNativeFrameVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugNativeFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugNativeFrame * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugNativeFrame * This); - - HRESULT ( STDMETHODCALLTYPE *GetChain )( + + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugNativeFrame * This, /* [out] */ mdMethodDef *pToken); - - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugNativeFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - - HRESULT ( STDMETHODCALLTYPE *GetIP )( + + HRESULT ( STDMETHODCALLTYPE *GetIP )( ICorDebugNativeFrame * This, /* [out] */ ULONG32 *pnOffset); - - HRESULT ( STDMETHODCALLTYPE *SetIP )( + + HRESULT ( STDMETHODCALLTYPE *SetIP )( ICorDebugNativeFrame * This, /* [in] */ ULONG32 nOffset); - - HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); - - HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterValue )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister reg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetLocalDoubleRegisterValue )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalDoubleRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister highWordReg, /* [in] */ CorDebugRegister lowWordReg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryValue )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryValue )( ICorDebugNativeFrame * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterMemoryValue )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterMemoryValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister highWordReg, /* [in] */ CORDB_ADDRESS lowWordAddress, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryRegisterValue )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CORDB_ADDRESS highWordAddress, /* [in] */ CorDebugRegister lowWordRegister, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *CanSetIP )( + + HRESULT ( STDMETHODCALLTYPE *CanSetIP )( ICorDebugNativeFrame * This, /* [in] */ ULONG32 nOffset); - + END_INTERFACE } ICorDebugNativeFrameVtbl; @@ -11433,72 +11524,72 @@ EXTERN_C const IID IID_ICorDebugNativeFrame; CONST_VTBL struct ICorDebugNativeFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugNativeFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugNativeFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugNativeFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugNativeFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugNativeFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugNativeFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugNativeFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugNativeFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugNativeFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugNativeFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugNativeFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugNativeFrame_GetIP(This,pnOffset) \ - ( (This)->lpVtbl -> GetIP(This,pnOffset) ) + ( (This)->lpVtbl -> GetIP(This,pnOffset) ) #define ICorDebugNativeFrame_SetIP(This,nOffset) \ - ( (This)->lpVtbl -> SetIP(This,nOffset) ) + ( (This)->lpVtbl -> SetIP(This,nOffset) ) #define ICorDebugNativeFrame_GetRegisterSet(This,ppRegisters) \ - ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugNativeFrame_GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) \ - ( (This)->lpVtbl -> GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) ) + ( (This)->lpVtbl -> GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_CanSetIP(This,nOffset) \ - ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) + ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) #endif /* COBJMACROS */ @@ -11511,75 +11602,75 @@ EXTERN_C const IID IID_ICorDebugNativeFrame; #endif /* __ICorDebugNativeFrame_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0071 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0072 */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0071_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0071_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0072_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0072_v0_0_s_ifspec; #ifndef __ICorDebugNativeFrame2_INTERFACE_DEFINED__ #define __ICorDebugNativeFrame2_INTERFACE_DEFINED__ /* interface ICorDebugNativeFrame2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugNativeFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("35389FF1-3684-4c55-A2EE-210F26C60E5E") ICorDebugNativeFrame2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsChild( + virtual HRESULT STDMETHODCALLTYPE IsChild( /* [out] */ BOOL *pIsChild) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsMatchingParentFrame( + + virtual HRESULT STDMETHODCALLTYPE IsMatchingParentFrame( /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, /* [out] */ BOOL *pIsParent) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStackParameterSize( + + virtual HRESULT STDMETHODCALLTYPE GetStackParameterSize( /* [out] */ ULONG32 *pSize) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugNativeFrame2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugNativeFrame2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugNativeFrame2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugNativeFrame2 * This); - - HRESULT ( STDMETHODCALLTYPE *IsChild )( + + HRESULT ( STDMETHODCALLTYPE *IsChild )( ICorDebugNativeFrame2 * This, /* [out] */ BOOL *pIsChild); - - HRESULT ( STDMETHODCALLTYPE *IsMatchingParentFrame )( + + HRESULT ( STDMETHODCALLTYPE *IsMatchingParentFrame )( ICorDebugNativeFrame2 * This, /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, /* [out] */ BOOL *pIsParent); - - HRESULT ( STDMETHODCALLTYPE *GetStackParameterSize )( + + HRESULT ( STDMETHODCALLTYPE *GetStackParameterSize )( ICorDebugNativeFrame2 * This, /* [out] */ ULONG32 *pSize); - + END_INTERFACE } ICorDebugNativeFrame2Vtbl; @@ -11588,29 +11679,29 @@ EXTERN_C const IID IID_ICorDebugNativeFrame2; CONST_VTBL struct ICorDebugNativeFrame2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugNativeFrame2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugNativeFrame2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugNativeFrame2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugNativeFrame2_IsChild(This,pIsChild) \ - ( (This)->lpVtbl -> IsChild(This,pIsChild) ) + ( (This)->lpVtbl -> IsChild(This,pIsChild) ) #define ICorDebugNativeFrame2_IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) \ - ( (This)->lpVtbl -> IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) ) + ( (This)->lpVtbl -> IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) ) #define ICorDebugNativeFrame2_GetStackParameterSize(This,pSize) \ - ( (This)->lpVtbl -> GetStackParameterSize(This,pSize) ) + ( (This)->lpVtbl -> GetStackParameterSize(This,pSize) ) #endif /* COBJMACROS */ @@ -11627,47 +11718,47 @@ EXTERN_C const IID IID_ICorDebugNativeFrame2; #define __ICorDebugModule3_INTERFACE_DEFINED__ /* interface ICorDebugModule3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("86F012BF-FF15-4372-BD30-B6F11CAAE1DD") ICorDebugModule3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateReaderForInMemorySymbols( + virtual HRESULT STDMETHODCALLTYPE CreateReaderForInMemorySymbols( /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppObj) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModule3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule3 * This); - - HRESULT ( STDMETHODCALLTYPE *CreateReaderForInMemorySymbols )( + + HRESULT ( STDMETHODCALLTYPE *CreateReaderForInMemorySymbols )( ICorDebugModule3 * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppObj); - + END_INTERFACE } ICorDebugModule3Vtbl; @@ -11676,23 +11767,23 @@ EXTERN_C const IID IID_ICorDebugModule3; CONST_VTBL struct ICorDebugModule3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule3_CreateReaderForInMemorySymbols(This,riid,ppObj) \ - ( (This)->lpVtbl -> CreateReaderForInMemorySymbols(This,riid,ppObj) ) + ( (This)->lpVtbl -> CreateReaderForInMemorySymbols(This,riid,ppObj) ) #endif /* COBJMACROS */ @@ -11709,45 +11800,45 @@ EXTERN_C const IID IID_ICorDebugModule3; #define __ICorDebugModule4_INTERFACE_DEFINED__ /* interface ICorDebugModule4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FF8B8EAF-25CD-4316-8859-84416DE4402E") ICorDebugModule4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsMappedLayout( + virtual HRESULT STDMETHODCALLTYPE IsMappedLayout( /* [out] */ BOOL *pIsMapped) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModule4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule4 * This); - - HRESULT ( STDMETHODCALLTYPE *IsMappedLayout )( + + HRESULT ( STDMETHODCALLTYPE *IsMappedLayout )( ICorDebugModule4 * This, /* [out] */ BOOL *pIsMapped); - + END_INTERFACE } ICorDebugModule4Vtbl; @@ -11756,23 +11847,23 @@ EXTERN_C const IID IID_ICorDebugModule4; CONST_VTBL struct ICorDebugModule4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule4_IsMappedLayout(This,pIsMapped) \ - ( (This)->lpVtbl -> IsMappedLayout(This,pIsMapped) ) + ( (This)->lpVtbl -> IsMappedLayout(This,pIsMapped) ) #endif /* COBJMACROS */ @@ -11789,71 +11880,71 @@ EXTERN_C const IID IID_ICorDebugModule4; #define __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ /* interface ICorDebugRuntimeUnwindableFrame */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("879CAC0A-4A53-4668-B8E3-CB8473CB187F") ICorDebugRuntimeUnwindableFrame : public ICorDebugFrame { public: }; - - + + #else /* C style interface */ typedef struct ICorDebugRuntimeUnwindableFrameVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRuntimeUnwindableFrame * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRuntimeUnwindableFrame * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRuntimeUnwindableFrame * This); - - HRESULT ( STDMETHODCALLTYPE *GetChain )( + + HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugChain **ppChain); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ mdMethodDef *pToken); - - HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); - - HRESULT ( STDMETHODCALLTYPE *GetCaller )( + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *GetCallee )( + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFrame **ppFrame); - - HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugStepper **ppStepper); - + END_INTERFACE } ICorDebugRuntimeUnwindableFrameVtbl; @@ -11862,44 +11953,44 @@ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; CONST_VTBL struct ICorDebugRuntimeUnwindableFrameVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugRuntimeUnwindableFrame_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRuntimeUnwindableFrame_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRuntimeUnwindableFrame_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRuntimeUnwindableFrame_GetChain(This,ppChain) \ - ( (This)->lpVtbl -> GetChain(This,ppChain) ) + ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugRuntimeUnwindableFrame_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugRuntimeUnwindableFrame_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugRuntimeUnwindableFrame_GetFunctionToken(This,pToken) \ - ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugRuntimeUnwindableFrame_GetStackRange(This,pStart,pEnd) \ - ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugRuntimeUnwindableFrame_GetCaller(This,ppFrame) \ - ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugRuntimeUnwindableFrame_GetCallee(This,ppFrame) \ - ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugRuntimeUnwindableFrame_CreateStepper(This,ppStepper) \ - ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #endif /* COBJMACROS */ @@ -11917,173 +12008,173 @@ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; #define __ICorDebugModule_INTERFACE_DEFINED__ /* interface ICorDebugModule */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("dba2d8c1-e5c5-4069-8c13-10a7c6abf43d") ICorDebugModule : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetProcess( + virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( + + virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAssembly( + + virtual HRESULT STDMETHODCALLTYPE GetAssembly( /* [out] */ ICorDebugAssembly **ppAssembly) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetName( + + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableJITDebugging( + + virtual HRESULT STDMETHODCALLTYPE EnableJITDebugging( /* [in] */ BOOL bTrackJITInfo, /* [in] */ BOOL bAllowJitOpts) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnableClassLoadCallbacks( + + virtual HRESULT STDMETHODCALLTYPE EnableClassLoadCallbacks( /* [in] */ BOOL bClassLoadCallbacks) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( /* [in] */ mdMethodDef methodDef, /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunctionFromRVA( + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromRVA( /* [in] */ CORDB_ADDRESS rva, /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( + + virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( /* [in] */ mdTypeDef typeDef, /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEditAndContinueSnapshot( + + virtual HRESULT STDMETHODCALLTYPE GetEditAndContinueSnapshot( /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMetaDataInterface( + + virtual HRESULT STDMETHODCALLTYPE GetMetaDataInterface( /* [in] */ REFIID riid, /* [out] */ IUnknown **ppObj) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdModule *pToken) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsDynamic( + + virtual HRESULT STDMETHODCALLTYPE IsDynamic( /* [out] */ BOOL *pDynamic) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetGlobalVariableValue( + + virtual HRESULT STDMETHODCALLTYPE GetGlobalVariableValue( /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsInMemory( + + virtual HRESULT STDMETHODCALLTYPE IsInMemory( /* [out] */ BOOL *pInMemory) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule * This); - - HRESULT ( STDMETHODCALLTYPE *GetProcess )( + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugModule * This, /* [out] */ ICorDebugProcess **ppProcess); - - HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( ICorDebugModule * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *GetAssembly )( + + HRESULT ( STDMETHODCALLTYPE *GetAssembly )( ICorDebugModule * This, /* [out] */ ICorDebugAssembly **ppAssembly); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugModule * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *EnableJITDebugging )( + + HRESULT ( STDMETHODCALLTYPE *EnableJITDebugging )( ICorDebugModule * This, /* [in] */ BOOL bTrackJITInfo, /* [in] */ BOOL bAllowJitOpts); - - HRESULT ( STDMETHODCALLTYPE *EnableClassLoadCallbacks )( + + HRESULT ( STDMETHODCALLTYPE *EnableClassLoadCallbacks )( ICorDebugModule * This, /* [in] */ BOOL bClassLoadCallbacks); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorDebugModule * This, /* [in] */ mdMethodDef methodDef, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetFunctionFromRVA )( + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromRVA )( ICorDebugModule * This, /* [in] */ CORDB_ADDRESS rva, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorDebugModule * This, /* [in] */ mdTypeDef typeDef, /* [out] */ ICorDebugClass **ppClass); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugModule * This, /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetEditAndContinueSnapshot )( + + HRESULT ( STDMETHODCALLTYPE *GetEditAndContinueSnapshot )( ICorDebugModule * This, /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot); - - HRESULT ( STDMETHODCALLTYPE *GetMetaDataInterface )( + + HRESULT ( STDMETHODCALLTYPE *GetMetaDataInterface )( ICorDebugModule * This, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppObj); - - HRESULT ( STDMETHODCALLTYPE *GetToken )( + + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugModule * This, /* [out] */ mdModule *pToken); - - HRESULT ( STDMETHODCALLTYPE *IsDynamic )( + + HRESULT ( STDMETHODCALLTYPE *IsDynamic )( ICorDebugModule * This, /* [out] */ BOOL *pDynamic); - - HRESULT ( STDMETHODCALLTYPE *GetGlobalVariableValue )( + + HRESULT ( STDMETHODCALLTYPE *GetGlobalVariableValue )( ICorDebugModule * This, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugModule * This, /* [out] */ ULONG32 *pcBytes); - - HRESULT ( STDMETHODCALLTYPE *IsInMemory )( + + HRESULT ( STDMETHODCALLTYPE *IsInMemory )( ICorDebugModule * This, /* [out] */ BOOL *pInMemory); - + END_INTERFACE } ICorDebugModuleVtbl; @@ -12092,71 +12183,71 @@ EXTERN_C const IID IID_ICorDebugModule; CONST_VTBL struct ICorDebugModuleVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule_GetProcess(This,ppProcess) \ - ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugModule_GetBaseAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) #define ICorDebugModule_GetAssembly(This,ppAssembly) \ - ( (This)->lpVtbl -> GetAssembly(This,ppAssembly) ) + ( (This)->lpVtbl -> GetAssembly(This,ppAssembly) ) #define ICorDebugModule_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugModule_EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) \ - ( (This)->lpVtbl -> EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) ) + ( (This)->lpVtbl -> EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) ) #define ICorDebugModule_EnableClassLoadCallbacks(This,bClassLoadCallbacks) \ - ( (This)->lpVtbl -> EnableClassLoadCallbacks(This,bClassLoadCallbacks) ) + ( (This)->lpVtbl -> EnableClassLoadCallbacks(This,bClassLoadCallbacks) ) #define ICorDebugModule_GetFunctionFromToken(This,methodDef,ppFunction) \ - ( (This)->lpVtbl -> GetFunctionFromToken(This,methodDef,ppFunction) ) + ( (This)->lpVtbl -> GetFunctionFromToken(This,methodDef,ppFunction) ) #define ICorDebugModule_GetFunctionFromRVA(This,rva,ppFunction) \ - ( (This)->lpVtbl -> GetFunctionFromRVA(This,rva,ppFunction) ) + ( (This)->lpVtbl -> GetFunctionFromRVA(This,rva,ppFunction) ) #define ICorDebugModule_GetClassFromToken(This,typeDef,ppClass) \ - ( (This)->lpVtbl -> GetClassFromToken(This,typeDef,ppClass) ) + ( (This)->lpVtbl -> GetClassFromToken(This,typeDef,ppClass) ) #define ICorDebugModule_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugModule_GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) \ - ( (This)->lpVtbl -> GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) ) + ( (This)->lpVtbl -> GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) ) #define ICorDebugModule_GetMetaDataInterface(This,riid,ppObj) \ - ( (This)->lpVtbl -> GetMetaDataInterface(This,riid,ppObj) ) + ( (This)->lpVtbl -> GetMetaDataInterface(This,riid,ppObj) ) #define ICorDebugModule_GetToken(This,pToken) \ - ( (This)->lpVtbl -> GetToken(This,pToken) ) + ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ICorDebugModule_IsDynamic(This,pDynamic) \ - ( (This)->lpVtbl -> IsDynamic(This,pDynamic) ) + ( (This)->lpVtbl -> IsDynamic(This,pDynamic) ) #define ICorDebugModule_GetGlobalVariableValue(This,fieldDef,ppValue) \ - ( (This)->lpVtbl -> GetGlobalVariableValue(This,fieldDef,ppValue) ) + ( (This)->lpVtbl -> GetGlobalVariableValue(This,fieldDef,ppValue) ) #define ICorDebugModule_GetSize(This,pcBytes) \ - ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #define ICorDebugModule_IsInMemory(This,pInMemory) \ - ( (This)->lpVtbl -> IsInMemory(This,pInMemory) ) + ( (This)->lpVtbl -> IsInMemory(This,pInMemory) ) #endif /* COBJMACROS */ @@ -12169,98 +12260,98 @@ EXTERN_C const IID IID_ICorDebugModule; #endif /* __ICorDebugModule_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0076 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0077 */ +/* [local] */ #pragma warning(pop) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0076_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0076_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0077_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0077_v0_0_s_ifspec; #ifndef __ICorDebugModule2_INTERFACE_DEFINED__ #define __ICorDebugModule2_INTERFACE_DEFINED__ /* interface ICorDebugModule2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7") ICorDebugModule2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode, /* [in] */ ULONG32 cTokens, /* [size_is][in] */ mdToken pTokens[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE ApplyChanges( + + virtual HRESULT STDMETHODCALLTYPE ApplyChanges( /* [in] */ ULONG cbMetadata, /* [size_is][in] */ BYTE pbMetadata[ ], /* [in] */ ULONG cbIL, /* [size_is][in] */ BYTE pbIL[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( /* [in] */ DWORD dwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetJITCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE GetJITCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE ResolveAssembly( + + virtual HRESULT STDMETHODCALLTYPE ResolveAssembly( /* [in] */ mdToken tkAssemblyRef, /* [out] */ ICorDebugAssembly **ppAssembly) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModule2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule2 * This); - - HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugModule2 * This, /* [in] */ BOOL bIsJustMyCode, /* [in] */ ULONG32 cTokens, /* [size_is][in] */ mdToken pTokens[ ]); - - HRESULT ( STDMETHODCALLTYPE *ApplyChanges )( + + HRESULT ( STDMETHODCALLTYPE *ApplyChanges )( ICorDebugModule2 * This, /* [in] */ ULONG cbMetadata, /* [size_is][in] */ BYTE pbMetadata[ ], /* [in] */ ULONG cbIL, /* [size_is][in] */ BYTE pbIL[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( + + HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( ICorDebugModule2 * This, /* [in] */ DWORD dwFlags); - - HRESULT ( STDMETHODCALLTYPE *GetJITCompilerFlags )( + + HRESULT ( STDMETHODCALLTYPE *GetJITCompilerFlags )( ICorDebugModule2 * This, /* [out] */ DWORD *pdwFlags); - - HRESULT ( STDMETHODCALLTYPE *ResolveAssembly )( + + HRESULT ( STDMETHODCALLTYPE *ResolveAssembly )( ICorDebugModule2 * This, /* [in] */ mdToken tkAssemblyRef, /* [out] */ ICorDebugAssembly **ppAssembly); - + END_INTERFACE } ICorDebugModule2Vtbl; @@ -12269,35 +12360,35 @@ EXTERN_C const IID IID_ICorDebugModule2; CONST_VTBL struct ICorDebugModule2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModule2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule2_SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) \ - ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) ) + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) ) #define ICorDebugModule2_ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) \ - ( (This)->lpVtbl -> ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) ) + ( (This)->lpVtbl -> ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) ) #define ICorDebugModule2_SetJITCompilerFlags(This,dwFlags) \ - ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) + ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) #define ICorDebugModule2_GetJITCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetJITCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetJITCompilerFlags(This,pdwFlags) ) #define ICorDebugModule2_ResolveAssembly(This,tkAssemblyRef,ppAssembly) \ - ( (This)->lpVtbl -> ResolveAssembly(This,tkAssemblyRef,ppAssembly) ) + ( (This)->lpVtbl -> ResolveAssembly(This,tkAssemblyRef,ppAssembly) ) #endif /* COBJMACROS */ @@ -12314,94 +12405,94 @@ EXTERN_C const IID IID_ICorDebugModule2; #define __ICorDebugFunction_INTERFACE_DEFINED__ /* interface ICorDebugFunction */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF3-8A68-11d2-983C-0000F808342D") ICorDebugFunction : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClass( + + virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdMethodDef *pMethodDef) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetILCode( + + virtual HRESULT STDMETHODCALLTYPE GetILCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetNativeCode( + + virtual HRESULT STDMETHODCALLTYPE GetNativeCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( + + virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( /* [out] */ mdSignature *pmdSig) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCurrentVersionNumber( + + virtual HRESULT STDMETHODCALLTYPE GetCurrentVersionNumber( /* [out] */ ULONG32 *pnCurrentVersion) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunctionVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction * This); - - HRESULT ( STDMETHODCALLTYPE *GetModule )( + + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugFunction * This, /* [out] */ ICorDebugModule **ppModule); - - HRESULT ( STDMETHODCALLTYPE *GetClass )( + + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugFunction * This, /* [out] */ ICorDebugClass **ppClass); - - HRESULT ( STDMETHODCALLTYPE *GetToken )( + + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugFunction * This, /* [out] */ mdMethodDef *pMethodDef); - - HRESULT ( STDMETHODCALLTYPE *GetILCode )( + + HRESULT ( STDMETHODCALLTYPE *GetILCode )( ICorDebugFunction * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetNativeCode )( + + HRESULT ( STDMETHODCALLTYPE *GetNativeCode )( ICorDebugFunction * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugFunction * This, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( ICorDebugFunction * This, /* [out] */ mdSignature *pmdSig); - - HRESULT ( STDMETHODCALLTYPE *GetCurrentVersionNumber )( + + HRESULT ( STDMETHODCALLTYPE *GetCurrentVersionNumber )( ICorDebugFunction * This, /* [out] */ ULONG32 *pnCurrentVersion); - + END_INTERFACE } ICorDebugFunctionVtbl; @@ -12410,44 +12501,44 @@ EXTERN_C const IID IID_ICorDebugFunction; CONST_VTBL struct ICorDebugFunctionVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #define ICorDebugFunction_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugFunction_GetToken(This,pMethodDef) \ - ( (This)->lpVtbl -> GetToken(This,pMethodDef) ) + ( (This)->lpVtbl -> GetToken(This,pMethodDef) ) #define ICorDebugFunction_GetILCode(This,ppCode) \ - ( (This)->lpVtbl -> GetILCode(This,ppCode) ) + ( (This)->lpVtbl -> GetILCode(This,ppCode) ) #define ICorDebugFunction_GetNativeCode(This,ppCode) \ - ( (This)->lpVtbl -> GetNativeCode(This,ppCode) ) + ( (This)->lpVtbl -> GetNativeCode(This,ppCode) ) #define ICorDebugFunction_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugFunction_GetLocalVarSigToken(This,pmdSig) \ - ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) + ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) #define ICorDebugFunction_GetCurrentVersionNumber(This,pnCurrentVersion) \ - ( (This)->lpVtbl -> GetCurrentVersionNumber(This,pnCurrentVersion) ) + ( (This)->lpVtbl -> GetCurrentVersionNumber(This,pnCurrentVersion) ) #endif /* COBJMACROS */ @@ -12464,66 +12555,66 @@ EXTERN_C const IID IID_ICorDebugFunction; #define __ICorDebugFunction2_INTERFACE_DEFINED__ /* interface ICorDebugFunction2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("EF0C490B-94C3-4e4d-B629-DDC134C532D8") ICorDebugFunction2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetJMCStatus( + + virtual HRESULT STDMETHODCALLTYPE GetJMCStatus( /* [out] */ BOOL *pbIsJustMyCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateNativeCode( + + virtual HRESULT STDMETHODCALLTYPE EnumerateNativeCode( /* [out] */ ICorDebugCodeEnum **ppCodeEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( + + virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( /* [out] */ ULONG32 *pnVersion) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction2 * This); - - HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugFunction2 * This, /* [in] */ BOOL bIsJustMyCode); - - HRESULT ( STDMETHODCALLTYPE *GetJMCStatus )( + + HRESULT ( STDMETHODCALLTYPE *GetJMCStatus )( ICorDebugFunction2 * This, /* [out] */ BOOL *pbIsJustMyCode); - - HRESULT ( STDMETHODCALLTYPE *EnumerateNativeCode )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateNativeCode )( ICorDebugFunction2 * This, /* [out] */ ICorDebugCodeEnum **ppCodeEnum); - - HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( + + HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( ICorDebugFunction2 * This, /* [out] */ ULONG32 *pnVersion); - + END_INTERFACE } ICorDebugFunction2Vtbl; @@ -12532,32 +12623,32 @@ EXTERN_C const IID IID_ICorDebugFunction2; CONST_VTBL struct ICorDebugFunction2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction2_SetJMCStatus(This,bIsJustMyCode) \ - ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) #define ICorDebugFunction2_GetJMCStatus(This,pbIsJustMyCode) \ - ( (This)->lpVtbl -> GetJMCStatus(This,pbIsJustMyCode) ) + ( (This)->lpVtbl -> GetJMCStatus(This,pbIsJustMyCode) ) #define ICorDebugFunction2_EnumerateNativeCode(This,ppCodeEnum) \ - ( (This)->lpVtbl -> EnumerateNativeCode(This,ppCodeEnum) ) + ( (This)->lpVtbl -> EnumerateNativeCode(This,ppCodeEnum) ) #define ICorDebugFunction2_GetVersionNumber(This,pnVersion) \ - ( (This)->lpVtbl -> GetVersionNumber(This,pnVersion) ) + ( (This)->lpVtbl -> GetVersionNumber(This,pnVersion) ) #endif /* COBJMACROS */ @@ -12574,45 +12665,45 @@ EXTERN_C const IID IID_ICorDebugFunction2; #define __ICorDebugFunction3_INTERFACE_DEFINED__ /* interface ICorDebugFunction3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("09B70F28-E465-482D-99E0-81A165EB0532") ICorDebugFunction3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetActiveReJitRequestILCode( + virtual HRESULT STDMETHODCALLTYPE GetActiveReJitRequestILCode( ICorDebugILCode **ppReJitedILCode) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetActiveReJitRequestILCode )( + + HRESULT ( STDMETHODCALLTYPE *GetActiveReJitRequestILCode )( ICorDebugFunction3 * This, ICorDebugILCode **ppReJitedILCode); - + END_INTERFACE } ICorDebugFunction3Vtbl; @@ -12621,23 +12712,23 @@ EXTERN_C const IID IID_ICorDebugFunction3; CONST_VTBL struct ICorDebugFunction3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction3_GetActiveReJitRequestILCode(This,ppReJitedILCode) \ - ( (This)->lpVtbl -> GetActiveReJitRequestILCode(This,ppReJitedILCode) ) + ( (This)->lpVtbl -> GetActiveReJitRequestILCode(This,ppReJitedILCode) ) #endif /* COBJMACROS */ @@ -12654,45 +12745,45 @@ EXTERN_C const IID IID_ICorDebugFunction3; #define __ICorDebugFunction4_INTERFACE_DEFINED__ /* interface ICorDebugFunction4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("72965963-34fd-46e9-9434-b817fe6e7f43") ICorDebugFunction4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateNativeBreakpoint( + virtual HRESULT STDMETHODCALLTYPE CreateNativeBreakpoint( ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFunction4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction4 * This); - - HRESULT ( STDMETHODCALLTYPE *CreateNativeBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateNativeBreakpoint )( ICorDebugFunction4 * This, ICorDebugFunctionBreakpoint **ppBreakpoint); - + END_INTERFACE } ICorDebugFunction4Vtbl; @@ -12701,23 +12792,23 @@ EXTERN_C const IID IID_ICorDebugFunction4; CONST_VTBL struct ICorDebugFunction4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFunction4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction4_CreateNativeBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateNativeBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateNativeBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ @@ -12734,119 +12825,119 @@ EXTERN_C const IID IID_ICorDebugFunction4; #define __ICorDebugCode_INTERFACE_DEFINED__ /* interface ICorDebugCode */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF4-8A68-11d2-983C-0000F808342D") ICorDebugCode : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE IsIL( + virtual HRESULT STDMETHODCALLTYPE IsIL( /* [out] */ BOOL *pbIL) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunction( + + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAddress( + + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pStart) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [in] */ ULONG32 offset, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCode( + + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset, /* [in] */ ULONG32 cBufferAlloc, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *pcBufferSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( + + virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( /* [out] */ ULONG32 *nVersion) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetEnCRemapSequencePoints( + + virtual HRESULT STDMETHODCALLTYPE GetEnCRemapSequencePoints( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ ULONG32 offsets[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCodeVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode * This); - - HRESULT ( STDMETHODCALLTYPE *IsIL )( + + HRESULT ( STDMETHODCALLTYPE *IsIL )( ICorDebugCode * This, /* [out] */ BOOL *pbIL); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugCode * This, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugCode * This, /* [out] */ CORDB_ADDRESS *pStart); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugCode * This, /* [out] */ ULONG32 *pcBytes); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugCode * This, /* [in] */ ULONG32 offset, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugCode * This, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset, /* [in] */ ULONG32 cBufferAlloc, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *pcBufferSize); - - HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( + + HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( ICorDebugCode * This, /* [out] */ ULONG32 *nVersion); - - HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorDebugCode * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetEnCRemapSequencePoints )( + + HRESULT ( STDMETHODCALLTYPE *GetEnCRemapSequencePoints )( ICorDebugCode * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ ULONG32 offsets[ ]); - + END_INTERFACE } ICorDebugCodeVtbl; @@ -12855,47 +12946,47 @@ EXTERN_C const IID IID_ICorDebugCode; CONST_VTBL struct ICorDebugCodeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode_IsIL(This,pbIL) \ - ( (This)->lpVtbl -> IsIL(This,pbIL) ) + ( (This)->lpVtbl -> IsIL(This,pbIL) ) #define ICorDebugCode_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugCode_GetAddress(This,pStart) \ - ( (This)->lpVtbl -> GetAddress(This,pStart) ) + ( (This)->lpVtbl -> GetAddress(This,pStart) ) #define ICorDebugCode_GetSize(This,pcBytes) \ - ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #define ICorDebugCode_CreateBreakpoint(This,offset,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,offset,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,offset,ppBreakpoint) ) #define ICorDebugCode_GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) \ - ( (This)->lpVtbl -> GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) ) + ( (This)->lpVtbl -> GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) ) #define ICorDebugCode_GetVersionNumber(This,nVersion) \ - ( (This)->lpVtbl -> GetVersionNumber(This,nVersion) ) + ( (This)->lpVtbl -> GetVersionNumber(This,nVersion) ) #define ICorDebugCode_GetILToNativeMapping(This,cMap,pcMap,map) \ - ( (This)->lpVtbl -> GetILToNativeMapping(This,cMap,pcMap,map) ) + ( (This)->lpVtbl -> GetILToNativeMapping(This,cMap,pcMap,map) ) #define ICorDebugCode_GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) \ - ( (This)->lpVtbl -> GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) ) + ( (This)->lpVtbl -> GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) ) #endif /* COBJMACROS */ @@ -12912,7 +13003,7 @@ EXTERN_C const IID IID_ICorDebugCode; #define __ICorDebugCode2_INTERFACE_DEFINED__ /* interface ICorDebugCode2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ typedef struct _CodeChunkInfo { @@ -12924,50 +13015,50 @@ typedef struct _CodeChunkInfo EXTERN_C const IID IID_ICorDebugCode2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5F696509-452F-4436-A3FE-4D11FE7E2347") ICorDebugCode2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCodeChunks( + virtual HRESULT STDMETHODCALLTYPE GetCodeChunks( /* [in] */ ULONG32 cbufSize, /* [out] */ ULONG32 *pcnumChunks, /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCompilerFlags( + + virtual HRESULT STDMETHODCALLTYPE GetCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCode2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetCodeChunks )( + + HRESULT ( STDMETHODCALLTYPE *GetCodeChunks )( ICorDebugCode2 * This, /* [in] */ ULONG32 cbufSize, /* [out] */ ULONG32 *pcnumChunks, /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetCompilerFlags )( + + HRESULT ( STDMETHODCALLTYPE *GetCompilerFlags )( ICorDebugCode2 * This, /* [out] */ DWORD *pdwFlags); - + END_INTERFACE } ICorDebugCode2Vtbl; @@ -12976,26 +13067,26 @@ EXTERN_C const IID IID_ICorDebugCode2; CONST_VTBL struct ICorDebugCode2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode2_GetCodeChunks(This,cbufSize,pcnumChunks,chunks) \ - ( (This)->lpVtbl -> GetCodeChunks(This,cbufSize,pcnumChunks,chunks) ) + ( (This)->lpVtbl -> GetCodeChunks(This,cbufSize,pcnumChunks,chunks) ) #define ICorDebugCode2_GetCompilerFlags(This,pdwFlags) \ - ( (This)->lpVtbl -> GetCompilerFlags(This,pdwFlags) ) + ( (This)->lpVtbl -> GetCompilerFlags(This,pdwFlags) ) #endif /* COBJMACROS */ @@ -13012,51 +13103,51 @@ EXTERN_C const IID IID_ICorDebugCode2; #define __ICorDebugCode3_INTERFACE_DEFINED__ /* interface ICorDebugCode3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D13D3E88-E1F2-4020-AA1D-3D162DCBE966") ICorDebugCode3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetReturnValueLiveOffset( + virtual HRESULT STDMETHODCALLTYPE GetReturnValueLiveOffset( /* [in] */ ULONG32 ILoffset, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *pFetched, /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCode3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetReturnValueLiveOffset )( + + HRESULT ( STDMETHODCALLTYPE *GetReturnValueLiveOffset )( ICorDebugCode3 * This, /* [in] */ ULONG32 ILoffset, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *pFetched, /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]); - + END_INTERFACE } ICorDebugCode3Vtbl; @@ -13065,23 +13156,23 @@ EXTERN_C const IID IID_ICorDebugCode3; CONST_VTBL struct ICorDebugCode3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode3_GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) \ - ( (This)->lpVtbl -> GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) ) + ( (This)->lpVtbl -> GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) ) #endif /* COBJMACROS */ @@ -13098,45 +13189,45 @@ EXTERN_C const IID IID_ICorDebugCode3; #define __ICorDebugCode4_INTERFACE_DEFINED__ /* interface ICorDebugCode4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("18221fa4-20cb-40fa-b19d-9f91c4fa8c14") ICorDebugCode4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( + virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( /* [out] */ ICorDebugVariableHomeEnum **ppEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCode4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode4 * This); - - HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( ICorDebugCode4 * This, /* [out] */ ICorDebugVariableHomeEnum **ppEnum); - + END_INTERFACE } ICorDebugCode4Vtbl; @@ -13145,23 +13236,23 @@ EXTERN_C const IID IID_ICorDebugCode4; CONST_VTBL struct ICorDebugCode4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCode4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode4_EnumerateVariableHomes(This,ppEnum) \ - ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) + ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) #endif /* COBJMACROS */ @@ -13178,7 +13269,7 @@ EXTERN_C const IID IID_ICorDebugCode4; #define __ICorDebugILCode_INTERFACE_DEFINED__ /* interface ICorDebugILCode */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ typedef struct _CorDebugEHClause { @@ -13195,43 +13286,43 @@ typedef struct _CorDebugEHClause EXTERN_C const IID IID_ICorDebugILCode; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("598D46C2-C877-42A7-89D2-3D0C7F1C1264") ICorDebugILCode : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetEHClauses( + virtual HRESULT STDMETHODCALLTYPE GetEHClauses( /* [in] */ ULONG32 cClauses, /* [out] */ ULONG32 *pcClauses, /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILCodeVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILCode * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILCode * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILCode * This); - - HRESULT ( STDMETHODCALLTYPE *GetEHClauses )( + + HRESULT ( STDMETHODCALLTYPE *GetEHClauses )( ICorDebugILCode * This, /* [in] */ ULONG32 cClauses, /* [out] */ ULONG32 *pcClauses, /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]); - + END_INTERFACE } ICorDebugILCodeVtbl; @@ -13240,23 +13331,23 @@ EXTERN_C const IID IID_ICorDebugILCode; CONST_VTBL struct ICorDebugILCodeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILCode_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILCode_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILCode_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILCode_GetEHClauses(This,cClauses,pcClauses,clauses) \ - ( (This)->lpVtbl -> GetEHClauses(This,cClauses,pcClauses,clauses) ) + ( (This)->lpVtbl -> GetEHClauses(This,cClauses,pcClauses,clauses) ) #endif /* COBJMACROS */ @@ -13273,56 +13364,56 @@ EXTERN_C const IID IID_ICorDebugILCode; #define __ICorDebugILCode2_INTERFACE_DEFINED__ /* interface ICorDebugILCode2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILCode2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("46586093-D3F5-4DB6-ACDB-955BCE228C15") ICorDebugILCode2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( + virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( /* [out] */ mdSignature *pmdSig) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetInstrumentedILMap( + + virtual HRESULT STDMETHODCALLTYPE GetInstrumentedILMap( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_IL_MAP map[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugILCode2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILCode2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILCode2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILCode2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( + + HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( ICorDebugILCode2 * This, /* [out] */ mdSignature *pmdSig); - - HRESULT ( STDMETHODCALLTYPE *GetInstrumentedILMap )( + + HRESULT ( STDMETHODCALLTYPE *GetInstrumentedILMap )( ICorDebugILCode2 * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_IL_MAP map[ ]); - + END_INTERFACE } ICorDebugILCode2Vtbl; @@ -13331,26 +13422,26 @@ EXTERN_C const IID IID_ICorDebugILCode2; CONST_VTBL struct ICorDebugILCode2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugILCode2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILCode2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILCode2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILCode2_GetLocalVarSigToken(This,pmdSig) \ - ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) + ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) #define ICorDebugILCode2_GetInstrumentedILMap(This,cMap,pcMap,map) \ - ( (This)->lpVtbl -> GetInstrumentedILMap(This,cMap,pcMap,map) ) + ( (This)->lpVtbl -> GetInstrumentedILMap(This,cMap,pcMap,map) ) #endif /* COBJMACROS */ @@ -13367,63 +13458,63 @@ EXTERN_C const IID IID_ICorDebugILCode2; #define __ICorDebugClass_INTERFACE_DEFINED__ /* interface ICorDebugClass */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugClass; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF5-8A68-11d2-983C-0000F808342D") ICorDebugClass : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **pModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdTypeDef *pTypeDef) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugClassVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugClass * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugClass * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugClass * This); - - HRESULT ( STDMETHODCALLTYPE *GetModule )( + + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugClass * This, /* [out] */ ICorDebugModule **pModule); - - HRESULT ( STDMETHODCALLTYPE *GetToken )( + + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugClass * This, /* [out] */ mdTypeDef *pTypeDef); - - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( ICorDebugClass * This, /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugClassVtbl; @@ -13432,29 +13523,29 @@ EXTERN_C const IID IID_ICorDebugClass; CONST_VTBL struct ICorDebugClassVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugClass_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugClass_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugClass_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugClass_GetModule(This,pModule) \ - ( (This)->lpVtbl -> GetModule(This,pModule) ) + ( (This)->lpVtbl -> GetModule(This,pModule) ) #define ICorDebugClass_GetToken(This,pTypeDef) \ - ( (This)->lpVtbl -> GetToken(This,pTypeDef) ) + ( (This)->lpVtbl -> GetToken(This,pTypeDef) ) #define ICorDebugClass_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ - ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) + ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) #endif /* COBJMACROS */ @@ -13471,58 +13562,58 @@ EXTERN_C const IID IID_ICorDebugClass; #define __ICorDebugClass2_INTERFACE_DEFINED__ /* interface ICorDebugClass2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugClass2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("B008EA8D-7AB1-43f7-BB20-FBB5A04038AE") ICorDebugClass2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetParameterizedType( + virtual HRESULT STDMETHODCALLTYPE GetParameterizedType( /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugClass2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugClass2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugClass2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugClass2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetParameterizedType )( + + HRESULT ( STDMETHODCALLTYPE *GetParameterizedType )( ICorDebugClass2 * This, /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType); - - HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugClass2 * This, /* [in] */ BOOL bIsJustMyCode); - + END_INTERFACE } ICorDebugClass2Vtbl; @@ -13531,26 +13622,26 @@ EXTERN_C const IID IID_ICorDebugClass2; CONST_VTBL struct ICorDebugClass2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugClass2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugClass2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugClass2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugClass2_GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) \ - ( (This)->lpVtbl -> GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) ) + ( (This)->lpVtbl -> GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) ) #define ICorDebugClass2_SetJMCStatus(This,bIsJustMyCode) \ - ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) #endif /* COBJMACROS */ @@ -13567,126 +13658,126 @@ EXTERN_C const IID IID_ICorDebugClass2; #define __ICorDebugEval_INTERFACE_DEFINED__ /* interface ICorDebugEval */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEval; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF6-8A68-11d2-983C-0000F808342D") ICorDebugEval : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CallFunction( + virtual HRESULT STDMETHODCALLTYPE CallFunction( /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewObject( + + virtual HRESULT STDMETHODCALLTYPE NewObject( /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewObjectNoConstructor( + + virtual HRESULT STDMETHODCALLTYPE NewObjectNoConstructor( /* [in] */ ICorDebugClass *pClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewString( + + virtual HRESULT STDMETHODCALLTYPE NewString( /* [in] */ LPCWSTR string) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewArray( + + virtual HRESULT STDMETHODCALLTYPE NewArray( /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsActive( + + virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; - + virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetResult( + + virtual HRESULT STDMETHODCALLTYPE GetResult( /* [out] */ ICorDebugValue **ppResult) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetThread( + + virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateValue( + + virtual HRESULT STDMETHODCALLTYPE CreateValue( /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEvalVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEval * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEval * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEval * This); - - HRESULT ( STDMETHODCALLTYPE *CallFunction )( + + HRESULT ( STDMETHODCALLTYPE *CallFunction )( ICorDebugEval * This, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *NewObject )( + + HRESULT ( STDMETHODCALLTYPE *NewObject )( ICorDebugEval * This, /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *NewObjectNoConstructor )( + + HRESULT ( STDMETHODCALLTYPE *NewObjectNoConstructor )( ICorDebugEval * This, /* [in] */ ICorDebugClass *pClass); - - HRESULT ( STDMETHODCALLTYPE *NewString )( + + HRESULT ( STDMETHODCALLTYPE *NewString )( ICorDebugEval * This, /* [in] */ LPCWSTR string); - - HRESULT ( STDMETHODCALLTYPE *NewArray )( + + HRESULT ( STDMETHODCALLTYPE *NewArray )( ICorDebugEval * This, /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]); - - HRESULT ( STDMETHODCALLTYPE *IsActive )( + + HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugEval * This, /* [out] */ BOOL *pbActive); - - HRESULT ( STDMETHODCALLTYPE *Abort )( + + HRESULT ( STDMETHODCALLTYPE *Abort )( ICorDebugEval * This); - - HRESULT ( STDMETHODCALLTYPE *GetResult )( + + HRESULT ( STDMETHODCALLTYPE *GetResult )( ICorDebugEval * This, /* [out] */ ICorDebugValue **ppResult); - - HRESULT ( STDMETHODCALLTYPE *GetThread )( + + HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugEval * This, /* [out] */ ICorDebugThread **ppThread); - - HRESULT ( STDMETHODCALLTYPE *CreateValue )( + + HRESULT ( STDMETHODCALLTYPE *CreateValue )( ICorDebugEval * This, /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugEvalVtbl; @@ -13695,50 +13786,50 @@ EXTERN_C const IID IID_ICorDebugEval; CONST_VTBL struct ICorDebugEvalVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEval_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEval_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEval_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEval_CallFunction(This,pFunction,nArgs,ppArgs) \ - ( (This)->lpVtbl -> CallFunction(This,pFunction,nArgs,ppArgs) ) + ( (This)->lpVtbl -> CallFunction(This,pFunction,nArgs,ppArgs) ) #define ICorDebugEval_NewObject(This,pConstructor,nArgs,ppArgs) \ - ( (This)->lpVtbl -> NewObject(This,pConstructor,nArgs,ppArgs) ) + ( (This)->lpVtbl -> NewObject(This,pConstructor,nArgs,ppArgs) ) #define ICorDebugEval_NewObjectNoConstructor(This,pClass) \ - ( (This)->lpVtbl -> NewObjectNoConstructor(This,pClass) ) + ( (This)->lpVtbl -> NewObjectNoConstructor(This,pClass) ) #define ICorDebugEval_NewString(This,string) \ - ( (This)->lpVtbl -> NewString(This,string) ) + ( (This)->lpVtbl -> NewString(This,string) ) #define ICorDebugEval_NewArray(This,elementType,pElementClass,rank,dims,lowBounds) \ - ( (This)->lpVtbl -> NewArray(This,elementType,pElementClass,rank,dims,lowBounds) ) + ( (This)->lpVtbl -> NewArray(This,elementType,pElementClass,rank,dims,lowBounds) ) #define ICorDebugEval_IsActive(This,pbActive) \ - ( (This)->lpVtbl -> IsActive(This,pbActive) ) + ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugEval_Abort(This) \ - ( (This)->lpVtbl -> Abort(This) ) + ( (This)->lpVtbl -> Abort(This) ) #define ICorDebugEval_GetResult(This,ppResult) \ - ( (This)->lpVtbl -> GetResult(This,ppResult) ) + ( (This)->lpVtbl -> GetResult(This,ppResult) ) #define ICorDebugEval_GetThread(This,ppThread) \ - ( (This)->lpVtbl -> GetThread(This,ppThread) ) + ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugEval_CreateValue(This,elementType,pElementClass,ppValue) \ - ( (This)->lpVtbl -> CreateValue(This,elementType,pElementClass,ppValue) ) + ( (This)->lpVtbl -> CreateValue(This,elementType,pElementClass,ppValue) ) #endif /* COBJMACROS */ @@ -13755,115 +13846,115 @@ EXTERN_C const IID IID_ICorDebugEval; #define __ICorDebugEval2_INTERFACE_DEFINED__ /* interface ICorDebugEval2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEval2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("FB0D9CE7-BE66-4683-9D32-A42A04E2FD91") ICorDebugEval2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CallParameterizedFunction( + virtual HRESULT STDMETHODCALLTYPE CallParameterizedFunction( /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateValueForType( + + virtual HRESULT STDMETHODCALLTYPE CreateValueForType( /* [in] */ ICorDebugType *pType, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewParameterizedObject( + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedObject( /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewParameterizedObjectNoConstructor( + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedObjectNoConstructor( /* [in] */ ICorDebugClass *pClass, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewParameterizedArray( + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedArray( /* [in] */ ICorDebugType *pElementType, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE NewStringWithLength( + + virtual HRESULT STDMETHODCALLTYPE NewStringWithLength( /* [in] */ LPCWSTR string, /* [in] */ UINT uiLength) = 0; - + virtual HRESULT STDMETHODCALLTYPE RudeAbort( void) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEval2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEval2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEval2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEval2 * This); - - HRESULT ( STDMETHODCALLTYPE *CallParameterizedFunction )( + + HRESULT ( STDMETHODCALLTYPE *CallParameterizedFunction )( ICorDebugEval2 * This, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *CreateValueForType )( + + HRESULT ( STDMETHODCALLTYPE *CreateValueForType )( ICorDebugEval2 * This, /* [in] */ ICorDebugType *pType, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *NewParameterizedObject )( + + HRESULT ( STDMETHODCALLTYPE *NewParameterizedObject )( ICorDebugEval2 * This, /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *NewParameterizedObjectNoConstructor )( + + HRESULT ( STDMETHODCALLTYPE *NewParameterizedObjectNoConstructor )( ICorDebugEval2 * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]); - - HRESULT ( STDMETHODCALLTYPE *NewParameterizedArray )( + + HRESULT ( STDMETHODCALLTYPE *NewParameterizedArray )( ICorDebugEval2 * This, /* [in] */ ICorDebugType *pElementType, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]); - - HRESULT ( STDMETHODCALLTYPE *NewStringWithLength )( + + HRESULT ( STDMETHODCALLTYPE *NewStringWithLength )( ICorDebugEval2 * This, /* [in] */ LPCWSTR string, /* [in] */ UINT uiLength); - - HRESULT ( STDMETHODCALLTYPE *RudeAbort )( + + HRESULT ( STDMETHODCALLTYPE *RudeAbort )( ICorDebugEval2 * This); - + END_INTERFACE } ICorDebugEval2Vtbl; @@ -13872,41 +13963,41 @@ EXTERN_C const IID IID_ICorDebugEval2; CONST_VTBL struct ICorDebugEval2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEval2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEval2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEval2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEval2_CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ - ( (This)->lpVtbl -> CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) + ( (This)->lpVtbl -> CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) #define ICorDebugEval2_CreateValueForType(This,pType,ppValue) \ - ( (This)->lpVtbl -> CreateValueForType(This,pType,ppValue) ) + ( (This)->lpVtbl -> CreateValueForType(This,pType,ppValue) ) #define ICorDebugEval2_NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ - ( (This)->lpVtbl -> NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) + ( (This)->lpVtbl -> NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) #define ICorDebugEval2_NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) \ - ( (This)->lpVtbl -> NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) ) + ( (This)->lpVtbl -> NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) ) #define ICorDebugEval2_NewParameterizedArray(This,pElementType,rank,dims,lowBounds) \ - ( (This)->lpVtbl -> NewParameterizedArray(This,pElementType,rank,dims,lowBounds) ) + ( (This)->lpVtbl -> NewParameterizedArray(This,pElementType,rank,dims,lowBounds) ) #define ICorDebugEval2_NewStringWithLength(This,string,uiLength) \ - ( (This)->lpVtbl -> NewStringWithLength(This,string,uiLength) ) + ( (This)->lpVtbl -> NewStringWithLength(This,string,uiLength) ) #define ICorDebugEval2_RudeAbort(This) \ - ( (This)->lpVtbl -> RudeAbort(This) ) + ( (This)->lpVtbl -> RudeAbort(This) ) #endif /* COBJMACROS */ @@ -13923,66 +14014,66 @@ EXTERN_C const IID IID_ICorDebugEval2; #define __ICorDebugValue_INTERFACE_DEFINED__ /* interface ICorDebugValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF7-8A68-11d2-983C-0000F808342D") ICorDebugValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetType( + virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ CorElementType *pType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSize( + + virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pSize) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetAddress( + + virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + END_INTERFACE } ICorDebugValueVtbl; @@ -13991,32 +14082,32 @@ EXTERN_C const IID IID_ICorDebugValue; CONST_VTBL struct ICorDebugValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ @@ -14033,45 +14124,45 @@ EXTERN_C const IID IID_ICorDebugValue; #define __ICorDebugValue2_INTERFACE_DEFINED__ /* interface ICorDebugValue2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5E0B54E7-D88A-4626-9420-A691E0A78B49") ICorDebugValue2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetExactType( + virtual HRESULT STDMETHODCALLTYPE GetExactType( /* [out] */ ICorDebugType **ppType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValue2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetExactType )( + + HRESULT ( STDMETHODCALLTYPE *GetExactType )( ICorDebugValue2 * This, /* [out] */ ICorDebugType **ppType); - + END_INTERFACE } ICorDebugValue2Vtbl; @@ -14080,23 +14171,23 @@ EXTERN_C const IID IID_ICorDebugValue2; CONST_VTBL struct ICorDebugValue2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValue2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue2_GetExactType(This,ppType) \ - ( (This)->lpVtbl -> GetExactType(This,ppType) ) + ( (This)->lpVtbl -> GetExactType(This,ppType) ) #endif /* COBJMACROS */ @@ -14113,45 +14204,45 @@ EXTERN_C const IID IID_ICorDebugValue2; #define __ICorDebugValue3_INTERFACE_DEFINED__ /* interface ICorDebugValue3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("565005FC-0F8A-4F3E-9EDB-83102B156595") ICorDebugValue3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetSize64( + virtual HRESULT STDMETHODCALLTYPE GetSize64( /* [out] */ ULONG64 *pSize) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValue3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetSize64 )( + + HRESULT ( STDMETHODCALLTYPE *GetSize64 )( ICorDebugValue3 * This, /* [out] */ ULONG64 *pSize); - + END_INTERFACE } ICorDebugValue3Vtbl; @@ -14160,23 +14251,23 @@ EXTERN_C const IID IID_ICorDebugValue3; CONST_VTBL struct ICorDebugValue3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValue3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue3_GetSize64(This,pSize) \ - ( (This)->lpVtbl -> GetSize64(This,pSize) ) + ( (This)->lpVtbl -> GetSize64(This,pSize) ) #endif /* COBJMACROS */ @@ -14193,68 +14284,68 @@ EXTERN_C const IID IID_ICorDebugValue3; #define __ICorDebugGenericValue_INTERFACE_DEFINED__ /* interface ICorDebugGenericValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGenericValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF8-8A68-11d2-983C-0000F808342D") ICorDebugGenericValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE GetValue( + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ void *pTo) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetValue( + + virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ void *pFrom) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugGenericValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGenericValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGenericValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGenericValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugGenericValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugGenericValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugGenericValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugGenericValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetValue )( + + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugGenericValue * This, /* [out] */ void *pTo); - - HRESULT ( STDMETHODCALLTYPE *SetValue )( + + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugGenericValue * This, /* [in] */ void *pFrom); - + END_INTERFACE } ICorDebugGenericValueVtbl; @@ -14263,39 +14354,39 @@ EXTERN_C const IID IID_ICorDebugGenericValue; CONST_VTBL struct ICorDebugGenericValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugGenericValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGenericValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGenericValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGenericValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugGenericValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugGenericValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugGenericValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugGenericValue_GetValue(This,pTo) \ - ( (This)->lpVtbl -> GetValue(This,pTo) ) + ( (This)->lpVtbl -> GetValue(This,pTo) ) #define ICorDebugGenericValue_SetValue(This,pFrom) \ - ( (This)->lpVtbl -> SetValue(This,pFrom) ) + ( (This)->lpVtbl -> SetValue(This,pFrom) ) #endif /* COBJMACROS */ @@ -14312,89 +14403,89 @@ EXTERN_C const IID IID_ICorDebugGenericValue; #define __ICorDebugReferenceValue_INTERFACE_DEFINED__ /* interface ICorDebugReferenceValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugReferenceValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAF9-8A68-11d2-983C-0000F808342D") ICorDebugReferenceValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE IsNull( + virtual HRESULT STDMETHODCALLTYPE IsNull( /* [out] */ BOOL *pbNull) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetValue( + + virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ CORDB_ADDRESS *pValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetValue( + + virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ CORDB_ADDRESS value) = 0; - - virtual HRESULT STDMETHODCALLTYPE Dereference( + + virtual HRESULT STDMETHODCALLTYPE Dereference( /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE DereferenceStrong( + + virtual HRESULT STDMETHODCALLTYPE DereferenceStrong( /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugReferenceValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugReferenceValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugReferenceValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugReferenceValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugReferenceValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugReferenceValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugReferenceValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *IsNull )( + + HRESULT ( STDMETHODCALLTYPE *IsNull )( ICorDebugReferenceValue * This, /* [out] */ BOOL *pbNull); - - HRESULT ( STDMETHODCALLTYPE *GetValue )( + + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugReferenceValue * This, /* [out] */ CORDB_ADDRESS *pValue); - - HRESULT ( STDMETHODCALLTYPE *SetValue )( + + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugReferenceValue * This, /* [in] */ CORDB_ADDRESS value); - - HRESULT ( STDMETHODCALLTYPE *Dereference )( + + HRESULT ( STDMETHODCALLTYPE *Dereference )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( + + HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugReferenceValueVtbl; @@ -14403,48 +14494,48 @@ EXTERN_C const IID IID_ICorDebugReferenceValue; CONST_VTBL struct ICorDebugReferenceValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugReferenceValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugReferenceValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugReferenceValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugReferenceValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugReferenceValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugReferenceValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugReferenceValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugReferenceValue_IsNull(This,pbNull) \ - ( (This)->lpVtbl -> IsNull(This,pbNull) ) + ( (This)->lpVtbl -> IsNull(This,pbNull) ) #define ICorDebugReferenceValue_GetValue(This,pValue) \ - ( (This)->lpVtbl -> GetValue(This,pValue) ) + ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ICorDebugReferenceValue_SetValue(This,value) \ - ( (This)->lpVtbl -> SetValue(This,value) ) + ( (This)->lpVtbl -> SetValue(This,value) ) #define ICorDebugReferenceValue_Dereference(This,ppValue) \ - ( (This)->lpVtbl -> Dereference(This,ppValue) ) + ( (This)->lpVtbl -> Dereference(This,ppValue) ) #define ICorDebugReferenceValue_DereferenceStrong(This,ppValue) \ - ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) + ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) #endif /* COBJMACROS */ @@ -14461,68 +14552,68 @@ EXTERN_C const IID IID_ICorDebugReferenceValue; #define __ICorDebugHeapValue_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAFA-8A68-11d2-983C-0000F808342D") ICorDebugHeapValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE IsValid( + virtual HRESULT STDMETHODCALLTYPE IsValid( /* [out] */ BOOL *pbValid) = 0; - - virtual HRESULT STDMETHODCALLTYPE CreateRelocBreakpoint( + + virtual HRESULT STDMETHODCALLTYPE CreateRelocBreakpoint( /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugHeapValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugHeapValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugHeapValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugHeapValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *IsValid )( + + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugHeapValue * This, /* [out] */ BOOL *pbValid); - - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugHeapValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - + END_INTERFACE } ICorDebugHeapValueVtbl; @@ -14531,39 +14622,39 @@ EXTERN_C const IID IID_ICorDebugHeapValue; CONST_VTBL struct ICorDebugHeapValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugHeapValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugHeapValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugHeapValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugHeapValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugHeapValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ @@ -14580,47 +14671,47 @@ EXTERN_C const IID IID_ICorDebugHeapValue; #define __ICorDebugHeapValue2_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("E3AC4D6C-9CB7-43e6-96CC-B21540E5083C") ICorDebugHeapValue2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreateHandle( + virtual HRESULT STDMETHODCALLTYPE CreateHandle( /* [in] */ CorDebugHandleType type, /* [out] */ ICorDebugHandleValue **ppHandle) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValue2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue2 * This); - - HRESULT ( STDMETHODCALLTYPE *CreateHandle )( + + HRESULT ( STDMETHODCALLTYPE *CreateHandle )( ICorDebugHeapValue2 * This, /* [in] */ CorDebugHandleType type, /* [out] */ ICorDebugHandleValue **ppHandle); - + END_INTERFACE } ICorDebugHeapValue2Vtbl; @@ -14629,23 +14720,23 @@ EXTERN_C const IID IID_ICorDebugHeapValue2; CONST_VTBL struct ICorDebugHeapValue2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue2_CreateHandle(This,type,ppHandle) \ - ( (This)->lpVtbl -> CreateHandle(This,type,ppHandle) ) + ( (This)->lpVtbl -> CreateHandle(This,type,ppHandle) ) #endif /* COBJMACROS */ @@ -14662,54 +14753,54 @@ EXTERN_C const IID IID_ICorDebugHeapValue2; #define __ICorDebugHeapValue3_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue3 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue3; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("A69ACAD8-2374-46e9-9FF8-B1F14120D296") ICorDebugHeapValue3 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetThreadOwningMonitorLock( + virtual HRESULT STDMETHODCALLTYPE GetThreadOwningMonitorLock( /* [out] */ ICorDebugThread **ppThread, /* [out] */ DWORD *pAcquisitionCount) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMonitorEventWaitList( + + virtual HRESULT STDMETHODCALLTYPE GetMonitorEventWaitList( /* [out] */ ICorDebugThreadEnum **ppThreadEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValue3Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue3 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue3 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue3 * This); - - HRESULT ( STDMETHODCALLTYPE *GetThreadOwningMonitorLock )( + + HRESULT ( STDMETHODCALLTYPE *GetThreadOwningMonitorLock )( ICorDebugHeapValue3 * This, /* [out] */ ICorDebugThread **ppThread, /* [out] */ DWORD *pAcquisitionCount); - - HRESULT ( STDMETHODCALLTYPE *GetMonitorEventWaitList )( + + HRESULT ( STDMETHODCALLTYPE *GetMonitorEventWaitList )( ICorDebugHeapValue3 * This, /* [out] */ ICorDebugThreadEnum **ppThreadEnum); - + END_INTERFACE } ICorDebugHeapValue3Vtbl; @@ -14718,26 +14809,26 @@ EXTERN_C const IID IID_ICorDebugHeapValue3; CONST_VTBL struct ICorDebugHeapValue3Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue3_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue3_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue3_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue3_GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) \ - ( (This)->lpVtbl -> GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) ) + ( (This)->lpVtbl -> GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) ) #define ICorDebugHeapValue3_GetMonitorEventWaitList(This,ppThreadEnum) \ - ( (This)->lpVtbl -> GetMonitorEventWaitList(This,ppThreadEnum) ) + ( (This)->lpVtbl -> GetMonitorEventWaitList(This,ppThreadEnum) ) #endif /* COBJMACROS */ @@ -14754,45 +14845,45 @@ EXTERN_C const IID IID_ICorDebugHeapValue3; #define __ICorDebugHeapValue4_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue4 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue4; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("B35DD495-A555-463B-9BE9-C55338486BB8") ICorDebugHeapValue4 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CreatePinnedHandle( + virtual HRESULT STDMETHODCALLTYPE CreatePinnedHandle( /* [out] */ ICorDebugHandleValue **ppHandle) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHeapValue4Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue4 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue4 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue4 * This); - - HRESULT ( STDMETHODCALLTYPE *CreatePinnedHandle )( + + HRESULT ( STDMETHODCALLTYPE *CreatePinnedHandle )( ICorDebugHeapValue4 * This, /* [out] */ ICorDebugHandleValue **ppHandle); - + END_INTERFACE } ICorDebugHeapValue4Vtbl; @@ -14801,23 +14892,23 @@ EXTERN_C const IID IID_ICorDebugHeapValue4; CONST_VTBL struct ICorDebugHeapValue4Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHeapValue4_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue4_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue4_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue4_CreatePinnedHandle(This,ppHandle) \ - ( (This)->lpVtbl -> CreatePinnedHandle(This,ppHandle) ) + ( (This)->lpVtbl -> CreatePinnedHandle(This,ppHandle) ) #endif /* COBJMACROS */ @@ -14834,109 +14925,109 @@ EXTERN_C const IID IID_ICorDebugHeapValue4; #define __ICorDebugObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("18AD3D6E-B7D2-11d2-BD04-0000F80849BD") ICorDebugObjectValue : public ICorDebugValue { public: - virtual HRESULT STDMETHODCALLTYPE GetClass( + virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFieldValue( + + virtual HRESULT STDMETHODCALLTYPE GetFieldValue( /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetVirtualMethod( + + virtual HRESULT STDMETHODCALLTYPE GetVirtualMethod( /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetContext( + + virtual HRESULT STDMETHODCALLTYPE GetContext( /* [out] */ ICorDebugContext **ppContext) = 0; - - virtual HRESULT STDMETHODCALLTYPE IsValueClass( + + virtual HRESULT STDMETHODCALLTYPE IsValueClass( /* [out] */ BOOL *pbIsValueClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetManagedCopy( + + virtual HRESULT STDMETHODCALLTYPE GetManagedCopy( /* [out] */ IUnknown **ppObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetFromManagedCopy( + + virtual HRESULT STDMETHODCALLTYPE SetFromManagedCopy( /* [in] */ IUnknown *pObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugObjectValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugObjectValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugObjectValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugObjectValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugObjectValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetClass )( + + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugObjectValue * This, /* [out] */ ICorDebugClass **ppClass); - - HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( + + HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( ICorDebugObjectValue * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( + + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( ICorDebugObjectValue * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetContext )( + + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugObjectValue * This, /* [out] */ ICorDebugContext **ppContext); - - HRESULT ( STDMETHODCALLTYPE *IsValueClass )( + + HRESULT ( STDMETHODCALLTYPE *IsValueClass )( ICorDebugObjectValue * This, /* [out] */ BOOL *pbIsValueClass); - - HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( + + HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( ICorDebugObjectValue * This, /* [out] */ IUnknown **ppObject); - - HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( + + HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( ICorDebugObjectValue * This, /* [in] */ IUnknown *pObject); - + END_INTERFACE } ICorDebugObjectValueVtbl; @@ -14945,54 +15036,54 @@ EXTERN_C const IID IID_ICorDebugObjectValue; CONST_VTBL struct ICorDebugObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugObjectValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugObjectValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugObjectValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugObjectValue_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugObjectValue_GetFieldValue(This,pClass,fieldDef,ppValue) \ - ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) + ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) #define ICorDebugObjectValue_GetVirtualMethod(This,memberRef,ppFunction) \ - ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) + ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) #define ICorDebugObjectValue_GetContext(This,ppContext) \ - ( (This)->lpVtbl -> GetContext(This,ppContext) ) + ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugObjectValue_IsValueClass(This,pbIsValueClass) \ - ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) + ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) #define ICorDebugObjectValue_GetManagedCopy(This,ppObject) \ - ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) + ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) #define ICorDebugObjectValue_SetFromManagedCopy(This,pObject) \ - ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) + ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) #endif /* COBJMACROS */ @@ -15009,49 +15100,49 @@ EXTERN_C const IID IID_ICorDebugObjectValue; #define __ICorDebugObjectValue2_INTERFACE_DEFINED__ /* interface ICorDebugObjectValue2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectValue2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("49E4A320-4A9B-4eca-B105-229FB7D5009F") ICorDebugObjectValue2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetVirtualMethodAndType( + virtual HRESULT STDMETHODCALLTYPE GetVirtualMethodAndType( /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction, /* [out] */ ICorDebugType **ppType) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugObjectValue2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectValue2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectValue2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectValue2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetVirtualMethodAndType )( + + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethodAndType )( ICorDebugObjectValue2 * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction, /* [out] */ ICorDebugType **ppType); - + END_INTERFACE } ICorDebugObjectValue2Vtbl; @@ -15060,23 +15151,23 @@ EXTERN_C const IID IID_ICorDebugObjectValue2; CONST_VTBL struct ICorDebugObjectValue2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugObjectValue2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectValue2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectValue2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectValue2_GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) \ - ( (This)->lpVtbl -> GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) ) + ( (This)->lpVtbl -> GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) ) #endif /* COBJMACROS */ @@ -15093,52 +15184,52 @@ EXTERN_C const IID IID_ICorDebugObjectValue2; #define __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugDelegateObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("3AF70CC7-6047-47F6-A5C5-090A1A622638") ICorDebugDelegateObjectValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetTarget( + virtual HRESULT STDMETHODCALLTYPE GetTarget( /* [out] */ ICorDebugReferenceValue **ppObject) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFunction( + + virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugDelegateObjectValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDelegateObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDelegateObjectValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDelegateObjectValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetTarget )( + + HRESULT ( STDMETHODCALLTYPE *GetTarget )( ICorDebugDelegateObjectValue * This, /* [out] */ ICorDebugReferenceValue **ppObject); - - HRESULT ( STDMETHODCALLTYPE *GetFunction )( + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugDelegateObjectValue * This, /* [out] */ ICorDebugFunction **ppFunction); - + END_INTERFACE } ICorDebugDelegateObjectValueVtbl; @@ -15147,26 +15238,26 @@ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; CONST_VTBL struct ICorDebugDelegateObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugDelegateObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDelegateObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDelegateObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDelegateObjectValue_GetTarget(This,ppObject) \ - ( (This)->lpVtbl -> GetTarget(This,ppObject) ) + ( (This)->lpVtbl -> GetTarget(This,ppObject) ) #define ICorDebugDelegateObjectValue_GetFunction(This,ppFunction) \ - ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #endif /* COBJMACROS */ @@ -15183,69 +15274,69 @@ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; #define __ICorDebugBoxValue_INTERFACE_DEFINED__ /* interface ICorDebugBoxValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBoxValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAFC-8A68-11d2-983C-0000F808342D") ICorDebugBoxValue : public ICorDebugHeapValue { public: - virtual HRESULT STDMETHODCALLTYPE GetObject( + virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugObjectValue **ppObject) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBoxValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBoxValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBoxValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBoxValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugBoxValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugBoxValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugBoxValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugBoxValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *IsValid )( + + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugBoxValue * This, /* [out] */ BOOL *pbValid); - - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugBoxValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetObject )( + + HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugBoxValue * This, /* [out] */ ICorDebugObjectValue **ppObject); - + END_INTERFACE } ICorDebugBoxValueVtbl; @@ -15254,43 +15345,43 @@ EXTERN_C const IID IID_ICorDebugBoxValue; CONST_VTBL struct ICorDebugBoxValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBoxValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBoxValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBoxValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBoxValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugBoxValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugBoxValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugBoxValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugBoxValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugBoxValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugBoxValue_GetObject(This,ppObject) \ - ( (This)->lpVtbl -> GetObject(This,ppObject) ) + ( (This)->lpVtbl -> GetObject(This,ppObject) ) #endif /* COBJMACROS */ @@ -15303,94 +15394,94 @@ EXTERN_C const IID IID_ICorDebugBoxValue; #endif /* __ICorDebugBoxValue_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0104 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0105 */ +/* [local] */ #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0104_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0104_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0105_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0105_v0_0_s_ifspec; #ifndef __ICorDebugStringValue_INTERFACE_DEFINED__ #define __ICorDebugStringValue_INTERFACE_DEFINED__ /* interface ICorDebugStringValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStringValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCAFD-8A68-11d2-983C-0000F808342D") ICorDebugStringValue : public ICorDebugHeapValue { public: - virtual HRESULT STDMETHODCALLTYPE GetLength( + virtual HRESULT STDMETHODCALLTYPE GetLength( /* [out] */ ULONG32 *pcchString) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetString( + + virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStringValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStringValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStringValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStringValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugStringValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugStringValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugStringValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugStringValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *IsValid )( + + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugStringValue * This, /* [out] */ BOOL *pbValid); - - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugStringValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetLength )( + + HRESULT ( STDMETHODCALLTYPE *GetLength )( ICorDebugStringValue * This, /* [out] */ ULONG32 *pcchString); - - HRESULT ( STDMETHODCALLTYPE *GetString )( + + HRESULT ( STDMETHODCALLTYPE *GetString )( ICorDebugStringValue * This, /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]); - + END_INTERFACE } ICorDebugStringValueVtbl; @@ -15399,46 +15490,46 @@ EXTERN_C const IID IID_ICorDebugStringValue; CONST_VTBL struct ICorDebugStringValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStringValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStringValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStringValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStringValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugStringValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugStringValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugStringValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugStringValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugStringValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugStringValue_GetLength(This,pcchString) \ - ( (This)->lpVtbl -> GetLength(This,pcchString) ) + ( (This)->lpVtbl -> GetLength(This,pcchString) ) #define ICorDebugStringValue_GetString(This,cchString,pcchString,szString) \ - ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) + ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) #endif /* COBJMACROS */ @@ -15451,141 +15542,141 @@ EXTERN_C const IID IID_ICorDebugStringValue; #endif /* __ICorDebugStringValue_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0105 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0106 */ +/* [local] */ #pragma warning(pop) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0105_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0105_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0106_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0106_v0_0_s_ifspec; #ifndef __ICorDebugArrayValue_INTERFACE_DEFINED__ #define __ICorDebugArrayValue_INTERFACE_DEFINED__ /* interface ICorDebugArrayValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugArrayValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("0405B0DF-A660-11d2-BD02-0000F80849BD") ICorDebugArrayValue : public ICorDebugHeapValue { public: - virtual HRESULT STDMETHODCALLTYPE GetElementType( + virtual HRESULT STDMETHODCALLTYPE GetElementType( /* [out] */ CorElementType *pType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRank( + + virtual HRESULT STDMETHODCALLTYPE GetRank( /* [out] */ ULONG32 *pnRank) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCount( + + virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG32 *pnCount) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDimensions( + + virtual HRESULT STDMETHODCALLTYPE GetDimensions( /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 dims[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE HasBaseIndicies( + + virtual HRESULT STDMETHODCALLTYPE HasBaseIndicies( /* [out] */ BOOL *pbHasBaseIndicies) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBaseIndicies( + + virtual HRESULT STDMETHODCALLTYPE GetBaseIndicies( /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 indicies[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetElement( + + virtual HRESULT STDMETHODCALLTYPE GetElement( /* [in] */ ULONG32 cdim, /* [length_is][size_is][in] */ ULONG32 indices[ ], /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetElementAtPosition( + + virtual HRESULT STDMETHODCALLTYPE GetElementAtPosition( /* [in] */ ULONG32 nPosition, /* [out] */ ICorDebugValue **ppValue) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugArrayValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugArrayValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugArrayValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugArrayValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugArrayValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugArrayValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugArrayValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *IsValid )( + + HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugArrayValue * This, /* [out] */ BOOL *pbValid); - - HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugArrayValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetElementType )( + + HRESULT ( STDMETHODCALLTYPE *GetElementType )( ICorDebugArrayValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetRank )( + + HRESULT ( STDMETHODCALLTYPE *GetRank )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pnRank); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pnCount); - - HRESULT ( STDMETHODCALLTYPE *GetDimensions )( + + HRESULT ( STDMETHODCALLTYPE *GetDimensions )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 dims[ ]); - - HRESULT ( STDMETHODCALLTYPE *HasBaseIndicies )( + + HRESULT ( STDMETHODCALLTYPE *HasBaseIndicies )( ICorDebugArrayValue * This, /* [out] */ BOOL *pbHasBaseIndicies); - - HRESULT ( STDMETHODCALLTYPE *GetBaseIndicies )( + + HRESULT ( STDMETHODCALLTYPE *GetBaseIndicies )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 indicies[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetElement )( + + HRESULT ( STDMETHODCALLTYPE *GetElement )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][in] */ ULONG32 indices[ ], /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetElementAtPosition )( + + HRESULT ( STDMETHODCALLTYPE *GetElementAtPosition )( ICorDebugArrayValue * This, /* [in] */ ULONG32 nPosition, /* [out] */ ICorDebugValue **ppValue); - + END_INTERFACE } ICorDebugArrayValueVtbl; @@ -15594,64 +15685,64 @@ EXTERN_C const IID IID_ICorDebugArrayValue; CONST_VTBL struct ICorDebugArrayValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugArrayValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugArrayValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugArrayValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugArrayValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugArrayValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugArrayValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugArrayValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugArrayValue_IsValid(This,pbValid) \ - ( (This)->lpVtbl -> IsValid(This,pbValid) ) + ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugArrayValue_CreateRelocBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugArrayValue_GetElementType(This,pType) \ - ( (This)->lpVtbl -> GetElementType(This,pType) ) + ( (This)->lpVtbl -> GetElementType(This,pType) ) #define ICorDebugArrayValue_GetRank(This,pnRank) \ - ( (This)->lpVtbl -> GetRank(This,pnRank) ) + ( (This)->lpVtbl -> GetRank(This,pnRank) ) #define ICorDebugArrayValue_GetCount(This,pnCount) \ - ( (This)->lpVtbl -> GetCount(This,pnCount) ) + ( (This)->lpVtbl -> GetCount(This,pnCount) ) #define ICorDebugArrayValue_GetDimensions(This,cdim,dims) \ - ( (This)->lpVtbl -> GetDimensions(This,cdim,dims) ) + ( (This)->lpVtbl -> GetDimensions(This,cdim,dims) ) #define ICorDebugArrayValue_HasBaseIndicies(This,pbHasBaseIndicies) \ - ( (This)->lpVtbl -> HasBaseIndicies(This,pbHasBaseIndicies) ) + ( (This)->lpVtbl -> HasBaseIndicies(This,pbHasBaseIndicies) ) #define ICorDebugArrayValue_GetBaseIndicies(This,cdim,indicies) \ - ( (This)->lpVtbl -> GetBaseIndicies(This,cdim,indicies) ) + ( (This)->lpVtbl -> GetBaseIndicies(This,cdim,indicies) ) #define ICorDebugArrayValue_GetElement(This,cdim,indices,ppValue) \ - ( (This)->lpVtbl -> GetElement(This,cdim,indices,ppValue) ) + ( (This)->lpVtbl -> GetElement(This,cdim,indices,ppValue) ) #define ICorDebugArrayValue_GetElementAtPosition(This,nPosition,ppValue) \ - ( (This)->lpVtbl -> GetElementAtPosition(This,nPosition,ppValue) ) + ( (This)->lpVtbl -> GetElementAtPosition(This,nPosition,ppValue) ) #endif /* COBJMACROS */ @@ -15668,97 +15759,97 @@ EXTERN_C const IID IID_ICorDebugArrayValue; #define __ICorDebugVariableHome_INTERFACE_DEFINED__ /* interface ICorDebugVariableHome */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum VariableLocationType { VLT_REGISTER = 0, VLT_REGISTER_RELATIVE = ( VLT_REGISTER + 1 ) , - VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) + VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) } VariableLocationType; EXTERN_C const IID IID_ICorDebugVariableHome; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("50847b8d-f43f-41b0-924c-6383a5f2278b") ICorDebugVariableHome : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCode( + virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ICorDebugCode **ppCode) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( /* [out] */ ULONG32 *pSlotIndex) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( + + virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( /* [out] */ ULONG32 *pArgumentIndex) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLiveRange( + + virtual HRESULT STDMETHODCALLTYPE GetLiveRange( /* [out] */ ULONG32 *pStartOffset, /* [out] */ ULONG32 *pEndOffset) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetLocationType( + + virtual HRESULT STDMETHODCALLTYPE GetLocationType( /* [out] */ VariableLocationType *pLocationType) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRegister( + + virtual HRESULT STDMETHODCALLTYPE GetRegister( /* [out] */ CorDebugRegister *pRegister) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOffset( + + virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ LONG *pOffset) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVariableHomeVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableHome * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableHome * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableHome * This); - - HRESULT ( STDMETHODCALLTYPE *GetCode )( + + HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugVariableHome * This, /* [out] */ ICorDebugCode **ppCode); - - HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pSlotIndex); - - HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( + + HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pArgumentIndex); - - HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( + + HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pStartOffset, /* [out] */ ULONG32 *pEndOffset); - - HRESULT ( STDMETHODCALLTYPE *GetLocationType )( + + HRESULT ( STDMETHODCALLTYPE *GetLocationType )( ICorDebugVariableHome * This, /* [out] */ VariableLocationType *pLocationType); - - HRESULT ( STDMETHODCALLTYPE *GetRegister )( + + HRESULT ( STDMETHODCALLTYPE *GetRegister )( ICorDebugVariableHome * This, /* [out] */ CorDebugRegister *pRegister); - - HRESULT ( STDMETHODCALLTYPE *GetOffset )( + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugVariableHome * This, /* [out] */ LONG *pOffset); - + END_INTERFACE } ICorDebugVariableHomeVtbl; @@ -15767,41 +15858,41 @@ EXTERN_C const IID IID_ICorDebugVariableHome; CONST_VTBL struct ICorDebugVariableHomeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVariableHome_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableHome_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableHome_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableHome_GetCode(This,ppCode) \ - ( (This)->lpVtbl -> GetCode(This,ppCode) ) + ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugVariableHome_GetSlotIndex(This,pSlotIndex) \ - ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) #define ICorDebugVariableHome_GetArgumentIndex(This,pArgumentIndex) \ - ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) + ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) #define ICorDebugVariableHome_GetLiveRange(This,pStartOffset,pEndOffset) \ - ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) + ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) #define ICorDebugVariableHome_GetLocationType(This,pLocationType) \ - ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) + ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) #define ICorDebugVariableHome_GetRegister(This,pRegister) \ - ( (This)->lpVtbl -> GetRegister(This,pRegister) ) + ( (This)->lpVtbl -> GetRegister(This,pRegister) ) #define ICorDebugVariableHome_GetOffset(This,pOffset) \ - ( (This)->lpVtbl -> GetOffset(This,pOffset) ) + ( (This)->lpVtbl -> GetOffset(This,pOffset) ) #endif /* COBJMACROS */ @@ -15818,86 +15909,86 @@ EXTERN_C const IID IID_ICorDebugVariableHome; #define __ICorDebugHandleValue_INTERFACE_DEFINED__ /* interface ICorDebugHandleValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHandleValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("029596E8-276B-46a1-9821-732E96BBB00B") ICorDebugHandleValue : public ICorDebugReferenceValue { public: - virtual HRESULT STDMETHODCALLTYPE GetHandleType( + virtual HRESULT STDMETHODCALLTYPE GetHandleType( /* [out] */ CorDebugHandleType *pType) = 0; - + virtual HRESULT STDMETHODCALLTYPE Dispose( void) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugHandleValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHandleValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHandleValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHandleValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugHandleValue * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugHandleValue * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugHandleValue * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *IsNull )( + + HRESULT ( STDMETHODCALLTYPE *IsNull )( ICorDebugHandleValue * This, /* [out] */ BOOL *pbNull); - - HRESULT ( STDMETHODCALLTYPE *GetValue )( + + HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugHandleValue * This, /* [out] */ CORDB_ADDRESS *pValue); - - HRESULT ( STDMETHODCALLTYPE *SetValue )( + + HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugHandleValue * This, /* [in] */ CORDB_ADDRESS value); - - HRESULT ( STDMETHODCALLTYPE *Dereference )( + + HRESULT ( STDMETHODCALLTYPE *Dereference )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( + + HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetHandleType )( + + HRESULT ( STDMETHODCALLTYPE *GetHandleType )( ICorDebugHandleValue * This, /* [out] */ CorDebugHandleType *pType); - - HRESULT ( STDMETHODCALLTYPE *Dispose )( + + HRESULT ( STDMETHODCALLTYPE *Dispose )( ICorDebugHandleValue * This); - + END_INTERFACE } ICorDebugHandleValueVtbl; @@ -15906,55 +15997,55 @@ EXTERN_C const IID IID_ICorDebugHandleValue; CONST_VTBL struct ICorDebugHandleValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugHandleValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHandleValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHandleValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHandleValue_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugHandleValue_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugHandleValue_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugHandleValue_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugHandleValue_IsNull(This,pbNull) \ - ( (This)->lpVtbl -> IsNull(This,pbNull) ) + ( (This)->lpVtbl -> IsNull(This,pbNull) ) #define ICorDebugHandleValue_GetValue(This,pValue) \ - ( (This)->lpVtbl -> GetValue(This,pValue) ) + ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ICorDebugHandleValue_SetValue(This,value) \ - ( (This)->lpVtbl -> SetValue(This,value) ) + ( (This)->lpVtbl -> SetValue(This,value) ) #define ICorDebugHandleValue_Dereference(This,ppValue) \ - ( (This)->lpVtbl -> Dereference(This,ppValue) ) + ( (This)->lpVtbl -> Dereference(This,ppValue) ) #define ICorDebugHandleValue_DereferenceStrong(This,ppValue) \ - ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) + ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) #define ICorDebugHandleValue_GetHandleType(This,pType) \ - ( (This)->lpVtbl -> GetHandleType(This,pType) ) + ( (This)->lpVtbl -> GetHandleType(This,pType) ) #define ICorDebugHandleValue_Dispose(This) \ - ( (This)->lpVtbl -> Dispose(This) ) + ( (This)->lpVtbl -> Dispose(This) ) #endif /* COBJMACROS */ @@ -15971,85 +16062,85 @@ EXTERN_C const IID IID_ICorDebugHandleValue; #define __ICorDebugContext_INTERFACE_DEFINED__ /* interface ICorDebugContext */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugContext; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB00-8A68-11d2-983C-0000F808342D") ICorDebugContext : public ICorDebugObjectValue { public: }; - - + + #else /* C style interface */ typedef struct ICorDebugContextVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugContext * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugContext * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugContext * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugContext * This, /* [out] */ CorElementType *pType); - - HRESULT ( STDMETHODCALLTYPE *GetSize )( + + HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugContext * This, /* [out] */ ULONG32 *pSize); - - HRESULT ( STDMETHODCALLTYPE *GetAddress )( + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugContext * This, /* [out] */ CORDB_ADDRESS *pAddress); - - HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugContext * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); - - HRESULT ( STDMETHODCALLTYPE *GetClass )( + + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugContext * This, /* [out] */ ICorDebugClass **ppClass); - - HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( + + HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( ICorDebugContext * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( + + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( ICorDebugContext * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction); - - HRESULT ( STDMETHODCALLTYPE *GetContext )( + + HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugContext * This, /* [out] */ ICorDebugContext **ppContext); - - HRESULT ( STDMETHODCALLTYPE *IsValueClass )( + + HRESULT ( STDMETHODCALLTYPE *IsValueClass )( ICorDebugContext * This, /* [out] */ BOOL *pbIsValueClass); - - HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( + + HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( ICorDebugContext * This, /* [out] */ IUnknown **ppObject); - - HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( + + HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( ICorDebugContext * This, /* [in] */ IUnknown *pObject); - + END_INTERFACE } ICorDebugContextVtbl; @@ -16058,54 +16149,54 @@ EXTERN_C const IID IID_ICorDebugContext; CONST_VTBL struct ICorDebugContextVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugContext_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugContext_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugContext_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugContext_GetType(This,pType) \ - ( (This)->lpVtbl -> GetType(This,pType) ) + ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugContext_GetSize(This,pSize) \ - ( (This)->lpVtbl -> GetSize(This,pSize) ) + ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugContext_GetAddress(This,pAddress) \ - ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugContext_CreateBreakpoint(This,ppBreakpoint) \ - ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugContext_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugContext_GetFieldValue(This,pClass,fieldDef,ppValue) \ - ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) + ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) #define ICorDebugContext_GetVirtualMethod(This,memberRef,ppFunction) \ - ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) + ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) #define ICorDebugContext_GetContext(This,ppContext) \ - ( (This)->lpVtbl -> GetContext(This,ppContext) ) + ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugContext_IsValueClass(This,pbIsValueClass) \ - ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) + ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) #define ICorDebugContext_GetManagedCopy(This,ppObject) \ - ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) + ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) #define ICorDebugContext_SetFromManagedCopy(This,pObject) \ - ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) + ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) #endif /* COBJMACROS */ @@ -16123,60 +16214,60 @@ EXTERN_C const IID IID_ICorDebugContext; #define __ICorDebugComObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugComObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugComObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("5F69C5E5-3E12-42DF-B371-F9D761D6EE24") ICorDebugComObjectValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetCachedInterfaceTypes( + virtual HRESULT STDMETHODCALLTYPE GetCachedInterfaceTypes( /* [in] */ BOOL bIInspectableOnly, /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetCachedInterfacePointers( + + virtual HRESULT STDMETHODCALLTYPE GetCachedInterfacePointers( /* [in] */ BOOL bIInspectableOnly, /* [in] */ ULONG32 celt, /* [out] */ ULONG32 *pcEltFetched, /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugComObjectValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugComObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugComObjectValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugComObjectValue * This); - - HRESULT ( STDMETHODCALLTYPE *GetCachedInterfaceTypes )( + + HRESULT ( STDMETHODCALLTYPE *GetCachedInterfaceTypes )( ICorDebugComObjectValue * This, /* [in] */ BOOL bIInspectableOnly, /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCachedInterfacePointers )( + + HRESULT ( STDMETHODCALLTYPE *GetCachedInterfacePointers )( ICorDebugComObjectValue * This, /* [in] */ BOOL bIInspectableOnly, /* [in] */ ULONG32 celt, /* [out] */ ULONG32 *pcEltFetched, /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs); - + END_INTERFACE } ICorDebugComObjectValueVtbl; @@ -16185,26 +16276,26 @@ EXTERN_C const IID IID_ICorDebugComObjectValue; CONST_VTBL struct ICorDebugComObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugComObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugComObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugComObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugComObjectValue_GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) \ - ( (This)->lpVtbl -> GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) ) + ( (This)->lpVtbl -> GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) ) #define ICorDebugComObjectValue_GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) \ - ( (This)->lpVtbl -> GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) ) + ( (This)->lpVtbl -> GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) ) #endif /* COBJMACROS */ @@ -16221,64 +16312,64 @@ EXTERN_C const IID IID_ICorDebugComObjectValue; #define __ICorDebugObjectEnum_INTERFACE_DEFINED__ /* interface ICorDebugObjectEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB02-8A68-11d2-983C-0000F808342D") ICorDebugObjectEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugObjectEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugObjectEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugObjectEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugObjectEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugObjectEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugObjectEnumVtbl; @@ -16287,36 +16378,36 @@ EXTERN_C const IID IID_ICorDebugObjectEnum; CONST_VTBL struct ICorDebugObjectEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugObjectEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugObjectEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugObjectEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugObjectEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugObjectEnum_Next(This,celt,objects,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ @@ -16333,64 +16424,64 @@ EXTERN_C const IID IID_ICorDebugObjectEnum; #define __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ /* interface ICorDebugBreakpointEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBreakpointEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB03-8A68-11d2-983C-0000F808342D") ICorDebugBreakpointEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBreakpointEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBreakpointEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBreakpointEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBreakpointEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugBreakpointEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugBreakpointEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugBreakpointEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugBreakpointEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugBreakpointEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugBreakpointEnumVtbl; @@ -16399,36 +16490,36 @@ EXTERN_C const IID IID_ICorDebugBreakpointEnum; CONST_VTBL struct ICorDebugBreakpointEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBreakpointEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBreakpointEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBreakpointEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBreakpointEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugBreakpointEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugBreakpointEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugBreakpointEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugBreakpointEnum_Next(This,celt,breakpoints,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,breakpoints,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,breakpoints,pceltFetched) ) #endif /* COBJMACROS */ @@ -16445,64 +16536,64 @@ EXTERN_C const IID IID_ICorDebugBreakpointEnum; #define __ICorDebugStepperEnum_INTERFACE_DEFINED__ /* interface ICorDebugStepperEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStepperEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB04-8A68-11d2-983C-0000F808342D") ICorDebugStepperEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugStepperEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepperEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepperEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepperEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugStepperEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugStepperEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugStepperEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugStepperEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugStepperEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugStepperEnumVtbl; @@ -16511,36 +16602,36 @@ EXTERN_C const IID IID_ICorDebugStepperEnum; CONST_VTBL struct ICorDebugStepperEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugStepperEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepperEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepperEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepperEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugStepperEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugStepperEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugStepperEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugStepperEnum_Next(This,celt,steppers,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,steppers,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,steppers,pceltFetched) ) #endif /* COBJMACROS */ @@ -16557,64 +16648,64 @@ EXTERN_C const IID IID_ICorDebugStepperEnum; #define __ICorDebugProcessEnum_INTERFACE_DEFINED__ /* interface ICorDebugProcessEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcessEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB05-8A68-11d2-983C-0000F808342D") ICorDebugProcessEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugProcessEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcessEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcessEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcessEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugProcessEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugProcessEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugProcessEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugProcessEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugProcessEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugProcessEnumVtbl; @@ -16623,36 +16714,36 @@ EXTERN_C const IID IID_ICorDebugProcessEnum; CONST_VTBL struct ICorDebugProcessEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugProcessEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcessEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcessEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcessEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugProcessEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugProcessEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugProcessEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugProcessEnum_Next(This,celt,processes,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,processes,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,processes,pceltFetched) ) #endif /* COBJMACROS */ @@ -16669,64 +16760,64 @@ EXTERN_C const IID IID_ICorDebugProcessEnum; #define __ICorDebugThreadEnum_INTERFACE_DEFINED__ /* interface ICorDebugThreadEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThreadEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB06-8A68-11d2-983C-0000F808342D") ICorDebugThreadEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugThreadEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThreadEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThreadEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThreadEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugThreadEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugThreadEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugThreadEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugThreadEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugThreadEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugThreadEnumVtbl; @@ -16735,36 +16826,36 @@ EXTERN_C const IID IID_ICorDebugThreadEnum; CONST_VTBL struct ICorDebugThreadEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugThreadEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThreadEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThreadEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThreadEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugThreadEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugThreadEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugThreadEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugThreadEnum_Next(This,celt,threads,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,threads,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,threads,pceltFetched) ) #endif /* COBJMACROS */ @@ -16781,64 +16872,64 @@ EXTERN_C const IID IID_ICorDebugThreadEnum; #define __ICorDebugFrameEnum_INTERFACE_DEFINED__ /* interface ICorDebugFrameEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFrameEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB07-8A68-11d2-983C-0000F808342D") ICorDebugFrameEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugFrameEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFrameEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFrameEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFrameEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugFrameEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugFrameEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugFrameEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugFrameEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugFrameEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugFrameEnumVtbl; @@ -16847,36 +16938,36 @@ EXTERN_C const IID IID_ICorDebugFrameEnum; CONST_VTBL struct ICorDebugFrameEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugFrameEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFrameEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFrameEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFrameEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugFrameEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugFrameEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugFrameEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugFrameEnum_Next(This,celt,frames,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,frames,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,frames,pceltFetched) ) #endif /* COBJMACROS */ @@ -16893,64 +16984,64 @@ EXTERN_C const IID IID_ICorDebugFrameEnum; #define __ICorDebugChainEnum_INTERFACE_DEFINED__ /* interface ICorDebugChainEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugChainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB08-8A68-11d2-983C-0000F808342D") ICorDebugChainEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugChainEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugChainEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugChainEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugChainEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugChainEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugChainEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugChainEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugChainEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugChainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugChainEnumVtbl; @@ -16959,36 +17050,36 @@ EXTERN_C const IID IID_ICorDebugChainEnum; CONST_VTBL struct ICorDebugChainEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugChainEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugChainEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugChainEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugChainEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugChainEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugChainEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugChainEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugChainEnum_Next(This,celt,chains,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,chains,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,chains,pceltFetched) ) #endif /* COBJMACROS */ @@ -17005,64 +17096,64 @@ EXTERN_C const IID IID_ICorDebugChainEnum; #define __ICorDebugModuleEnum_INTERFACE_DEFINED__ /* interface ICorDebugModuleEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB09-8A68-11d2-983C-0000F808342D") ICorDebugModuleEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugModuleEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugModuleEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugModuleEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugModuleEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugModuleEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugModuleEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugModuleEnumVtbl; @@ -17071,36 +17162,36 @@ EXTERN_C const IID IID_ICorDebugModuleEnum; CONST_VTBL struct ICorDebugModuleEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugModuleEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugModuleEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugModuleEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugModuleEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugModuleEnum_Next(This,celt,modules,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,modules,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,modules,pceltFetched) ) #endif /* COBJMACROS */ @@ -17117,64 +17208,64 @@ EXTERN_C const IID IID_ICorDebugModuleEnum; #define __ICorDebugValueEnum_INTERFACE_DEFINED__ /* interface ICorDebugValueEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValueEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC7BCB0A-8A68-11d2-983C-0000F808342D") ICorDebugValueEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugValue *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugValueEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValueEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValueEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValueEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugValueEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugValueEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugValueEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugValueEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugValueEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugValue *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugValueEnumVtbl; @@ -17183,36 +17274,36 @@ EXTERN_C const IID IID_ICorDebugValueEnum; CONST_VTBL struct ICorDebugValueEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugValueEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValueEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValueEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValueEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugValueEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugValueEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugValueEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugValueEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -17229,64 +17320,64 @@ EXTERN_C const IID IID_ICorDebugValueEnum; #define __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ /* interface ICorDebugVariableHomeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("e76b7a57-4f7a-4309-85a7-5d918c3deaf7") ICorDebugVariableHomeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugVariableHomeEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableHomeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableHomeEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableHomeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugVariableHomeEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugVariableHomeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugVariableHomeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugVariableHomeEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugVariableHomeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugVariableHomeEnumVtbl; @@ -17295,36 +17386,36 @@ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; CONST_VTBL struct ICorDebugVariableHomeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugVariableHomeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableHomeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableHomeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableHomeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugVariableHomeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugVariableHomeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugVariableHomeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugVariableHomeEnum_Next(This,celt,homes,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) #endif /* COBJMACROS */ @@ -17341,64 +17432,64 @@ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; #define __ICorDebugCodeEnum_INTERFACE_DEFINED__ /* interface ICorDebugCodeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCodeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("55E96461-9645-45e4-A2FF-0367877ABCDE") ICorDebugCodeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugCode *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugCodeEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCodeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCodeEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCodeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugCodeEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugCodeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugCodeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugCodeEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugCodeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugCode *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugCodeEnumVtbl; @@ -17407,36 +17498,36 @@ EXTERN_C const IID IID_ICorDebugCodeEnum; CONST_VTBL struct ICorDebugCodeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugCodeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCodeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCodeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCodeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugCodeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugCodeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugCodeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugCodeEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -17453,64 +17544,64 @@ EXTERN_C const IID IID_ICorDebugCodeEnum; #define __ICorDebugTypeEnum_INTERFACE_DEFINED__ /* interface ICorDebugTypeEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugTypeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("10F27499-9DF2-43ce-8333-A321D7C99CB4") ICorDebugTypeEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugType *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugTypeEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugTypeEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugTypeEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugTypeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugTypeEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugTypeEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugTypeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugTypeEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugTypeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugType *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugTypeEnumVtbl; @@ -17519,36 +17610,36 @@ EXTERN_C const IID IID_ICorDebugTypeEnum; CONST_VTBL struct ICorDebugTypeEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugTypeEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugTypeEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugTypeEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugTypeEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugTypeEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugTypeEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugTypeEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugTypeEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -17565,91 +17656,91 @@ EXTERN_C const IID IID_ICorDebugTypeEnum; #define __ICorDebugType_INTERFACE_DEFINED__ /* interface ICorDebugType */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugType; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5") ICorDebugType : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetType( + virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ CorElementType *ty) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetClass( + + virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; - - virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( + + virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFirstTypeParameter( + + virtual HRESULT STDMETHODCALLTYPE GetFirstTypeParameter( /* [out] */ ICorDebugType **value) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetBase( + + virtual HRESULT STDMETHODCALLTYPE GetBase( /* [out] */ ICorDebugType **pBase) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRank( + + virtual HRESULT STDMETHODCALLTYPE GetRank( /* [out] */ ULONG32 *pnRank) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugTypeVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugType * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugType * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugType * This); - - HRESULT ( STDMETHODCALLTYPE *GetType )( + + HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugType * This, /* [out] */ CorElementType *ty); - - HRESULT ( STDMETHODCALLTYPE *GetClass )( + + HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugType * This, /* [out] */ ICorDebugClass **ppClass); - - HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( ICorDebugType * This, /* [out] */ ICorDebugTypeEnum **ppTyParEnum); - - HRESULT ( STDMETHODCALLTYPE *GetFirstTypeParameter )( + + HRESULT ( STDMETHODCALLTYPE *GetFirstTypeParameter )( ICorDebugType * This, /* [out] */ ICorDebugType **value); - - HRESULT ( STDMETHODCALLTYPE *GetBase )( + + HRESULT ( STDMETHODCALLTYPE *GetBase )( ICorDebugType * This, /* [out] */ ICorDebugType **pBase); - - HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( ICorDebugType * This, /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue); - - HRESULT ( STDMETHODCALLTYPE *GetRank )( + + HRESULT ( STDMETHODCALLTYPE *GetRank )( ICorDebugType * This, /* [out] */ ULONG32 *pnRank); - + END_INTERFACE } ICorDebugTypeVtbl; @@ -17658,41 +17749,41 @@ EXTERN_C const IID IID_ICorDebugType; CONST_VTBL struct ICorDebugTypeVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugType_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugType_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugType_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugType_GetType(This,ty) \ - ( (This)->lpVtbl -> GetType(This,ty) ) + ( (This)->lpVtbl -> GetType(This,ty) ) #define ICorDebugType_GetClass(This,ppClass) \ - ( (This)->lpVtbl -> GetClass(This,ppClass) ) + ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugType_EnumerateTypeParameters(This,ppTyParEnum) \ - ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) + ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) #define ICorDebugType_GetFirstTypeParameter(This,value) \ - ( (This)->lpVtbl -> GetFirstTypeParameter(This,value) ) + ( (This)->lpVtbl -> GetFirstTypeParameter(This,value) ) #define ICorDebugType_GetBase(This,pBase) \ - ( (This)->lpVtbl -> GetBase(This,pBase) ) + ( (This)->lpVtbl -> GetBase(This,pBase) ) #define ICorDebugType_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ - ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) + ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) #define ICorDebugType_GetRank(This,pnRank) \ - ( (This)->lpVtbl -> GetRank(This,pnRank) ) + ( (This)->lpVtbl -> GetRank(This,pnRank) ) #endif /* COBJMACROS */ @@ -17709,45 +17800,45 @@ EXTERN_C const IID IID_ICorDebugType; #define __ICorDebugType2_INTERFACE_DEFINED__ /* interface ICorDebugType2 */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugType2; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("e6e91d79-693d-48bc-b417-8284b4f10fb5") ICorDebugType2 : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetTypeID( + virtual HRESULT STDMETHODCALLTYPE GetTypeID( /* [out] */ COR_TYPEID *id) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugType2Vtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugType2 * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugType2 * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugType2 * This); - - HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( ICorDebugType2 * This, /* [out] */ COR_TYPEID *id); - + END_INTERFACE } ICorDebugType2Vtbl; @@ -17756,23 +17847,23 @@ EXTERN_C const IID IID_ICorDebugType2; CONST_VTBL struct ICorDebugType2Vtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugType2_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugType2_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugType2_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugType2_GetTypeID(This,id) \ - ( (This)->lpVtbl -> GetTypeID(This,id) ) + ( (This)->lpVtbl -> GetTypeID(This,id) ) #endif /* COBJMACROS */ @@ -17789,64 +17880,64 @@ EXTERN_C const IID IID_ICorDebugType2; #define __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ /* interface ICorDebugErrorInfoEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("F0E18809-72B5-11d2-976F-00A0C9B4D50C") ICorDebugErrorInfoEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugErrorInfoEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugErrorInfoEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugErrorInfoEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugErrorInfoEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugErrorInfoEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugErrorInfoEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugErrorInfoEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugErrorInfoEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugErrorInfoEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugErrorInfoEnumVtbl; @@ -17855,36 +17946,36 @@ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; CONST_VTBL struct ICorDebugErrorInfoEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugErrorInfoEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugErrorInfoEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugErrorInfoEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugErrorInfoEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugErrorInfoEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugErrorInfoEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugErrorInfoEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugErrorInfoEnum_Next(This,celt,errors,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,errors,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,errors,pceltFetched) ) #endif /* COBJMACROS */ @@ -17901,64 +17992,64 @@ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; #define __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ /* interface ICorDebugAppDomainEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("63ca1b24-4359-4883-bd57-13f815f58744") ICorDebugAppDomainEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAppDomainEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomainEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomainEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomainEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugAppDomainEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugAppDomainEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugAppDomainEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugAppDomainEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugAppDomainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugAppDomainEnumVtbl; @@ -17967,36 +18058,36 @@ EXTERN_C const IID IID_ICorDebugAppDomainEnum; CONST_VTBL struct ICorDebugAppDomainEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAppDomainEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomainEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomainEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomainEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugAppDomainEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugAppDomainEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugAppDomainEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugAppDomainEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18013,64 +18104,64 @@ EXTERN_C const IID IID_ICorDebugAppDomainEnum; #define __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ /* interface ICorDebugAssemblyEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssemblyEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83") ICorDebugAssemblyEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugAssemblyEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssemblyEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssemblyEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssemblyEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugAssemblyEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugAssemblyEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugAssemblyEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugAssemblyEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugAssemblyEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugAssemblyEnumVtbl; @@ -18079,36 +18170,36 @@ EXTERN_C const IID IID_ICorDebugAssemblyEnum; CONST_VTBL struct ICorDebugAssemblyEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugAssemblyEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssemblyEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssemblyEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssemblyEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugAssemblyEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugAssemblyEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugAssemblyEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugAssemblyEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18125,64 +18216,64 @@ EXTERN_C const IID IID_ICorDebugAssemblyEnum; #define __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ /* interface ICorDebugBlockingObjectEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("976A6278-134A-4a81-81A3-8F277943F4C3") ICorDebugBlockingObjectEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugBlockingObjectEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBlockingObjectEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBlockingObjectEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBlockingObjectEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugBlockingObjectEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugBlockingObjectEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugBlockingObjectEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugBlockingObjectEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugBlockingObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugBlockingObjectEnumVtbl; @@ -18191,36 +18282,36 @@ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; CONST_VTBL struct ICorDebugBlockingObjectEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugBlockingObjectEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBlockingObjectEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBlockingObjectEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBlockingObjectEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugBlockingObjectEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugBlockingObjectEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugBlockingObjectEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugBlockingObjectEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18233,23 +18324,23 @@ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; #endif /* __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0129 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0130 */ +/* [local] */ #pragma warning(push) #pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0129_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0129_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0130_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0130_v0_0_s_ifspec; #ifndef __ICorDebugMDA_INTERFACE_DEFINED__ #define __ICorDebugMDA_INTERFACE_DEFINED__ /* interface ICorDebugMDA */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ -typedef +typedef enum CorDebugMDAFlags { MDA_FLAG_SLIP = 0x2 @@ -18259,79 +18350,79 @@ enum CorDebugMDAFlags EXTERN_C const IID IID_ICorDebugMDA; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("CC726F2F-1DB7-459b-B0EC-05F01D841B42") ICorDebugMDA : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetName( + virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetDescription( + + virtual HRESULT STDMETHODCALLTYPE GetDescription( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetXML( + + virtual HRESULT STDMETHODCALLTYPE GetXML( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetFlags( + + virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [in] */ CorDebugMDAFlags *pFlags) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetOSThreadId( + + virtual HRESULT STDMETHODCALLTYPE GetOSThreadId( /* [out] */ DWORD *pOsTid) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugMDAVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMDA * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMDA * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMDA * This); - - HRESULT ( STDMETHODCALLTYPE *GetName )( + + HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetDescription )( + + HRESULT ( STDMETHODCALLTYPE *GetDescription )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetXML )( + + HRESULT ( STDMETHODCALLTYPE *GetXML )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); - - HRESULT ( STDMETHODCALLTYPE *GetFlags )( + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( ICorDebugMDA * This, /* [in] */ CorDebugMDAFlags *pFlags); - - HRESULT ( STDMETHODCALLTYPE *GetOSThreadId )( + + HRESULT ( STDMETHODCALLTYPE *GetOSThreadId )( ICorDebugMDA * This, /* [out] */ DWORD *pOsTid); - + END_INTERFACE } ICorDebugMDAVtbl; @@ -18340,35 +18431,35 @@ EXTERN_C const IID IID_ICorDebugMDA; CONST_VTBL struct ICorDebugMDAVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugMDA_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMDA_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMDA_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMDA_GetName(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetDescription(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetDescription(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetDescription(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetXML(This,cchName,pcchName,szName) \ - ( (This)->lpVtbl -> GetXML(This,cchName,pcchName,szName) ) + ( (This)->lpVtbl -> GetXML(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetFlags(This,pFlags) \ - ( (This)->lpVtbl -> GetFlags(This,pFlags) ) + ( (This)->lpVtbl -> GetFlags(This,pFlags) ) #define ICorDebugMDA_GetOSThreadId(This,pOsTid) \ - ( (This)->lpVtbl -> GetOSThreadId(This,pOsTid) ) + ( (This)->lpVtbl -> GetOSThreadId(This,pOsTid) ) #endif /* COBJMACROS */ @@ -18381,85 +18472,85 @@ EXTERN_C const IID IID_ICorDebugMDA; #endif /* __ICorDebugMDA_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0130 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0131 */ +/* [local] */ #pragma warning(pop) #pragma warning(push) -#pragma warning(disable:28718) +#pragma warning(disable:28718) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0130_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0130_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_s_ifspec; #ifndef __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ #define __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ /* interface ICorDebugEditAndContinueErrorInfo */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("8D600D41-F4F6-4cb3-B7EC-7BD164944036") ICorDebugEditAndContinueErrorInfo : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE GetModule( + virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetToken( + + virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdToken *pToken) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetErrorCode( + + virtual HRESULT STDMETHODCALLTYPE GetErrorCode( /* [out] */ HRESULT *pHr) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetString( + + virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEditAndContinueErrorInfoVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEditAndContinueErrorInfo * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEditAndContinueErrorInfo * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEditAndContinueErrorInfo * This); - - HRESULT ( STDMETHODCALLTYPE *GetModule )( + + HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ ICorDebugModule **ppModule); - - HRESULT ( STDMETHODCALLTYPE *GetToken )( + + HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ mdToken *pToken); - - HRESULT ( STDMETHODCALLTYPE *GetErrorCode )( + + HRESULT ( STDMETHODCALLTYPE *GetErrorCode )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ HRESULT *pHr); - - HRESULT ( STDMETHODCALLTYPE *GetString )( + + HRESULT ( STDMETHODCALLTYPE *GetString )( ICorDebugEditAndContinueErrorInfo * This, /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]); - + END_INTERFACE } ICorDebugEditAndContinueErrorInfoVtbl; @@ -18468,32 +18559,32 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; CONST_VTBL struct ICorDebugEditAndContinueErrorInfoVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEditAndContinueErrorInfo_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEditAndContinueErrorInfo_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEditAndContinueErrorInfo_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEditAndContinueErrorInfo_GetModule(This,ppModule) \ - ( (This)->lpVtbl -> GetModule(This,ppModule) ) + ( (This)->lpVtbl -> GetModule(This,ppModule) ) #define ICorDebugEditAndContinueErrorInfo_GetToken(This,pToken) \ - ( (This)->lpVtbl -> GetToken(This,pToken) ) + ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ICorDebugEditAndContinueErrorInfo_GetErrorCode(This,pHr) \ - ( (This)->lpVtbl -> GetErrorCode(This,pHr) ) + ( (This)->lpVtbl -> GetErrorCode(This,pHr) ) #define ICorDebugEditAndContinueErrorInfo_GetString(This,cchString,pcchString,szString) \ - ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) + ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) #endif /* COBJMACROS */ @@ -18506,106 +18597,106 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; #endif /* __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_cordebug_0000_0131 */ -/* [local] */ +/* interface __MIDL_itf_cordebug_0000_0132 */ +/* [local] */ #pragma warning(pop) -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0132_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0132_v0_0_s_ifspec; #ifndef __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ #define __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ /* interface ICorDebugEditAndContinueSnapshot */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("6DC3FA01-D7CB-11d2-8A95-0080C792E5D8") ICorDebugEditAndContinueSnapshot : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE CopyMetaData( + virtual HRESULT STDMETHODCALLTYPE CopyMetaData( /* [in] */ IStream *pIStream, /* [out] */ GUID *pMvid) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetMvid( + + virtual HRESULT STDMETHODCALLTYPE GetMvid( /* [out] */ GUID *pMvid) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRoDataRVA( + + virtual HRESULT STDMETHODCALLTYPE GetRoDataRVA( /* [out] */ ULONG32 *pRoDataRVA) = 0; - - virtual HRESULT STDMETHODCALLTYPE GetRwDataRVA( + + virtual HRESULT STDMETHODCALLTYPE GetRwDataRVA( /* [out] */ ULONG32 *pRwDataRVA) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetPEBytes( + + virtual HRESULT STDMETHODCALLTYPE SetPEBytes( /* [in] */ IStream *pIStream) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetILMap( + + virtual HRESULT STDMETHODCALLTYPE SetILMap( /* [in] */ mdToken mdFunction, /* [in] */ ULONG cMapSize, /* [size_is][in] */ COR_IL_MAP map[ ]) = 0; - - virtual HRESULT STDMETHODCALLTYPE SetPESymbolBytes( + + virtual HRESULT STDMETHODCALLTYPE SetPESymbolBytes( /* [in] */ IStream *pIStream) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugEditAndContinueSnapshotVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEditAndContinueSnapshot * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEditAndContinueSnapshot * This); - - HRESULT ( STDMETHODCALLTYPE *CopyMetaData )( + + HRESULT ( STDMETHODCALLTYPE *CopyMetaData )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream, /* [out] */ GUID *pMvid); - - HRESULT ( STDMETHODCALLTYPE *GetMvid )( + + HRESULT ( STDMETHODCALLTYPE *GetMvid )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ GUID *pMvid); - - HRESULT ( STDMETHODCALLTYPE *GetRoDataRVA )( + + HRESULT ( STDMETHODCALLTYPE *GetRoDataRVA )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ ULONG32 *pRoDataRVA); - - HRESULT ( STDMETHODCALLTYPE *GetRwDataRVA )( + + HRESULT ( STDMETHODCALLTYPE *GetRwDataRVA )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ ULONG32 *pRwDataRVA); - - HRESULT ( STDMETHODCALLTYPE *SetPEBytes )( + + HRESULT ( STDMETHODCALLTYPE *SetPEBytes )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream); - - HRESULT ( STDMETHODCALLTYPE *SetILMap )( + + HRESULT ( STDMETHODCALLTYPE *SetILMap )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ mdToken mdFunction, /* [in] */ ULONG cMapSize, /* [size_is][in] */ COR_IL_MAP map[ ]); - - HRESULT ( STDMETHODCALLTYPE *SetPESymbolBytes )( + + HRESULT ( STDMETHODCALLTYPE *SetPESymbolBytes )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream); - + END_INTERFACE } ICorDebugEditAndContinueSnapshotVtbl; @@ -18614,41 +18705,41 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; CONST_VTBL struct ICorDebugEditAndContinueSnapshotVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugEditAndContinueSnapshot_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEditAndContinueSnapshot_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEditAndContinueSnapshot_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEditAndContinueSnapshot_CopyMetaData(This,pIStream,pMvid) \ - ( (This)->lpVtbl -> CopyMetaData(This,pIStream,pMvid) ) + ( (This)->lpVtbl -> CopyMetaData(This,pIStream,pMvid) ) #define ICorDebugEditAndContinueSnapshot_GetMvid(This,pMvid) \ - ( (This)->lpVtbl -> GetMvid(This,pMvid) ) + ( (This)->lpVtbl -> GetMvid(This,pMvid) ) #define ICorDebugEditAndContinueSnapshot_GetRoDataRVA(This,pRoDataRVA) \ - ( (This)->lpVtbl -> GetRoDataRVA(This,pRoDataRVA) ) + ( (This)->lpVtbl -> GetRoDataRVA(This,pRoDataRVA) ) #define ICorDebugEditAndContinueSnapshot_GetRwDataRVA(This,pRwDataRVA) \ - ( (This)->lpVtbl -> GetRwDataRVA(This,pRwDataRVA) ) + ( (This)->lpVtbl -> GetRwDataRVA(This,pRwDataRVA) ) #define ICorDebugEditAndContinueSnapshot_SetPEBytes(This,pIStream) \ - ( (This)->lpVtbl -> SetPEBytes(This,pIStream) ) + ( (This)->lpVtbl -> SetPEBytes(This,pIStream) ) #define ICorDebugEditAndContinueSnapshot_SetILMap(This,mdFunction,cMapSize,map) \ - ( (This)->lpVtbl -> SetILMap(This,mdFunction,cMapSize,map) ) + ( (This)->lpVtbl -> SetILMap(This,mdFunction,cMapSize,map) ) #define ICorDebugEditAndContinueSnapshot_SetPESymbolBytes(This,pIStream) \ - ( (This)->lpVtbl -> SetPESymbolBytes(This,pIStream) ) + ( (This)->lpVtbl -> SetPESymbolBytes(This,pIStream) ) #endif /* COBJMACROS */ @@ -18665,64 +18756,64 @@ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; #define __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ /* interface ICorDebugExceptionObjectCallStackEnum */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("ED775530-4DC4-41F7-86D0-9E2DEF7DFC66") ICorDebugExceptionObjectCallStackEnum : public ICorDebugEnum { public: - virtual HRESULT STDMETHODCALLTYPE Next( + virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], /* [out] */ ULONG *pceltFetched) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugExceptionObjectCallStackEnumVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionObjectCallStackEnum * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionObjectCallStackEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Skip )( + + HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ ULONG celt); - - HRESULT ( STDMETHODCALLTYPE *Reset )( + + HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugExceptionObjectCallStackEnum * This); - - HRESULT ( STDMETHODCALLTYPE *Clone )( + + HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugExceptionObjectCallStackEnum * This, /* [out] */ ICorDebugEnum **ppEnum); - - HRESULT ( STDMETHODCALLTYPE *GetCount )( + + HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugExceptionObjectCallStackEnum * This, /* [out] */ ULONG *pcelt); - - HRESULT ( STDMETHODCALLTYPE *Next )( + + HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], /* [out] */ ULONG *pceltFetched); - + END_INTERFACE } ICorDebugExceptionObjectCallStackEnumVtbl; @@ -18731,36 +18822,36 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; CONST_VTBL struct ICorDebugExceptionObjectCallStackEnumVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugExceptionObjectCallStackEnum_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionObjectCallStackEnum_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionObjectCallStackEnum_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionObjectCallStackEnum_Skip(This,celt) \ - ( (This)->lpVtbl -> Skip(This,celt) ) + ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugExceptionObjectCallStackEnum_Reset(This) \ - ( (This)->lpVtbl -> Reset(This) ) + ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugExceptionObjectCallStackEnum_Clone(This,ppEnum) \ - ( (This)->lpVtbl -> Clone(This,ppEnum) ) + ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugExceptionObjectCallStackEnum_GetCount(This,pcelt) \ - ( (This)->lpVtbl -> GetCount(This,pcelt) ) + ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugExceptionObjectCallStackEnum_Next(This,celt,values,pceltFetched) \ - ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ @@ -18777,45 +18868,45 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; #define __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugExceptionObjectValue */ -/* [unique][uuid][local][object] */ +/* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) - + MIDL_INTERFACE("AE4CA65D-59DD-42A2-83A5-57E8A08D8719") ICorDebugExceptionObjectValue : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE EnumerateExceptionCallStack( + virtual HRESULT STDMETHODCALLTYPE EnumerateExceptionCallStack( /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum) = 0; - + }; - - + + #else /* C style interface */ typedef struct ICorDebugExceptionObjectValueVtbl { BEGIN_INTERFACE - - HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionObjectValue * This, /* [in] */ REFIID riid, - /* [annotation][iid_is][out] */ + /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); - - ULONG ( STDMETHODCALLTYPE *AddRef )( + + ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionObjectValue * This); - - ULONG ( STDMETHODCALLTYPE *Release )( + + ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionObjectValue * This); - - HRESULT ( STDMETHODCALLTYPE *EnumerateExceptionCallStack )( + + HRESULT ( STDMETHODCALLTYPE *EnumerateExceptionCallStack )( ICorDebugExceptionObjectValue * This, /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum); - + END_INTERFACE } ICorDebugExceptionObjectValueVtbl; @@ -18824,23 +18915,23 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; CONST_VTBL struct ICorDebugExceptionObjectValueVtbl *lpVtbl; }; - + #ifdef COBJMACROS #define ICorDebugExceptionObjectValue_QueryInterface(This,riid,ppvObject) \ - ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionObjectValue_AddRef(This) \ - ( (This)->lpVtbl -> AddRef(This) ) + ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionObjectValue_Release(This) \ - ( (This)->lpVtbl -> Release(This) ) + ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionObjectValue_EnumerateExceptionCallStack(This,ppCallStackEnum) \ - ( (This)->lpVtbl -> EnumerateExceptionCallStack(This,ppCallStackEnum) ) + ( (This)->lpVtbl -> EnumerateExceptionCallStack(This,ppCallStackEnum) ) #endif /* COBJMACROS */ @@ -18858,7 +18949,7 @@ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; #define __CORDBLib_LIBRARY_DEFINED__ /* library CORDBLib */ -/* [helpstring][version][uuid] */ +/* [helpstring][version][uuid] */ @@ -18919,5 +19010,3 @@ EmbeddedCLRCorDebug; #endif #endif - - diff --git a/src/coreclr/pal/src/arch/arm64/context2.S b/src/coreclr/pal/src/arch/arm64/context2.S index 2ebce4b440048e..12e5acf305cfd9 100644 --- a/src/coreclr/pal/src/arch/arm64/context2.S +++ b/src/coreclr/pal/src/arch/arm64/context2.S @@ -204,12 +204,11 @@ LOCAL_LABEL(No_Restore_CONTEXT_INTEGER): ldr w17, [x16, CONTEXT_Cpsr] msr nzcv, x17 ldp fp, lr, [x16, CONTEXT_Fp] - ldr x17, [x16, CONTEXT_Sp] - mov sp, x17 - ldr x17, [x16, CONTEXT_Pc] + ldp x16, x17, [x16, CONTEXT_Sp] // Context_Pc is right after Context_Sp + mov sp, x16 br x17 LOCAL_LABEL(No_Restore_CONTEXT_CONTROL): - ret + ret LEAF_END RtlRestoreContext, _TEXT diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp index e5aebdf652c6a5..eca89e0a204c64 100644 --- a/src/coreclr/pal/src/exception/machexception.cpp +++ b/src/coreclr/pal/src/exception/machexception.cpp @@ -369,19 +369,13 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE { CPalThread *pThread = InternalGetCurrentThread(); - CONTEXT *contextRecord; - EXCEPTION_RECORD *exceptionRecord; - AllocateExceptionRecords(&exceptionRecord, &contextRecord); + CONTEXT *contextRecord = pContext; + g_hardware_exception_context_locvar_offset = (int)((char*)&contextRecord - (char*)__builtin_frame_address(0)); - *contextRecord = *pContext; - *exceptionRecord = *pExRecord; - - contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; + pContext->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; bool continueExecution; - { - // The exception object takes ownership of the exceptionRecord and contextRecord - PAL_SEHException exception(exceptionRecord, contextRecord); + PAL_SEHException exception(pExRecord, pContext, true); TRACE("PAL_DispatchException(EC %08x EA %p)\n", pExRecord->ExceptionCode, pExRecord->ExceptionAddress); @@ -389,8 +383,8 @@ void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord, MachE if (continueExecution) { // Make a copy of the exception records so that we can free them before restoring the context - *pContext = *contextRecord; - *pExRecord = *exceptionRecord; + *pContext = *exception.ExceptionPointers.ContextRecord; + *pExRecord = *exception.ExceptionPointers.ExceptionRecord; } // The exception records are destroyed by the PAL_SEHException destructor now. diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index af0293ba5bc60c..b27fc9680bbedf 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -57,6 +57,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include "compact_unwind_encoding.h" +#define MACOS_ARM64_POINTER_AUTH_MASK 0x7fffffffffffull #endif // Sub-headers included from the libunwind.h contain an empty struct @@ -1422,25 +1423,56 @@ StepWithCompactNoEncoding(const libunwindInfo* info) #if defined(TARGET_ARM64) -inline static bool +#define ARM64_SYSCALL_OPCODE 0xD4001001 +#define ARM64_BL_OPCODE_MASK 0xFC000000 +#define ARM64_BL_OPCODE 0x94000000 +#define ARM64_BLR_OPCODE_MASK 0xFFFFFC00 +#define ARM64_BLR_OPCODE 0xD63F0000 +#define ARM64_BLRA_OPCODE_MASK 0xFEFFF800 +#define ARM64_BLRA_OPCODE 0xD63F0800 + +static bool +StepWithCompactNoEncoding(const libunwindInfo* info) +{ + // Check that the function is a syscall "wrapper" and assume there is no frame and pop the return address. + uint32_t opcode; + unw_word_t addr = info->Context->Pc - sizeof(opcode); + if (!ReadValue32(info, &addr, &opcode)) { + ERROR("StepWithCompactNoEncoding: can read opcode %p\n", (void*)addr); + return false; + } + // Is the IP pointing just after a "syscall" opcode? + if (opcode != ARM64_SYSCALL_OPCODE) { + ERROR("StepWithCompactNoEncoding: not in syscall wrapper function\n"); + return false; + } + // Pop the return address from the stack + info->Context->Pc = info->Context->Lr; + TRACE("StepWithCompactNoEncoding: SUCCESS new pc %p sp %p\n", (void*)info->Context->Pc, (void*)info->Context->Sp); + return true; +} + +static bool ReadCompactEncodingRegister(const libunwindInfo* info, unw_word_t* addr, DWORD64* reg) { - *addr -= sizeof(uint64_t); - if (!ReadValue64(info, addr, (uint64_t*)reg)) { + uint64_t value; + if (!info->ReadMemory((PVOID)*addr, &value, sizeof(value))) { return false; } + *reg = VAL64(value); + *addr -= sizeof(uint64_t); return true; } -inline static bool -ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, DWORD64*second, DWORD64* first) +static bool +ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, DWORD64* first, DWORD64* second) { // Registers are effectively pushed in pairs // + // *first = **addr // *addr -= 8 - // **addr = *first + // *second= **addr // *addr -= 8 - // **addr = *second if (!ReadCompactEncodingRegister(info, addr, first)) { return false; } @@ -1450,8 +1482,8 @@ ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, DWO return true; } -inline static bool -ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, NEON128*second, NEON128* first) +static bool +ReadCompactEncodingRegisterPair(const libunwindInfo* info, unw_word_t* addr, NEON128* first, NEON128* second) { if (!ReadCompactEncodingRegisterPair(info, addr, &first->Low, &second->Low)) { return false; @@ -1484,30 +1516,28 @@ static bool StepWithCompactEncodingArm64(const libunwindInfo* info, compact_unwind_encoding_t compactEncoding, bool hasFrame) { CONTEXT* context = info->Context; + unw_word_t addr; - unw_word_t callerSp; - - if (hasFrame) { - // caller Sp is callee Fp plus saved FP and LR - callerSp = context->Fp + 2 * sizeof(uint64_t); - } else { + if (hasFrame) + { + context->Sp = context->Fp + 16; + addr = context->Fp + 8; + if (!ReadCompactEncodingRegisterPair(info, &addr, &context->Lr, &context->Fp)) { + return false; + } + // Strip pointer authentication bits + context->Lr &= MACOS_ARM64_POINTER_AUTH_MASK; + } + else + { // Get the leat significant bit in UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK uint64_t stackSizeScale = UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK & ~(UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK - 1); - uint64_t stackSize = (compactEncoding & UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK) / stackSizeScale * 16; + uint64_t stackSize = ((compactEncoding & UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK) / stackSizeScale) * 16; - callerSp = context->Sp + stackSize; + addr = context->Sp + stackSize; } - context->Sp = callerSp; - - unw_word_t addr = callerSp; - - if (hasFrame && - !ReadCompactEncodingRegisterPair(info, &addr, &context->Lr, &context->Fp)) { - return false; - } - - // unwound return address is stored in Lr + // Unwound return address is stored in Lr context->Pc = context->Lr; if (compactEncoding & UNWIND_ARM64_FRAME_X19_X20_PAIR && @@ -1546,7 +1576,10 @@ StepWithCompactEncodingArm64(const libunwindInfo* info, compact_unwind_encoding_ !ReadCompactEncodingRegisterPair(info, &addr, &context->V[14], &context->V[15])) { return false; } - + if (!hasFrame) + { + context->Sp = addr; + } TRACE("SUCCESS: compact step encoding %08x pc %p sp %p fp %p lr %p\n", compactEncoding, (void*)context->Pc, (void*)context->Sp, (void*)context->Fp, (void*)context->Lr); return true; @@ -1557,11 +1590,11 @@ StepWithCompactEncodingArm64(const libunwindInfo* info, compact_unwind_encoding_ static bool StepWithCompactEncoding(const libunwindInfo* info, compact_unwind_encoding_t compactEncoding, unw_word_t functionStart) { -#if defined(TARGET_AMD64) if (compactEncoding == 0) { return StepWithCompactNoEncoding(info); } +#if defined(TARGET_AMD64) switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { case UNWIND_X86_64_MODE_RBP_FRAME: @@ -1575,11 +1608,6 @@ StepWithCompactEncoding(const libunwindInfo* info, compact_unwind_encoding_t com return false; } #elif defined(TARGET_ARM64) - if (compactEncoding == 0) - { - TRACE("Compact unwind missing for %p\n", (void*)info->Context->Pc); - return false; - } switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { case UNWIND_ARM64_MODE_FRAME: @@ -1717,6 +1745,12 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_AARCH64_X28, (unw_word_t *) &winContext->X28); unw_get_reg(cursor, UNW_AARCH64_X29, (unw_word_t *) &winContext->Fp); unw_get_reg(cursor, UNW_AARCH64_X30, (unw_word_t *) &winContext->Lr); +#ifdef __APPLE__ + // Strip pointer authentication bits which seem to be leaking out of libunwind + // Seems like ptrauth_strip() / __builtin_ptrauth_strip() should work, but currently + // errors with "this target does not support pointer authentication" + winContext->Pc = winContext->Pc & MACOS_ARM64_POINTER_AUTH_MASK; +#endif // __APPLE__ TRACE("sp %p pc %p lr %p fp %p\n", winContext->Sp, winContext->Pc, winContext->Lr, winContext->Fp); #elif defined(TARGET_S390X) unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->PSWAddr); @@ -2126,6 +2160,33 @@ PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *cont #elif defined(TARGET_ARM64) TRACE("Unwind: pc %p sp %p fp %p\n", (void*)context->Pc, (void*)context->Sp, (void*)context->Fp); result = GetProcInfo(context->Pc, &procInfo, &info, &step, false); + if (result && step) + { + // If the PC is at the start of the function, the previous instruction is BL and the unwind encoding is frameless + // with nothing on stack (0x02000000), back up PC by 1 to the previous function and get the unwind info for that + // function. + if ((context->Pc == procInfo.start_ip) && + (procInfo.format & (UNWIND_ARM64_MODE_MASK | UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK)) == UNWIND_ARM64_MODE_FRAMELESS) + { + uint32_t opcode; + unw_word_t addr = context->Pc - sizeof(opcode); + if (ReadValue32(&info, &addr, &opcode)) + { + // Is the previous instruction a BL opcode? + if ((opcode & ARM64_BL_OPCODE_MASK) == ARM64_BL_OPCODE || + (opcode & ARM64_BLR_OPCODE_MASK) == ARM64_BLR_OPCODE || + (opcode & ARM64_BLRA_OPCODE_MASK) == ARM64_BLRA_OPCODE) + { + TRACE("Unwind: getting unwind info for PC - 1 opcode %08x\n", opcode); + result = GetProcInfo(context->Pc - 1, &procInfo, &info, &step, false); + } + else + { + TRACE("Unwind: not BL* opcode %08x\n", opcode); + } + } + } + } #else #error Unexpected architecture #endif diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index 9a1f5d0b5e89d4..a9ddb179d5f822 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -476,7 +476,9 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL #ifndef HOST_WINDOWS -extern int g_common_signal_handler_context_locvar_offset; +// Frame pointer relative offset of a local containing a pointer to the windows style context of a location +// where a hardware exception occured. +int g_hardware_exception_context_locvar_offset = 0; BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers) { @@ -486,19 +488,17 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP DWORD64 curPc = CONTEXTGetPC(context); -#ifndef __APPLE__ - // Check if the PC is the return address from the SEHProcessException in the common_signal_handler. - // If that's the case, extract its local variable containing the windows style context of the hardware + // Check if the PC is the return address from the SEHProcessException. + // If that's the case, extract its local variable containing a pointer to the windows style context of the hardware // exception and return that. This skips the hardware signal handler trampoline that the libunwind - // cannot cross on some systems. + // cannot cross on some systems. On macOS, it skips a similar trampoline we create in HijackFaultingThread. if ((void*)curPc == g_SEHProcessExceptionReturnAddress) { - CONTEXT* signalContext = (CONTEXT*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); - memcpy_s(context, sizeof(CONTEXT), signalContext, sizeof(CONTEXT)); + CONTEXT* exceptionContext = *(CONTEXT**)(CONTEXTGetFP(context) + g_hardware_exception_context_locvar_offset); + memcpy_s(context, sizeof(CONTEXT), exceptionContext, sizeof(CONTEXT)); return TRUE; } -#endif if ((context->ContextFlags & CONTEXT_EXCEPTION_ACTIVE) != 0) { diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index cbcd1cac6f226e..4d9e8582acf949 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -114,10 +114,6 @@ struct sigaction g_previous_sigabrt; #if !HAVE_MACH_EXCEPTIONS -// Offset of the local variable containing pointer to windows style context in the common_signal_handler function. -// This offset is relative to the frame pointer. -int g_common_signal_handler_context_locvar_offset = 0; - // TOP of special stack for handling stack overflow volatile void* g_stackOverflowHandlerStack = NULL; @@ -845,6 +841,15 @@ PAL_ERROR InjectActivationInternal(CorUnix::CPalThread* pThread) // We can get EAGAIN when printing stack overflow stack trace and when other threads hit // stack overflow too. Those are held in the sigsegv_handler with blocked signals until // the process exits. + +#ifdef __APPLE__ + // On Apple, pthread_kill is not allowed to be sent to dispatch queue threads + if (status == ENOTSUP) + { + return ERROR_NOT_SUPPORTED; + } +#endif + if ((status != 0) && (status != EAGAIN)) { // Failure to send the signal is fatal. There are only two cases when sending @@ -922,11 +927,12 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext #if !HAVE_MACH_EXCEPTIONS sigset_t signal_set; CONTEXT signalContextRecord; + CONTEXT* signalContextRecordPtr = &signalContextRecord; EXCEPTION_RECORD exceptionRecord; native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; - g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0)); + g_hardware_exception_context_locvar_offset = (int)((char*)&signalContextRecordPtr - (char*)__builtin_frame_address(0)); if (code == (SIGSEGV | StackOverflowFlag)) { diff --git a/src/coreclr/pal/src/include/pal/mutex.hpp b/src/coreclr/pal/src/include/pal/mutex.hpp index 8aeaf9f62586ed..8a70fd6c7cd418 100644 --- a/src/coreclr/pal/src/include/pal/mutex.hpp +++ b/src/coreclr/pal/src/include/pal/mutex.hpp @@ -120,9 +120,16 @@ Miscellaneous existing shared memory, naming, and waiting infrastructure is not suitable for this purpose, and is not used. */ -// Temporarily disabling usage of pthread process-shared mutexes on ARM/ARM64 due to functional issues that cannot easily be -// detected with code due to hangs. See https://github.com/dotnet/runtime/issues/6014. -#if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && !(defined(HOST_ARM) || defined(HOST_ARM64) || defined(__FreeBSD__)) +// - Temporarily disabling usage of pthread process-shared mutexes on ARM/ARM64 due to functional issues that cannot easily be +// detected with code due to hangs. See https://github.com/dotnet/runtime/issues/6014. +// - On FreeBSD, pthread process-shared robust mutexes cannot be placed in shared memory mapped independently by the processes +// involved. See https://github.com/dotnet/runtime/issues/10519. +// - On OSX, pthread robust mutexes were/are not available at the time of this writing. In case they are made available in the +// future, their use is disabled for compatibility. +#if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && \ + HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && \ + !(defined(HOST_ARM) || defined(HOST_ARM64) || defined(__FreeBSD__) || defined(TARGET_OSX)) + #define NAMED_MUTEX_USE_PTHREAD_MUTEX 1 #else #define NAMED_MUTEX_USE_PTHREAD_MUTEX 0 diff --git a/src/coreclr/pal/src/include/pal/seh.hpp b/src/coreclr/pal/src/include/pal/seh.hpp index 6ad89df0fdd650..327fe0d7fb03e2 100644 --- a/src/coreclr/pal/src/include/pal/seh.hpp +++ b/src/coreclr/pal/src/include/pal/seh.hpp @@ -145,5 +145,10 @@ CorUnix::PAL_ERROR SEHDisable(CorUnix::CPalThread *pthrCurrent); } +// Offset of the local variable containing pointer to windows style context in the common_signal_handler / PAL_DispatchException function. +// This offset is relative to the frame pointer. +extern int g_hardware_exception_context_locvar_offset; + + #endif /* _PAL_SEH_HPP_ */ diff --git a/src/coreclr/pal/src/include/pal/sharedmemory.h b/src/coreclr/pal/src/include/pal/sharedmemory.h index 1ded94e12fcc59..c6e5abe97c3a78 100644 --- a/src/coreclr/pal/src/include/pal/sharedmemory.h +++ b/src/coreclr/pal/src/include/pal/sharedmemory.h @@ -173,7 +173,8 @@ class SharedMemorySharedDataHeader }; public: - static SIZE_T DetermineTotalByteCount(SIZE_T dataByteCount); + static SIZE_T GetUsedByteCount(SIZE_T dataByteCount); + static SIZE_T GetTotalByteCount(SIZE_T dataByteCount); public: SharedMemorySharedDataHeader(SharedMemoryType type, UINT8 version); diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 4c946cc5257b74..b1d7b3b6830459 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -519,9 +519,14 @@ bool SharedMemoryId::AppendSessionDirectoryName(PathCharString& path) const //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SharedMemorySharedDataHeader -SIZE_T SharedMemorySharedDataHeader::DetermineTotalByteCount(SIZE_T dataByteCount) +SIZE_T SharedMemorySharedDataHeader::GetUsedByteCount(SIZE_T dataByteCount) { - return SharedMemoryHelpers::AlignUp(sizeof(SharedMemorySharedDataHeader) + dataByteCount, GetVirtualPageSize()); + return sizeof(SharedMemorySharedDataHeader) + dataByteCount; +} + +SIZE_T SharedMemorySharedDataHeader::GetTotalByteCount(SIZE_T dataByteCount) +{ + return SharedMemoryHelpers::AlignUp(GetUsedByteCount(dataByteCount), GetVirtualPageSize()); } SharedMemorySharedDataHeader::SharedMemorySharedDataHeader(SharedMemoryType type, UINT8 version) @@ -642,7 +647,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( { _ASSERTE( processDataHeader->GetSharedDataTotalByteCount() == - SharedMemorySharedDataHeader::DetermineTotalByteCount(sharedDataByteCount)); + SharedMemorySharedDataHeader::GetTotalByteCount(sharedDataByteCount)); processDataHeader->IncRefCount(); return processDataHeader; } @@ -697,14 +702,23 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( } // Set or validate the file length - SIZE_T sharedDataTotalByteCount = SharedMemorySharedDataHeader::DetermineTotalByteCount(sharedDataByteCount); + SIZE_T sharedDataUsedByteCount = SharedMemorySharedDataHeader::GetUsedByteCount(sharedDataByteCount); + SIZE_T sharedDataTotalByteCount = SharedMemorySharedDataHeader::GetTotalByteCount(sharedDataByteCount); if (createdFile) { SharedMemoryHelpers::SetFileSize(fileDescriptor, sharedDataTotalByteCount); } - else if (SharedMemoryHelpers::GetFileSize(fileDescriptor) != sharedDataTotalByteCount) + else { - throw SharedMemoryException(static_cast(SharedMemoryError::HeaderMismatch)); + SIZE_T currentFileSize = SharedMemoryHelpers::GetFileSize(fileDescriptor); + if (currentFileSize < sharedDataUsedByteCount) + { + throw SharedMemoryException(static_cast(SharedMemoryError::HeaderMismatch)); + } + if (currentFileSize < sharedDataTotalByteCount) + { + SharedMemoryHelpers::SetFileSize(fileDescriptor, sharedDataTotalByteCount); + } } // Acquire and hold a shared file lock on the shared memory file as long as it is open, to indicate that this process is @@ -726,7 +740,7 @@ SharedMemoryProcessDataHeader *SharedMemoryProcessDataHeader::CreateOrOpen( { if (clearContents) { - memset(mappedBuffer, 0, sharedDataTotalByteCount); + memset(mappedBuffer, 0, sharedDataUsedByteCount); } sharedDataHeader = new(mappedBuffer) SharedMemorySharedDataHeader(requiredSharedDataHeader); } diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 0ae3f2eecafd05..f31449fb19c3e8 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -85,7 +85,6 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d #include #include #include -#if defined(HOST_ARM64) #include #include extern "C" @@ -103,7 +102,6 @@ extern "C" } \ } while (false) -#endif // defined(HOST_ARM64) #endif // __APPLE__ #ifdef __NetBSD__ @@ -3124,10 +3122,9 @@ PROCBuildCreateDumpCommandLine( std::vector& argv, char** pprogram, char** ppidarg, - char* dumpName, - char* dumpType, - BOOL diag, - BOOL crashReport) + const char* dumpName, + const char* dumpType, + ULONG32 flags) { if (g_szCoreCLRPath == nullptr) { @@ -3190,12 +3187,17 @@ PROCBuildCreateDumpCommandLine( } } - if (diag) + if (flags & GenerateDumpFlagsLoggingEnabled) { argv.push_back("--diag"); } - if (crashReport) + if (flags & GenerateDumpFlagsVerboseLoggingEnabled) + { + argv.push_back("--verbose"); + } + + if (flags & GenerateDumpFlagsCrashReportEnabled) { argv.push_back("--crashreport"); } @@ -3286,10 +3288,18 @@ PROCAbortInitialize() BOOL diag = diagStr != nullptr && strcmp(diagStr, "1") == 0; char* crashReportStr = getenv("COMPlus_EnableCrashReport"); BOOL crashReport = crashReportStr != nullptr && strcmp(crashReportStr, "1") == 0; - + ULONG32 flags = GenerateDumpFlagsNone; + if (diag) + { + flags |= GenerateDumpFlagsLoggingEnabled; + } + if (crashReport) + { + flags |= GenerateDumpFlagsCrashReportEnabled; + } char* program = nullptr; char* pidarg = nullptr; - if (!PROCBuildCreateDumpCommandLine(g_argvCreateDump, &program, &pidarg, dumpName, dumpType, diag, crashReport)) + if (!PROCBuildCreateDumpCommandLine(g_argvCreateDump, &program, &pidarg, dumpName, dumpType, flags)) { return FALSE; } @@ -3311,8 +3321,8 @@ PROCAbortInitialize() WithHeap = 2, Triage = 3, Full = 4 - diag - true - log createdump diagnostics to console + flags + See enum Return: TRUE success @@ -3322,7 +3332,7 @@ BOOL PAL_GenerateCoreDump( LPCSTR dumpName, INT dumpType, - BOOL diag) + ULONG32 flags) { std::vector argvCreateDump; char dumpTypeStr[16]; @@ -3341,7 +3351,7 @@ PAL_GenerateCoreDump( } char* program = nullptr; char* pidarg = nullptr; - BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, (char*)dumpName, dumpTypeStr, diag, false); + BOOL result = PROCBuildCreateDumpCommandLine(argvCreateDump, &program, &pidarg, dumpName, dumpTypeStr, flags); if (result) { result = PROCCreateCrashDump(argvCreateDump); @@ -3460,7 +3470,7 @@ InitializeFlushProcessWriteBuffers() } } -#if defined(TARGET_OSX) && defined(HOST_ARM64) +#ifdef TARGET_OSX return TRUE; #else s_helperPage = static_cast(mmap(0, GetVirtualPageSize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); @@ -3490,7 +3500,7 @@ InitializeFlushProcessWriteBuffers() } return status == 0; -#endif // defined(TARGET_OSX) && defined(HOST_ARM64) +#endif // TARGET_OSX } #define FATAL_ASSERT(e, msg) \ @@ -3540,7 +3550,7 @@ FlushProcessWriteBuffers() status = pthread_mutex_unlock(&flushProcessWriteBuffersMutex); FATAL_ASSERT(status == 0, "Failed to unlock the flushProcessWriteBuffersMutex lock"); } -#if defined(TARGET_OSX) && defined(HOST_ARM64) +#ifdef TARGET_OSX else { mach_msg_type_number_t cThreads; @@ -3566,7 +3576,7 @@ FlushProcessWriteBuffers() machret = vm_deallocate(mach_task_self(), (vm_address_t)pThreads, cThreads * sizeof(thread_act_t)); CHECK_MACH("vm_deallocate()", machret); } -#endif // defined(TARGET_OSX) && defined(HOST_ARM64) +#endif // TARGET_OSX } /*++ diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index db9eb3f137a588..6fd7ca33bfb8db 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2549,10 +2549,25 @@ static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_FLAGS* f } } + [UnmanagedCallersOnly] + static byte _doesFieldBelongToClass(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* fldHnd, CORINFO_CLASS_STRUCT_* cls) + { + var _this = GetThis(thisHandle); + try + { + return _this.doesFieldBelongToClass(fldHnd, cls) ? (byte)1 : (byte)0; + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 172); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173); callbacks[0] = (delegate* unmanaged)&_isJitIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2726,6 +2741,7 @@ static IntPtr GetUnmanagedCallbacks() callbacks[169] = (delegate* unmanaged)&_getRelocTypeHint; callbacks[170] = (delegate* unmanaged)&_getExpectedTargetArchitecture; callbacks[171] = (delegate* unmanaged)&_getJitFlags; + callbacks[172] = (delegate* unmanaged)&_doesFieldBelongToClass; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index a0ccb4400f0758..7ca0194fdb11da 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -392,9 +392,9 @@ private void PublishCode() _methodCodeNode.InitializeEHInfo(ehInfo); _methodCodeNode.InitializeDebugLocInfos(_debugLocInfos); - _methodCodeNode.InitializeDebugVarInfos(_debugVarInfos); + _methodCodeNode.InitializeDebugVarInfos(_debugVarInfos, _compilation.TypeSystemContext.Target); #if READYTORUN - _methodCodeNode.InitializeInliningInfo(_inlinedMethods.ToArray()); + _methodCodeNode.InitializeInliningInfo(_inlinedMethods.ToArray(), _compilation.NodeFactory); // Detect cases where the instruction set support used is a superset of the baseline instruction set specification var baselineSupport = _compilation.InstructionSetSupport; @@ -3531,6 +3531,42 @@ private uint getExpectedTargetArchitecture() } } + private bool doesFieldBelongToClass(CORINFO_FIELD_STRUCT_* fld, CORINFO_CLASS_STRUCT_* cls) + { + var field = HandleToObject(fld); + var queryType = HandleToObject(cls); + + Debug.Assert(!field.IsStatic); + + // doesFieldBelongToClass implements the predicate of... + // if field is not associated with the class in any way, return false. + // if field is the only FieldDesc that the JIT might see for a given class handle + // and logical field pair then return true. This is needed as the field handle here + // is used as a key into a hashtable mapping writes to fields to value numbers. + // + // In this implmentation this is made more complex as the JIT is exposed to CORINFO_FIELD_STRUCT + // pointers which represent exact instantions, so performing exact matching is the necessary approach + + // BaseType._field, BaseType -> true + // BaseType._field, DerivedType -> true + // BaseType<__Canon>._field, BaseType<__Canon> -> true + // BaseType<__Canon>._field, BaseType -> false + // BaseType<__Canon>._field, BaseType -> false + // BaseType._field, BaseType -> true + // BaseType._field, BaseType -> false + + var fieldOwnerType = field.OwningType; + + while (queryType != null) + { + if (fieldOwnerType == queryType) + return true; + queryType = queryType.BaseType; + } + + return false; + } + private bool isMethodDefinedInCoreLib() { TypeDesc owningType = MethodBeingCompiled.OwningType; diff --git a/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs b/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs index 55b8e2d1dc02c8..c4105d1ce91739 100644 --- a/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs +++ b/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs @@ -158,7 +158,7 @@ private static SystemVClassificationType TypeDef2SystemVClassification(TypeDesc case TypeFlags.GenericParameter: case TypeFlags.SignatureTypeVariable: case TypeFlags.SignatureMethodVariable: - Debug.Assert(false, $"Type {typeDesc} with unexpected category {typeDesc.Category}"); + Debug.Fail($"Type {typeDesc} with unexpected category {typeDesc.Category}"); return SystemVClassificationTypeUnknown; default: return SystemVClassificationTypeUnknown; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 22e390f52858ea..da802c872bb289 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -325,4 +325,4 @@ FUNCTIONS uint16_t getRelocTypeHint(void* target) uint32_t getExpectedTargetArchitecture() uint32_t getJitFlags(CORJIT_FLAGS* flags, uint32_t sizeInBytes) - + bool doesFieldBelongToClass(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLASS_HANDLE cls) diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs index dd494b9fdcf9a8..bba40fd1df33a4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Security.Cryptography; +using Internal.ReadyToRunDiagnosticsConstants; using Internal.TypeSystem; namespace ILCompiler.Diagnostics @@ -16,14 +17,8 @@ public class PerfMapWriter public const int LegacyCrossgen1FormatVersion = 0; public const int CurrentFormatVersion = 1; - - public enum PseudoRVA : uint - { - OutputGuid = 0xFFFFFFFF, - TargetOS = 0xFFFFFFFE, - TargetArchitecture = 0xFFFFFFFD, - FormatVersion = 0xFFFFFFFC, - } + + const int HeaderEntriesPseudoLength = 0; private TextWriter _writer; @@ -32,7 +27,7 @@ private PerfMapWriter(TextWriter writer) _writer = writer; } - public static void Write(string perfMapFileName, int perfMapFormatVersion, IEnumerable methods, IEnumerable inputAssemblies, TargetOS targetOS, TargetArchitecture targetArch) + public static void Write(string perfMapFileName, int perfMapFormatVersion, IEnumerable methods, IEnumerable inputAssemblies, TargetDetails details) { if (perfMapFormatVersion > CurrentFormatVersion) { @@ -41,22 +36,10 @@ public static void Write(string perfMapFileName, int perfMapFormatVersion, IEnum using (TextWriter writer = new StreamWriter(perfMapFileName)) { - IEnumerable orderedInputs = inputAssemblies.OrderBy(asm => asm.Name, StringComparer.OrdinalIgnoreCase); PerfMapWriter perfMapWriter = new PerfMapWriter(writer); - - List inputHash = new List(); - foreach (AssemblyInfo inputAssembly in orderedInputs) - { - inputHash.AddRange(inputAssembly.Mvid.ToByteArray()); - } - inputHash.Add((byte)targetOS); - inputHash.Add((byte)targetArch); - Guid outputGuid = new Guid(MD5.HashData(inputHash.ToArray())); - perfMapWriter.WriteLine(outputGuid.ToString(), (uint)PseudoRVA.OutputGuid, 0); - perfMapWriter.WriteLine(targetOS.ToString(), (uint)PseudoRVA.TargetOS, 0); - perfMapWriter.WriteLine(targetArch.ToString(), (uint)PseudoRVA.TargetArchitecture, 0); - perfMapWriter.WriteLine(CurrentFormatVersion.ToString(), (uint)PseudoRVA.FormatVersion, 0); + byte[] signature = PerfMapV1SignatureHelper(inputAssemblies, details); + WritePerfMapV1Header(inputAssemblies, details, perfMapWriter); foreach (MethodInfo methodInfo in methods) { @@ -72,6 +55,92 @@ public static void Write(string perfMapFileName, int perfMapFormatVersion, IEnum } } + private static void WritePerfMapV1Header(IEnumerable inputAssemblies, TargetDetails details, PerfMapWriter perfMapWriter) + { + byte[] signature = PerfMapV1SignatureHelper(inputAssemblies, details); + + // Make sure these get emitted in this order, other tools in the ecosystem like the symbol uploader and PerfView rely on this. + // In particular, the order of it. Append only. + string signatureFormatted = Convert.ToHexString(signature); + + PerfmapTokensForTarget targetTokens = TranslateTargetDetailsToPerfmapConstants(details); + + perfMapWriter.WriteLine(signatureFormatted, (uint)PerfMapPseudoRVAToken.OutputSignature, HeaderEntriesPseudoLength); + perfMapWriter.WriteLine(CurrentFormatVersion.ToString(), (uint)PerfMapPseudoRVAToken.FormatVersion, HeaderEntriesPseudoLength); + perfMapWriter.WriteLine(((uint)targetTokens.OperatingSystem).ToString(), (uint)PerfMapPseudoRVAToken.TargetOS, HeaderEntriesPseudoLength); + perfMapWriter.WriteLine(((uint)targetTokens.Architecture).ToString(), (uint)PerfMapPseudoRVAToken.TargetArchitecture, HeaderEntriesPseudoLength); + perfMapWriter.WriteLine(((uint)targetTokens.Abi).ToString(), (uint)PerfMapPseudoRVAToken.TargetABI, HeaderEntriesPseudoLength); + } + + public static byte[] PerfMapV1SignatureHelper(IEnumerable inputAssemblies, TargetDetails details) + { + IEnumerable orderedInputs = inputAssemblies.OrderBy(asm => asm.Name, StringComparer.OrdinalIgnoreCase); + List inputHash = new List(); + foreach (AssemblyInfo inputAssembly in orderedInputs) + { + inputHash.AddRange(inputAssembly.Mvid.ToByteArray()); + } + + PerfmapTokensForTarget targetTokens = TranslateTargetDetailsToPerfmapConstants(details); + + byte[] buffer = new byte[12]; + if (!BitConverter.TryWriteBytes(buffer.AsSpan(0, sizeof(uint)), (uint)targetTokens.OperatingSystem) + || !BitConverter.TryWriteBytes(buffer.AsSpan(4, sizeof(uint)), (uint)targetTokens.Architecture) + || !BitConverter.TryWriteBytes(buffer.AsSpan(8, sizeof(uint)), (uint)targetTokens.Abi)) + { + throw new InvalidOperationException(); + } + + if (!BitConverter.IsLittleEndian) + { + buffer.AsSpan(0, sizeof(uint)).Reverse(); + buffer.AsSpan(4, sizeof(uint)).Reverse(); + buffer.AsSpan(8, sizeof(uint)).Reverse(); + } + + inputHash.AddRange(buffer); + byte[] hash = MD5.HashData(inputHash.ToArray()); + + return hash; + } + + internal record struct PerfmapTokensForTarget(PerfMapOSToken OperatingSystem, PerfMapArchitectureToken Architecture, PerfMapAbiToken Abi); + + private static PerfmapTokensForTarget TranslateTargetDetailsToPerfmapConstants(TargetDetails details) + { + PerfMapOSToken osToken = details.OperatingSystem switch + { + TargetOS.Unknown => PerfMapOSToken.Unknown, + TargetOS.Windows => PerfMapOSToken.Windows, + TargetOS.Linux => PerfMapOSToken.Linux, + TargetOS.OSX => PerfMapOSToken.OSX, + TargetOS.FreeBSD => PerfMapOSToken.FreeBSD, + TargetOS.NetBSD => PerfMapOSToken.NetBSD, + TargetOS.SunOS => PerfMapOSToken.SunOS, + _ => throw new NotImplementedException(details.OperatingSystem.ToString()) + }; + + PerfMapAbiToken abiToken = details.Abi switch + { + TargetAbi.Unknown => PerfMapAbiToken.Unknown, + TargetAbi.CoreRT => PerfMapAbiToken.Default, + TargetAbi.CoreRTArmel => PerfMapAbiToken.Armel, + _ => throw new NotImplementedException(details.Abi.ToString()) + }; + + PerfMapArchitectureToken archToken = details.Architecture switch + { + TargetArchitecture.Unknown => PerfMapArchitectureToken.Unknown, + TargetArchitecture.ARM => PerfMapArchitectureToken.ARM, + TargetArchitecture.ARM64 => PerfMapArchitectureToken.ARM64, + TargetArchitecture.X64 => PerfMapArchitectureToken.X64, + TargetArchitecture.X86 => PerfMapArchitectureToken.X86, + _ => throw new NotImplementedException(details.Architecture.ToString()) + }; + + return new PerfmapTokensForTarget(osToken, archToken, abiToken); + } + private void WriteLine(string methodName, uint rva, uint length) { _writer.WriteLine($@"{rva:X8} {length:X2} {methodName}"); diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs new file mode 100644 index 00000000000000..fea26f9db02897 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ReadyToRunDiagnosticsConstants.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Internal.ReadyToRunDiagnosticsConstants; + +public enum PerfMapPseudoRVAToken : uint +{ + OutputSignature = 0xFFFFFFFF, + FormatVersion = 0xFFFFFFFE, + TargetOS = 0xFFFFFFFD, + TargetArchitecture = 0xFFFFFFFC, + TargetABI = 0xFFFFFFFB, +} + +public enum PerfMapArchitectureToken : uint +{ + Unknown = 0, + ARM = 1, + ARM64 = 2, + X64 = 3, + X86 = 4, +} + +public enum PerfMapOSToken : uint +{ + Unknown = 0, + Windows = 1, + Linux = 2, + OSX = 3, + FreeBSD = 4, + NetBSD = 5, + SunOS = 6, +} + +public enum PerfMapAbiToken : uint +{ + Unknown = 0, + Default = 1, + Armel = 2, +} diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index 6404f77fbac06d..d704579efd7661 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -27,7 +27,7 @@ namespace ILCompiler.DependencyAnalysis internal class ReadyToRunObjectWriter { /// - /// Nodefactory for which ObjectWriter is instantiated for. + /// Nodefactory for which ObjectWriter is instantiated for. /// private readonly NodeFactory _nodeFactory; @@ -234,6 +234,7 @@ public void EmitPortableExecutable() peIdProvider); NativeDebugDirectoryEntryNode nativeDebugDirectoryEntryNode = null; + PerfMapDebugDirectoryEntryNode perfMapDebugDirectoryEntryNode = null; ISymbolDefinitionNode firstImportThunk = null; ISymbolDefinitionNode lastImportThunk = null; ObjectNode lastWrittenObjectNode = null; @@ -261,6 +262,13 @@ public void EmitPortableExecutable() nativeDebugDirectoryEntryNode = nddeNode; } + if (node is PerfMapDebugDirectoryEntryNode pmdeNode) + { + // There should be only one PerfMapDebugDirectoryEntryNode. + Debug.Assert(perfMapDebugDirectoryEntryNode is null); + perfMapDebugDirectoryEntryNode = pmdeNode; + } + if (node is ImportThunk importThunkNode) { Debug.Assert(firstImportThunk == null || lastWrittenObjectNode is ImportThunk, @@ -305,7 +313,7 @@ public void EmitPortableExecutable() { r2rPeBuilder.AddSymbolForRange(_nodeFactory.DelayLoadMethodCallThunks, firstImportThunk, lastImportThunk); } - + if (_nodeFactory.Win32ResourcesNode != null) { @@ -313,6 +321,14 @@ public void EmitPortableExecutable() r2rPeBuilder.SetWin32Resources(_nodeFactory.Win32ResourcesNode, _nodeFactory.Win32ResourcesNode.Size); } + if (_outputInfoBuilder != null) + { + foreach (string inputFile in _inputFiles) + { + _outputInfoBuilder.AddInputModule(_nodeFactory.TypeSystemContext.GetModuleFromPath(inputFile)); + } + } + using (var peStream = File.Create(_objectFilePath)) { r2rPeBuilder.Write(peStream, timeDateStamp); @@ -322,26 +338,36 @@ public void EmitPortableExecutable() _mapFileBuilder.SetFileSize(peStream.Length); } - // Compute MD5 hash of the output image and store that in the native DebugDirectory entry - using (var md5Hash = MD5.Create()) + if (nativeDebugDirectoryEntryNode is not null) { - peStream.Seek(0, SeekOrigin.Begin); - byte[] hash = md5Hash.ComputeHash(peStream); - byte[] rsdsEntry = nativeDebugDirectoryEntryNode.GenerateRSDSEntryData(hash); + Debug.Assert(_generatePdbFile); + // Compute MD5 hash of the output image and store that in the native DebugDirectory entry + using (var md5Hash = MD5.Create()) + { + peStream.Seek(0, SeekOrigin.Begin); + byte[] hash = md5Hash.ComputeHash(peStream); + byte[] rsdsEntry = nativeDebugDirectoryEntryNode.GenerateRSDSEntryData(hash); + + int offsetToUpdate = r2rPeBuilder.GetSymbolFilePosition(nativeDebugDirectoryEntryNode); + peStream.Seek(offsetToUpdate, SeekOrigin.Begin); + peStream.Write(rsdsEntry); + } + } + + if (perfMapDebugDirectoryEntryNode is not null) + { + Debug.Assert(_generatePerfMapFile && _outputInfoBuilder is not null && _outputInfoBuilder.EnumerateInputAssemblies().Any()); + byte[] perfmapSig = PerfMapWriter.PerfMapV1SignatureHelper(_outputInfoBuilder.EnumerateInputAssemblies(), _nodeFactory.Target); + byte[] perfMapEntry = perfMapDebugDirectoryEntryNode.GeneratePerfMapEntryData(perfmapSig, _perfMapFormatVersion); - int offsetToUpdate = r2rPeBuilder.GetSymbolFilePosition(nativeDebugDirectoryEntryNode); + int offsetToUpdate = r2rPeBuilder.GetSymbolFilePosition(perfMapDebugDirectoryEntryNode); peStream.Seek(offsetToUpdate, SeekOrigin.Begin); - peStream.Write(rsdsEntry); + peStream.Write(perfMapEntry); } } if (_outputInfoBuilder != null) { - foreach (string inputFile in _inputFiles) - { - _outputInfoBuilder.AddInputModule(_nodeFactory.TypeSystemContext.GetModuleFromPath(inputFile)); - } - r2rPeBuilder.AddSections(_outputInfoBuilder); if (_generateMapFile) @@ -374,7 +400,7 @@ public void EmitPortableExecutable() { path = Path.GetDirectoryName(_objectFilePath); } - _symbolFileBuilder.SavePerfMap(path, _perfMapFormatVersion, _objectFilePath, _nodeFactory.Target.OperatingSystem, _nodeFactory.Target.Architecture); + _symbolFileBuilder.SavePerfMap(path, _perfMapFormatVersion, _objectFilePath, _nodeFactory.Target); } if (_profileFileBuilder != null) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs index 9aa6e6bbc46099..ae6323797d2c31 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryEntryNode.cs @@ -43,6 +43,76 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer } } + public class PerfMapDebugDirectoryEntryNode : DebugDirectoryEntryNode + { + const int PerfMapEntrySize = + sizeof(uint) + // Magic + SignatureSize + // Signature + sizeof(uint) + // Age + 260; // FileName + + public const uint PerfMapMagic = 0x4D523252;// R2RM + + public const int PerfMapEntryType = 21; // DebugDirectoryEntryType for this entry. + + private const int SignatureSize = 16; + + public override int ClassCode => 813123850; + + public unsafe int Size => PerfMapEntrySize; + + public PerfMapDebugDirectoryEntryNode(string entryName) + : base(null) + { + _entryName = entryName; + } + + private string _entryName; + + public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + { + sb.Append(nameMangler.CompilationUnitPrefix); + sb.Append($"__PerfMapDebugDirectoryEntryNode_{_entryName.Replace('.','_')}"); + } + + public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) + { + ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); + builder.RequireInitialPointerAlignment(); + builder.AddSymbol(this); + + // Emit empty entry. This will be filled with data after the output image is emitted + builder.EmitZeros(PerfMapEntrySize); + + return builder.ToObjectData(); + } + + public byte[] GeneratePerfMapEntryData(byte[] signature, int version) + { + Debug.Assert(SignatureSize == signature.Length); + MemoryStream perfmapEntry = new MemoryStream(PerfMapEntrySize); + + using (BinaryWriter writer = new BinaryWriter(perfmapEntry)) + { + writer.Write(PerfMapMagic); + writer.Write(signature); + writer.Write(version); + + byte[] perfmapNameBytes = Encoding.UTF8.GetBytes(_entryName); + writer.Write(perfmapNameBytes); + writer.Write(0); // Null terminator + + Debug.Assert(perfmapEntry.Length <= PerfMapEntrySize); + return perfmapEntry.ToArray(); + } + } + + public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) + { + return _entryName.CompareTo(((PerfMapDebugDirectoryEntryNode)other)._entryName); + } + } + public class NativeDebugDirectoryEntryNode : DebugDirectoryEntryNode { const int RSDSSize = @@ -55,6 +125,8 @@ public class NativeDebugDirectoryEntryNode : DebugDirectoryEntryNode public unsafe int Size => RSDSSize; + public const uint RsdsMagic = 0x53445352;// R2RM + public NativeDebugDirectoryEntryNode(string pdbName) : base(null) { @@ -87,8 +159,7 @@ public byte[] GenerateRSDSEntryData(byte[] md5Hash) using (BinaryWriter writer = new BinaryWriter(rsdsEntry)) { - // Magic "RSDS" - writer.Write((uint)0x53445352); + writer.Write(RsdsMagic); // The PDB signature will be the same as our NGEN signature. // However we want the printed version of the GUID to be the same as the @@ -105,6 +176,7 @@ public byte[] GenerateRSDSEntryData(byte[] md5Hash) string pdbFileName = _pdbName; byte[] pdbFileNameBytes = Encoding.UTF8.GetBytes(pdbFileName); writer.Write(pdbFileNameBytes); + writer.Write(0); // Null terminator Debug.Assert(rsdsEntry.Length <= RSDSSize); return rsdsEntry.ToArray(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs index 175025449039bd..fd1fb49d25febd 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugDirectoryNode.cs @@ -1,13 +1,14 @@ // 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.Collections.Immutable; using System.Diagnostics; using System.IO; +using System.Linq; using System.Reflection.PortableExecutable; using Internal.Text; +using Internal.TypeSystem; using Internal.TypeSystem.Ecma; namespace ILCompiler.DependencyAnalysis.ReadyToRun @@ -26,9 +27,11 @@ public class DebugDirectoryNode : ObjectNode, ISymbolDefinitionNode private EcmaModule _module; private NativeDebugDirectoryEntryNode _nativeEntry; + private PerfMapDebugDirectoryEntryNode _perfMapEntry; + private bool _insertDeterministicEntry; - public DebugDirectoryNode(EcmaModule sourceModule, string outputFileName) + public DebugDirectoryNode(EcmaModule sourceModule, string outputFileName, bool shouldAddNiPdb, bool shouldGeneratePerfmap) { _module = sourceModule; _insertDeterministicEntry = sourceModule == null; // Mark module as deterministic if generating composite image @@ -37,7 +40,16 @@ public DebugDirectoryNode(EcmaModule sourceModule, string outputFileName) { pdbNameRoot = sourceModule.Assembly.GetName().Name; } - _nativeEntry = new NativeDebugDirectoryEntryNode(pdbNameRoot + ".ni.pdb"); + + if (shouldAddNiPdb) + { + _nativeEntry = new NativeDebugDirectoryEntryNode(pdbNameRoot + ".ni.pdb"); + } + + if (shouldGeneratePerfmap) + { + _perfMapEntry = new PerfMapDebugDirectoryEntryNode(pdbNameRoot + ".ni.r2rmap"); + } } public override ObjectNodeSection Section => ObjectNodeSection.TextSection; @@ -52,7 +64,10 @@ public DebugDirectoryNode(EcmaModule sourceModule, string outputFileName) public int Offset => 0; - public int Size => (GetNumDebugDirectoryEntriesInModule() + 1 + (_insertDeterministicEntry ? 1 : 0)) * ImageDebugDirectorySize; + public int Size => (GetNumDebugDirectoryEntriesInModule() + + (_nativeEntry is not null ? 1 : 0) + + (_perfMapEntry is not null ? 1 : 0) + + (_insertDeterministicEntry ? 1 : 0)) * ImageDebugDirectorySize; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -83,27 +98,23 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); - ImmutableArray entries = default(ImmutableArray); + ImmutableArray entries = ImmutableArray.Empty; if (_module != null) entries = _module.PEReader.ReadDebugDirectory(); int numEntries = GetNumDebugDirectoryEntriesInModule(); + // Reuse the module's PDB entry + DebugDirectoryEntry pdbEntry = entries.Where(s => s.Type == DebugDirectoryEntryType.CodeView).FirstOrDefault(); + // First, write the native debug directory entry + if (_nativeEntry is not null) { var entry = _nativeEntry; builder.EmitUInt(0 /* Characteristics */); - if (numEntries > 0) - { - builder.EmitUInt(entries[0].Stamp); - builder.EmitUShort(entries[0].MajorVersion); - } - else - { - builder.EmitUInt(0); - builder.EmitUShort(0); - } + builder.EmitUInt(pdbEntry.Stamp); + builder.EmitUShort(pdbEntry.MajorVersion); // Make sure the "is portable pdb" indicator (MinorVersion == 0x504d) is clear // for the NGen debug directory entry since this debug directory can be copied // from an existing entry which could be a portable pdb. @@ -114,6 +125,21 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) builder.EmitReloc(entry, RelocType.IMAGE_REL_FILE_ABSOLUTE); } + // Second emit a record for the perfmap + if (_perfMapEntry is not null) + { + var entry = _perfMapEntry; + + builder.EmitUInt(0); /* Characteristics */ + builder.EmitUInt(0); /* Stamp */ + builder.EmitUShort(1); /* Major */ + builder.EmitUShort(0); /* Minor */ + builder.EmitInt((int)PerfMapDebugDirectoryEntryNode.PerfMapEntryType); + builder.EmitInt(entry.Size); + builder.EmitReloc(entry, RelocType.IMAGE_REL_BASED_ADDR32NB); + builder.EmitReloc(entry, RelocType.IMAGE_REL_FILE_ABSOLUTE); + } + // If generating a composite image, emit the deterministic marker if (_insertDeterministicEntry) { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs index fd628b637a17f9..24f5409a318f90 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/DebugInfoTableNode.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using Internal.JitInterface; @@ -149,11 +150,13 @@ public static byte[] CreateBoundsBlobForMethod(OffsetMapping[] offsetMapping) return writer.ToArray(); } - public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos) + public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos, TargetDetails target) { if (varInfos == null || varInfos.Length == 0) return null; + bool isX86 = target.Architecture == TargetArchitecture.X86; + NibbleWriter writer = new NibbleWriter(); writer.WriteUInt((uint)varInfos.Length); @@ -177,7 +180,7 @@ public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos) case VarLocType.VLT_STK: case VarLocType.VLT_STK_BYREF: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); - writer.WriteInt(nativeVarInfo.varLoc.C); + WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.C, assume4ByteAligned : isX86); break; case VarLocType.VLT_REG_REG: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); @@ -186,16 +189,16 @@ public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos) case VarLocType.VLT_REG_STK: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); - writer.WriteInt(nativeVarInfo.varLoc.D); + WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.D, assume4ByteAligned : isX86); break; case VarLocType.VLT_STK_REG: - writer.WriteInt(nativeVarInfo.varLoc.B); + WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.B, assume4ByteAligned : isX86); writer.WriteUInt((uint)nativeVarInfo.varLoc.C); writer.WriteUInt((uint)nativeVarInfo.varLoc.D); break; case VarLocType.VLT_STK2: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); - writer.WriteInt(nativeVarInfo.varLoc.C); + WriteEncodedStackOffset(writer, nativeVarInfo.varLoc.C, assume4ByteAligned : isX86); break; case VarLocType.VLT_FPSTK: writer.WriteUInt((uint)nativeVarInfo.varLoc.B); @@ -206,6 +209,19 @@ public static byte[] CreateVarBlobForMethod(NativeVarInfo[] varInfos) default: throw new BadImageFormatException("Unexpected var loc type"); } + + static void WriteEncodedStackOffset(NibbleWriter _writer, int offset, bool assume4ByteAligned) + { + if (assume4ByteAligned) + { + Debug.Assert(offset % 4 == 0); + _writer.WriteInt(offset / 4); + } + else + { + _writer.WriteInt(offset); + } + } } return writer.ToArray(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs index 548abb4d8a5e99..c63e589328b305 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs @@ -17,22 +17,58 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun { - public class InstanceEntryPointTableNode : HeaderTableNode + public class InstanceEntryPointTableNode : HeaderTableNode, ISignatureEmitter { private readonly NodeFactory _factory; + private bool _materializedSignature; public InstanceEntryPointTableNode(NodeFactory factory) : base(factory.Target) { _factory = factory; + _factory.ManifestMetadataTable.RegisterEmitter(this); } - + + public void MaterializeSignature() + { + if (!_materializedSignature) + { + if (_factory.CompilationModuleGroup.IsInputBubble) + { + foreach (MethodWithGCInfo method in _factory.EnumerateCompiledMethods(null, CompiledMethodCategory.Instantiated)) + { + BuildSignatureForMethod(method, _factory); + } + } + + _materializedSignature = true; + } + } + public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix); sb.Append("__ReadyToRunInstanceEntryPointTable"); } + private ArraySignatureBuilder BuildSignatureForMethod(MethodWithGCInfo method, NodeFactory factory) + { + // In composite R2R format, always enforce owning type to let us share generic instantiations among modules + + EcmaMethod typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition(); + ModuleToken moduleToken = new ModuleToken(typicalMethod.Module, typicalMethod.Handle); + + ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder(); + signatureBuilder.EmitMethodSignature( + new MethodWithToken(method.Method, moduleToken, constrainedType: null, unboxing: false, context: null), + enforceDefEncoding: true, + enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module), + factory.SignatureContext, + isInstantiatingStub: false); + + return signatureBuilder; + } + public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { if (relocsOnly) @@ -55,17 +91,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) int methodIndex = factory.RuntimeFunctionsTable.GetIndex(method); - // In composite R2R format, always enforce owning type to let us share generic instantiations among modules - EcmaMethod typicalMethod = (EcmaMethod)method.Method.GetTypicalMethodDefinition(); - ModuleToken moduleToken = new ModuleToken(typicalMethod.Module, typicalMethod.Handle); - - ArraySignatureBuilder signatureBuilder = new ArraySignatureBuilder(); - signatureBuilder.EmitMethodSignature( - new MethodWithToken(method.Method, moduleToken, constrainedType: null, unboxing: false, context: null), - enforceDefEncoding: true, - enforceOwningType: _factory.CompilationModuleGroup.EnforceOwningType(moduleToken.Module), - factory.SignatureContext, - isInstantiatingStub: false); + ArraySignatureBuilder signatureBuilder = BuildSignatureForMethod(method, factory); byte[] signature = signatureBuilder.ToArray(); BlobVertex signatureBlob; if (!uniqueSignatures.TryGetValue(signature, out signatureBlob)) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs index 80f80b202cecc7..ca6b4fc84d3a7d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Linq; using System.Reflection; using System.Reflection.Metadata; @@ -63,6 +64,11 @@ public class ManifestMetadataTableNode : HeaderTableNode /// private int _nextModuleId; + /// + /// Modules which need to exist in set of modules visible + /// + private ConcurrentBag _modulesWhichMustBeIndexable = new ConcurrentBag(); + /// /// Set to true after GetData has been called. After that, ModuleToIndex may be called no more. /// @@ -136,6 +142,19 @@ public int ModuleToIndex(EcmaModule module) return ModuleToIndexInternal(module); } + public void EnsureModuleIndexable(ModuleDesc module) + { + if (_emissionCompleted) + { + throw new InvalidOperationException("Adding a new assembly after signatures have been materialized."); + } + + if (module is EcmaModule ecmaModule && _nodeFactory.CompilationModuleGroup.VersionsWithModule(ecmaModule)) + { + _modulesWhichMustBeIndexable.Add(ecmaModule); + } + } + private int ModuleToIndexInternal(EcmaModule module) { AssemblyName assemblyName = module.Assembly.GetName(); @@ -170,13 +189,8 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde sb.Append("ManifestMetadataTableNode"); } - public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) + private void ComputeLastSetOfModuleIndices() { - if (relocsOnly) - { - return new ObjectData(Array.Empty(), null, 1, null); - } - if (!_emissionCompleted) { foreach (ISignatureEmitter emitter in _signatureEmitters) @@ -184,8 +198,25 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) emitter.MaterializeSignature(); } + EcmaModule [] moduleArray = _modulesWhichMustBeIndexable.ToArray(); + Array.Sort(moduleArray, (EcmaModule moduleA, EcmaModule moduleB) => moduleA.CompareTo(moduleB)); + foreach (var module in moduleArray) + { + ModuleToIndex(module); + } + _emissionCompleted = true; } + } + + public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) + { + if (relocsOnly) + { + return new ObjectData(Array.Empty(), null, 1, null); + } + + ComputeLastSetOfModuleIndices(); MetadataBuilder metadataBuilder = new MetadataBuilder(); @@ -277,6 +308,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) internal byte[] GetManifestAssemblyMvidTableData() { + ComputeLastSetOfModuleIndices(); + byte[] manifestAssemblyMvidTable = new byte[ManifestAssemblyMvidTableSize]; for (int i = 0; i < _manifestAssemblyMvids.Count; i++) { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs index 9dc2907900a4a5..514441e2ba646a 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodWithGCInfo.cs @@ -8,6 +8,7 @@ using Internal.JitInterface; using Internal.Text; using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; namespace ILCompiler.DependencyAnalysis.ReadyToRun { @@ -45,6 +46,34 @@ protected override void OnMarked(NodeFactory context) InitializeFrameInfos(Array.Empty()); } _lateTriggeredCompilation = context.CompilationCurrentPhase != 0; + RegisterInlineeModuleIndices(context); + } + + private void RegisterInlineeModuleIndices(NodeFactory factory) + { + if (_inlinedMethods != null) + { + foreach (var inlinee in _inlinedMethods) + { + MethodDesc inlineeDefinition = inlinee.GetTypicalMethodDefinition(); + if (!(inlineeDefinition is EcmaMethod ecmaInlineeDefinition)) + { + // We don't record non-ECMA methods because they don't have tokens that + // diagnostic tools could reason about anyway. + continue; + } + + if (!factory.CompilationModuleGroup.VersionsWithMethodBody(inlinee)) + { + // We cannot record inlining info across version bubble as cross-bubble assemblies + // are not guaranteed to preserve token values. Only non-versionable methods may be + // inlined across the version bubble. + Debug.Assert(inlinee.IsNonVersionable()); + continue; + } + factory.ManifestMetadataTable.EnsureModuleIndexable(ecmaInlineeDefinition.Module); + } + } } public override int DependencyPhaseForDeferredStaticComputation => _lateTriggeredCompilation ? 2 : 0; @@ -296,12 +325,12 @@ public void InitializeDebugLocInfos(OffsetMapping[] debugLocInfos) _debugLocInfos = DebugInfoTableNode.CreateBoundsBlobForMethod(debugLocInfos); } - public void InitializeDebugVarInfos(NativeVarInfo[] debugVarInfos) + public void InitializeDebugVarInfos(NativeVarInfo[] debugVarInfos, TargetDetails target) { Debug.Assert(_debugVarInfos == null); // Process the debug info from JIT format to R2R format immediately as it is large // and not used in the rest of the process except to emit. - _debugVarInfos = DebugInfoTableNode.CreateVarBlobForMethod(debugVarInfos); + _debugVarInfos = DebugInfoTableNode.CreateVarBlobForMethod(debugVarInfos, target); } public void InitializeDebugEHClauseInfos(DebugEHClauseInfo[] debugEHClauseInfos) @@ -316,10 +345,12 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return comparer.Compare(_method, otherNode._method); } - public void InitializeInliningInfo(MethodDesc[] inlinedMethods) + public void InitializeInliningInfo(MethodDesc[] inlinedMethods, NodeFactory factory) { Debug.Assert(_inlinedMethods == null); _inlinedMethods = inlinedMethods; + if (this.Marked) + RegisterInlineeModuleIndices(factory); } public int Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index de7ada8b21e01a..a5c7359a048b04 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -236,7 +236,7 @@ public sealed class ReadyToRunCodegenCompilation : Compilation private readonly IEnumerable _inputFiles; private readonly string _compositeRootPath; - + private readonly bool _resilient; private readonly int _parallelism; @@ -400,7 +400,9 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow } CopiedCorHeaderNode copiedCorHeader = new CopiedCorHeaderNode(inputModule); - DebugDirectoryNode debugDirectory = new DebugDirectoryNode(inputModule, outputFile); + // Re-written components shouldn't have any additional diagnostic information - only information about the forwards. + // Even with all of this, we might be modifying the image in a silly manner - adding a directory when if didn't have one. + DebugDirectoryNode debugDirectory = new DebugDirectoryNode(inputModule, outputFile, shouldAddNiPdb: false, shouldGeneratePerfmap: false); NodeFactory componentFactory = new NodeFactory( _nodeFactory.TypeSystemContext, _nodeFactory.CompilationModuleGroup, @@ -490,7 +492,7 @@ private bool IsLayoutFixedInCurrentVersionBubbleInternal(TypeDesc type) var fieldType = field.FieldType; if (!fieldType.IsValueType) continue; - + if (!IsLayoutFixedInCurrentVersionBubble(fieldType)) { return false; @@ -515,7 +517,7 @@ public bool IsInheritanceChainLayoutFixedInCurrentVersionBubble(TypeDesc type) { return false; } - + type = type.BaseType; if (type != null) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index c1207a4b5b2f00..34aced76b44b01 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -219,7 +219,7 @@ public override ICompilation ToCompilation() EcmaModule singleModule = _compilationGroup.IsCompositeBuildMode ? null : inputModules.First(); CopiedCorHeaderNode corHeaderNode = new CopiedCorHeaderNode(singleModule); // TODO: proper support for multiple input files - DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(singleModule, _outputFile); + DebugDirectoryNode debugDirectoryNode = new DebugDirectoryNode(singleModule, _outputFile, _generatePdbFile, _generatePerfMapFile); // Produce a ResourceData where the IBC PROFILE_DATA entry has been filtered out // TODO: proper support for multiple input files diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunFileLayoutOptimizer.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunFileLayoutOptimizer.cs index d8d6d36191a7c7..4ef5443e4f5477 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunFileLayoutOptimizer.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunFileLayoutOptimizer.cs @@ -26,6 +26,7 @@ public enum ReadyToRunMethodLayoutAlgorithm HotWarmCold, CallFrequency, PettisHansen, + Random, } public enum ReadyToRunFileLayoutAlgorithm @@ -166,6 +167,17 @@ int ComputeHotWarmColdRegion(MethodWithGCInfo method) methods = PettisHansenSort(methods); break; + case ReadyToRunMethodLayoutAlgorithm.Random: + Random rand = new Random(0); + for (int i = 0; i < methods.Count - 1; i++) + { + int j = rand.Next(i, methods.Count); + MethodWithGCInfo temp = methods[i]; + methods[i] = methods[j]; + methods[j] = temp; + } + break; + default: throw new NotImplementedException(_methodLayoutAlgorithm.ToString()); } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs index e506bb8b3b6ef8..9380a829b8f3c9 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunHashCode.cs @@ -34,10 +34,10 @@ public static int NameHashCode(string name) byte[] src = Encoding.UTF8.GetBytes(name); for (int i = 0; i < src.Length; i += 2) { - hash1 = unchecked(hash1 + RotateLeft(hash1, 5)) ^ src[i]; + hash1 = unchecked(hash1 + RotateLeft(hash1, 5)) ^ (int)unchecked((sbyte)src[i]); if (i + 1 < src.Length) { - hash2 = unchecked(hash2 + RotateLeft(hash2, 5)) ^ src[i + 1]; + hash2 = unchecked(hash2 + RotateLeft(hash2, 5)) ^ (int)unchecked((sbyte)src[i + 1]); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs index 8f37f8e9b62ff2..e8b8f0ab0b5e59 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs @@ -101,16 +101,30 @@ public IEnumerable GetCompiledMethods(EcmaModule moduleToEnumerate, { if (!_sortedMethods) { - TypeSystemComparer comparer = new TypeSystemComparer(); - Comparison sortHelper = (x, y) => comparer.Compare(x.Method, y.Method); + CompilerComparer comparer = new CompilerComparer(); + SortableDependencyNode.ObjectNodeComparer objectNodeComparer = new SortableDependencyNode.ObjectNodeComparer(comparer); + Comparison sortHelper = (x, y) => + { + int nodeComparerResult = objectNodeComparer.Compare((SortableDependencyNode)x, (SortableDependencyNode)y); +#if DEBUG + int methodOnlyResult = comparer.Compare(x.Method, y.Method); + + // Assert the two sorting techniques produce the same result unless there is a CustomSort applied + Debug.Assert((nodeComparerResult == methodOnlyResult) || + ((x is SortableDependencyNode sortableX && sortableX.CustomSort != Int32.MaxValue) || + (y is SortableDependencyNode sortableY && sortableY.CustomSort != Int32.MaxValue))); +#endif + return nodeComparerResult; + }; + Comparison sortHelperNoCustomSort = (x, y) => comparer.Compare(x, y); List perModuleDatas = new List(_methodsGenerated.Values); perModuleDatas.Sort((x, y) => x.Module.CompareTo(y.Module)); foreach (var perModuleData in perModuleDatas) { - perModuleData.MethodsGenerated.MergeSort(sortHelper); - perModuleData.GenericMethodsGenerated.MergeSort(sortHelper); + perModuleData.MethodsGenerated.MergeSort(sortHelperNoCustomSort); + perModuleData.GenericMethodsGenerated.MergeSort(sortHelperNoCustomSort); _completeSortedMethods.AddRange(perModuleData.MethodsGenerated); _completeSortedMethods.AddRange(perModuleData.GenericMethodsGenerated); _completeSortedGenericMethods.AddRange(perModuleData.GenericMethodsGenerated); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs index 7da42e09791fda..927148cf006e26 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Interop/IL/Marshaller.ReadyToRun.cs @@ -40,21 +40,18 @@ protected static Marshaller CreateMarshaller(MarshallerKind kind) } } - public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod) + private static Marshaller[] GetMarshallers( + MethodSignature methodSig, + PInvokeFlags flags, + ParameterMetadata[] parameterMetadataArray) { - Debug.Assert(targetMethod.IsPInvoke); - - MarshalDirection direction = MarshalDirection.Forward; - MethodSignature methodSig = targetMethod.Signature; - PInvokeFlags flags = targetMethod.GetPInvokeMethodMetadata().Flags; - - ParameterMetadata[] parameterMetadataArray = targetMethod.GetParameterMetadata(); Marshaller[] marshallers = new Marshaller[methodSig.Length + 1]; - ParameterMetadata parameterMetadata; for (int i = 0, parameterIndex = 0; i < marshallers.Length; i++) { Debug.Assert(parameterIndex == parameterMetadataArray.Length || i <= parameterMetadataArray[parameterIndex].Index); + + ParameterMetadata parameterMetadata; if (parameterIndex == parameterMetadataArray.Length || i < parameterMetadataArray[parameterIndex].Index) { // if we don't have metadata for the parameter, create a dummy one @@ -72,7 +69,7 @@ public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod) methodSig.GetEmbeddedSignatureData(), MarshallerType.Argument, parameterMetadata.MarshalAsDescriptor, - direction, + MarshalDirection.Forward, marshallers, parameterMetadata.Index, flags, @@ -84,6 +81,24 @@ public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod) return marshallers; } + + public static Marshaller[] GetMarshallersForMethod(MethodDesc targetMethod) + { + Debug.Assert(targetMethod.IsPInvoke); + return GetMarshallers( + targetMethod.Signature, + targetMethod.GetPInvokeMethodMetadata().Flags, + targetMethod.GetParameterMetadata()); + } + + public static Marshaller[] GetMarshallersForSignature(MethodSignature methodSig, ParameterMetadata[] paramMetadata) + { + return GetMarshallers( + methodSig, + new PInvokeFlags(PInvokeAttributes.None), + paramMetadata); + } + public static bool IsMarshallingRequired(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); @@ -115,25 +130,10 @@ public static bool IsMarshallingRequired(MethodDesc targetMethod) public static bool IsMarshallingRequired(MethodSignature methodSig, ParameterMetadata[] paramMetadata) { - for (int i = 0, paramIndex = 0; i < methodSig.Length + 1; i++) + Marshaller[] marshallers = GetMarshallersForSignature(methodSig, paramMetadata); + for (int i = 0; i < marshallers.Length; i++) { - ParameterMetadata parameterMetadata = (paramIndex == paramMetadata.Length || i < paramMetadata[paramIndex].Index) ? - new ParameterMetadata(i, ParameterMetadataAttributes.None, null) : - paramMetadata[paramIndex++]; - - TypeDesc parameterType = (i == 0) ? methodSig.ReturnType : methodSig[i - 1]; //first item is the return type - - MarshallerKind marshallerKind = MarshalHelpers.GetMarshallerKind( - parameterType, - parameterIndex: i, - customModifierData: methodSig.GetEmbeddedSignatureData(), - parameterMetadata.MarshalAsDescriptor, - parameterMetadata.Return, - isAnsi: true, - MarshallerType.Argument, - out MarshallerKind elementMarshallerKind); - - if (IsMarshallingRequired(marshallerKind)) + if (marshallers[i].IsMarshallingRequired()) return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs index 8cd0ad481cc6d2..d46dab26c7fd92 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs @@ -29,7 +29,7 @@ public void SavePdb(string pdbPath, string dllFileName) new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, _outputInfoBuilder.EnumerateMethods()); } - public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dllFileName, TargetOS targetOS, TargetArchitecture targetArch) + public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dllFileName, TargetDetails details) { string perfMapExtension; if (perfMapFormatVersion == PerfMapWriter.LegacyCrossgen1FormatVersion) @@ -56,7 +56,7 @@ public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dll string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + perfMapExtension); Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); - PerfMapWriter.Write(perfMapFileName, perfMapFormatVersion, _outputInfoBuilder.EnumerateMethods(), _outputInfoBuilder.EnumerateInputAssemblies(), targetOS, targetArch); + PerfMapWriter.Write(perfMapFileName, perfMapFormatVersion, _outputInfoBuilder.EnumerateMethods(), _outputInfoBuilder.EnumerateInputAssemblies(), details); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj index 82452cfa3e9c6d..42a13564aac724 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun/ILCompiler.TypeSystem.ReadyToRun.csproj @@ -30,7 +30,7 @@ 4.3.0 - $(SystemReflectionMetadataVersion) + $(SystemReflectionMetadataStaticVersion) 1.3.0 diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index afae84f57f6fac..e9eb59289f89f7 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -156,6 +156,7 @@ private void ProcessCommandLine(string[] args) "hotwarmcold" => ReadyToRunMethodLayoutAlgorithm.HotWarmCold, "callfrequency" => ReadyToRunMethodLayoutAlgorithm.CallFrequency, "pettishansen" => ReadyToRunMethodLayoutAlgorithm.PettisHansen, + "random" => ReadyToRunMethodLayoutAlgorithm.Random, _ => throw new CommandLineException(SR.InvalidMethodLayout) }; } diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index c122cd63abdfef..85ba1a7664ebad 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -148,7 +148,7 @@ Method layout must be either DefaultSort or MethodOrder. - Method layout must be either DefaultSort, ExclusiveWeight, HotCold, HotWarmCold, CallFrequency or PettisHansen. + Method layout must be either DefaultSort, ExclusiveWeight, HotCold, HotWarmCold, CallFrequency, PettisHansen, or Random. True to skip compiling methods into the R2R image (default = false) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 86591df5df32f9..68493f0bdc1e19 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -183,6 +183,7 @@ struct JitInterfaceCallbacks uint16_t (* getRelocTypeHint)(void * thisHandle, CorInfoExceptionClass** ppException, void* target); uint32_t (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoExceptionClass** ppException); uint32_t (* getJitFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORJIT_FLAGS* flags, uint32_t sizeInBytes); + bool (* doesFieldBelongToClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLASS_HANDLE cls); }; @@ -1857,4 +1858,14 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; return temp; } + + virtual bool doesFieldBelongToClass( + CORINFO_FIELD_HANDLE fldHnd, + CORINFO_CLASS_HANDLE cls) +{ + CorInfoExceptionClass* pException = nullptr; + bool temp = _callbacks->doesFieldBelongToClass(_thisHandle, &pException, fldHnd, cls); + if (pException != nullptr) throw pException; + return temp; +} }; diff --git a/src/coreclr/tools/r2rdump/R2RDump.cs b/src/coreclr/tools/r2rdump/R2RDump.cs index 94d71835966e5a..db9ecd31d3ade4 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/tools/r2rdump/R2RDump.cs @@ -146,7 +146,7 @@ private static unsafe IAssemblyMetadata Open(string filename) return new StandaloneAssemblyMetadata(peReader); } - + public SignatureFormattingOptions GetSignatureFormattingOptions() { if (signatureFormattingOptions == null) @@ -434,7 +434,9 @@ public void Dump(ReadyToRunReader r2r) { perfmapPath = Path.ChangeExtension(r2r.Filename, ".r2rmap"); } - PerfMapWriter.Write(perfmapPath, _options.PerfmapFormatVersion, ProduceDebugInfoMethods(r2r), ProduceDebugInfoAssemblies(r2r), r2r.TargetOperatingSystem, r2r.TargetArchitecture); + // TODO: can't seem to find any place that surfaces the ABI. This is for debugging purposes, so may not be as relevant to be correct. + TargetDetails details = new TargetDetails(r2r.TargetArchitecture, r2r.TargetOperatingSystem, TargetAbi.CoreRT); + PerfMapWriter.Write(perfmapPath, _options.PerfmapFormatVersion, ProduceDebugInfoMethods(r2r), ProduceDebugInfoAssemblies(r2r), details); } if (standardDump) @@ -459,7 +461,7 @@ IEnumerable ProduceDebugInfoMethods(ReadyToRunReader r2r) mi.AssemblyName = method.ComponentReader.MetadataReader.GetString(method.ComponentReader.MetadataReader.GetAssemblyDefinition().Name); mi.ColdRVA = 0; mi.ColdLength = 0; - + yield return mi; } } diff --git a/src/coreclr/tools/runincontext/runincontext.csproj b/src/coreclr/tools/runincontext/runincontext.csproj index 14a0a2cf310870..bf17769e6f0bd3 100644 --- a/src/coreclr/tools/runincontext/runincontext.csproj +++ b/src/coreclr/tools/runincontext/runincontext.csproj @@ -2,7 +2,7 @@ Exe $(NetCoreAppToolCurrent) - $(MicrosoftNETCoreAppVersion) + $(MicrosoftNETCoreAppRuntimewinx64Version) false BuildOnly $(RuntimeBinDir) diff --git a/src/coreclr/utilcode/clrconfig.cpp b/src/coreclr/utilcode/clrconfig.cpp index 59d32c0c43091d..ca6e095504313b 100644 --- a/src/coreclr/utilcode/clrconfig.cpp +++ b/src/coreclr/utilcode/clrconfig.cpp @@ -410,7 +410,7 @@ namespace // // Arguments: // * info - see file:../inc/CLRConfig.h for details. -// +// * isDefault - the value was not set or had an invalid format so the default was returned. // * result - the result. // // Return value: @@ -431,9 +431,7 @@ DWORD CLRConfig::GetConfigValue(const ConfigDWORDInfo & info, /* [Out] */ bool * DWORD resultMaybe; HRESULT hr = GetConfigDWORD(info.name, info.defaultValue, &resultMaybe, info.options); - - // Ignore the default value even if it's set explicitly. - if (resultMaybe != info.defaultValue) + if (SUCCEEDED(hr)) { *isDefault = false; return resultMaybe; diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index f7bf57c5b52cf1..13201596b7cfc3 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -3533,8 +3533,8 @@ DomainAssembly * AppDomain::FindAssembly(PEAssembly * pFile, FindAssemblyOptions !pManifestFile->IsResource() && pManifestFile->Equals(pFile)) { - // Caller already has PEAssembly, so we can give DomainAssembly away freely without AddRef - return pDomainAssembly.Extract(); + // Caller already has PEAssembly, so we can give DomainAssembly away freely without added reference + return pDomainAssembly.GetValue(); } } return NULL; @@ -3709,7 +3709,9 @@ BOOL AppDomain::AddFileToCache(AssemblySpec* pSpec, PEAssembly *pFile, BOOL fAll } CONTRACTL_END; - CrstHolder holder(&m_DomainCacheCrst); + GCX_PREEMP(); + DomainCacheCrstHolderForGCCoop holder(this); + // !!! suppress exceptions if(!m_AssemblyCache.StoreFile(pSpec, pFile) && !fAllowFailure) { @@ -3739,7 +3741,9 @@ BOOL AppDomain::AddAssemblyToCache(AssemblySpec* pSpec, DomainAssembly *pAssembl } CONTRACTL_END; - CrstHolder holder(&m_DomainCacheCrst); + GCX_PREEMP(); + DomainCacheCrstHolderForGCCoop holder(this); + // !!! suppress exceptions BOOL bRetVal = m_AssemblyCache.StoreAssembly(pSpec, pAssembly); return bRetVal; @@ -3760,7 +3764,9 @@ BOOL AppDomain::AddExceptionToCache(AssemblySpec* pSpec, Exception *ex) if (ex->IsTransient()) return TRUE; - CrstHolder holder(&m_DomainCacheCrst); + GCX_PREEMP(); + DomainCacheCrstHolderForGCCoop holder(this); + // !!! suppress exceptions return m_AssemblyCache.StoreException(pSpec, ex); } @@ -3778,7 +3784,7 @@ void AppDomain::AddUnmanagedImageToCache(LPCWSTR libraryName, NATIVE_LIBRARY_HAN } CONTRACTL_END; - CrstHolder lock(&m_DomainCacheCrst); + DomainCacheCrstHolderForGCPreemp lock(this); const UnmanagedImageCacheEntry *existingEntry = m_unmanagedCache.LookupPtr(libraryName); if (existingEntry != NULL) @@ -3808,7 +3814,8 @@ NATIVE_LIBRARY_HANDLE AppDomain::FindUnmanagedImageInCache(LPCWSTR libraryName) } CONTRACT_END; - CrstHolder lock(&m_DomainCacheCrst); + DomainCacheCrstHolderForGCPreemp lock(this); + const UnmanagedImageCacheEntry *existingEntry = m_unmanagedCache.LookupPtr(libraryName); if (existingEntry == NULL) RETURN NULL; @@ -3850,7 +3857,8 @@ BOOL AppDomain::RemoveAssemblyFromCache(DomainAssembly* pAssembly) } CONTRACTL_END; - CrstHolder holder(&m_DomainCacheCrst); + GCX_PREEMP(); + DomainCacheCrstHolderForGCCoop holder(this); return m_AssemblyCache.RemoveAssembly(pAssembly); } diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index fb2e45682fc685..2babce339267f4 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1171,6 +1171,30 @@ class BaseDomain }; friend class LockHolder; + // To be used when the thread will remain in preemptive GC mode while holding the lock + class DomainCacheCrstHolderForGCPreemp : private CrstHolder + { + public: + DomainCacheCrstHolderForGCPreemp(BaseDomain *pD) + : CrstHolder(&pD->m_DomainCacheCrst) + { + WRAPPER_NO_CONTRACT; + } + }; + + // To be used when the thread may enter cooperative GC mode while holding the lock. The thread enters a + // forbid-suspend-for-debugger region along with acquiring the lock, such that it would not suspend for the debugger while + // holding the lock, as that may otherwise cause a FuncEval to deadlock when trying to acquire the lock. + class DomainCacheCrstHolderForGCCoop : private CrstAndForbidSuspendForDebuggerHolder + { + public: + DomainCacheCrstHolderForGCCoop(BaseDomain *pD) + : CrstAndForbidSuspendForDebuggerHolder(&pD->m_DomainCacheCrst) + { + WRAPPER_NO_CONTRACT; + } + }; + class DomainLocalBlockLockHolder : public CrstHolder { public: diff --git a/src/coreclr/vm/callcounting.cpp b/src/coreclr/vm/callcounting.cpp index bdc4bc8a6d67fd..5a3561c284da88 100644 --- a/src/coreclr/vm/callcounting.cpp +++ b/src/coreclr/vm/callcounting.cpp @@ -715,14 +715,13 @@ extern "C" PCODE STDCALL OnCallCountThresholdReached(TransitionBlock *transition PCODE CallCountingManager::OnCallCountThresholdReached(TransitionBlock *transitionBlock, TADDR stubIdentifyingToken) { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - PRECONDITION(CheckPointer(transitionBlock)); - } - CONTRACTL_END; + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_TRIGGERS; + STATIC_CONTRACT_MODE_COOPERATIVE; + + PCODE codeEntryPoint; + + BEGIN_PRESERVE_LAST_ERROR; MAKE_CURRENT_THREAD_AVAILABLE(); @@ -740,8 +739,6 @@ PCODE CallCountingManager::OnCallCountThresholdReached(TransitionBlock *transiti CallCountingHelperFrame *frame = &frameWithCookie; frame->Push(CURRENT_THREAD); - PCODE codeEntryPoint; - INSTALL_MANAGED_EXCEPTION_DISPATCHER; INSTALL_UNWIND_AND_CONTINUE_HANDLER; @@ -786,6 +783,9 @@ PCODE CallCountingManager::OnCallCountThresholdReached(TransitionBlock *transiti UNINSTALL_MANAGED_EXCEPTION_DISPATCHER; frame->Pop(CURRENT_THREAD); + + END_PRESERVE_LAST_ERROR; + return codeEntryPoint; } diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index 78721292a3e9f5..153ca37d11b925 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -2412,6 +2412,11 @@ HeapList* EEJitManager::NewCodeHeap(CodeHeapRequestInfo *pInfo, DomainCodeHeapLi #endif size_t reserveSize = initialRequestSize; + +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) + reserveSize += JUMP_ALLOCATE_SIZE; +#endif + if (reserveSize < minReserveSize) reserveSize = minReserveSize; reserveSize = ALIGN_UP(reserveSize, VIRTUAL_ALLOC_RESERVE_GRANULARITY); diff --git a/src/coreclr/vm/crst.cpp b/src/coreclr/vm/crst.cpp index 63472e454e210b..d617647f27233b 100644 --- a/src/coreclr/vm/crst.cpp +++ b/src/coreclr/vm/crst.cpp @@ -789,8 +789,8 @@ CrstBase::CrstAndForbidSuspendForDebuggerHolder::CrstAndForbidSuspendForDebugger // Reentrant locks are currently not supported _ASSERTE((pCrst->m_dwFlags & CRST_REENTRANCY) == 0); - Thread *pThread = GetThread(); - if (pThread->IsInForbidSuspendForDebuggerRegion()) + Thread *pThread = GetThreadNULLOk(); + if (pThread == nullptr || pThread->IsInForbidSuspendForDebuggerRegion()) { AcquireLock(pCrst); return; diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index e21939990405c2..f08e5107b13812 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -776,6 +776,28 @@ FCIMPL4(void, DebugStackTrace::GetStackFramesInternal, } FCIMPLEND +MethodDesc* QCALLTYPE DebugStackTrace::GetMethodDescFromNativeIP(LPVOID ip) +{ + QCALL_CONTRACT; + + MethodDesc* pResult = nullptr; + + BEGIN_QCALL; + + // TODO: There is a race for dynamic and collectible methods here between getting + // the MethodDesc here and when the managed wrapper converts it into a MethodBase + // where the method could be collected. + EECodeInfo codeInfo((PCODE)ip); + if (codeInfo.IsValid()) + { + pResult = codeInfo.GetMethodDesc(); + } + + END_QCALL; + + return pResult; +} + FORCEINLINE void HolderDestroyStrongHandle(OBJECTHANDLE h) { if (h != NULL) DestroyStrongHandle(h); } typedef Wrapper, HolderDestroyStrongHandle, NULL> StrongHandleHolder; diff --git a/src/coreclr/vm/debugdebugger.h b/src/coreclr/vm/debugdebugger.h index cba432e3d8e5f2..2673f90717a695 100644 --- a/src/coreclr/vm/debugdebugger.h +++ b/src/coreclr/vm/debugdebugger.h @@ -158,6 +158,8 @@ class DebugStackTrace Object* pException ); + static MethodDesc* QCALLTYPE GetMethodDescFromNativeIP(LPVOID ip); + static void GetStackFramesFromException(OBJECTREF * e, GetStackFramesData *pData, PTRARRAYREF * pDynamicMethodArray = NULL); #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/dynamicmethod.cpp b/src/coreclr/vm/dynamicmethod.cpp index 6b6c5ffacce4e7..6428256e81df76 100644 --- a/src/coreclr/vm/dynamicmethod.cpp +++ b/src/coreclr/vm/dynamicmethod.cpp @@ -398,6 +398,11 @@ HeapList* HostCodeHeap::InitializeHeapList(CodeHeapRequestInfo *pInfo) // Add TrackAllocation, HeapList and very conservative padding to make sure we have enough for the allocation ReserveBlockSize += sizeof(TrackAllocation) + HOST_CODEHEAP_SIZE_ALIGN + 0x100; + +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) + ReserveBlockSize += JUMP_ALLOCATE_SIZE; +#endif + // reserve ReserveBlockSize rounded-up to VIRTUAL_ALLOC_RESERVE_GRANULARITY of memory ReserveBlockSize = ALIGN_UP(ReserveBlockSize, VIRTUAL_ALLOC_RESERVE_GRANULARITY); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index c83248c00e2d0d..363ae6f6cfa7cc 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -128,6 +128,7 @@ FCFuncEnd() FCFuncStart(gDiagnosticsStackTrace) FCFuncElement("GetStackFramesInternal", DebugStackTrace::GetStackFramesInternal) + QCFuncElement("GetMethodDescFromNativeIP", DebugStackTrace::GetMethodDescFromNativeIP) FCFuncEnd() FCFuncStart(gEnvironmentFuncs) diff --git a/src/coreclr/vm/eeprofinterfaces.h b/src/coreclr/vm/eeprofinterfaces.h index ec51b014148b4b..9267fc356179a4 100644 --- a/src/coreclr/vm/eeprofinterfaces.h +++ b/src/coreclr/vm/eeprofinterfaces.h @@ -47,6 +47,8 @@ void __stdcall GarbageCollectionStartedCallback(int generation, BOOL induced); void __stdcall GarbageCollectionFinishedCallback(); void __stdcall UpdateGenerationBounds(); + +void __stdcall ProfilerAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved); #include "eetoprofinterfaceimpl.h" diff --git a/src/coreclr/vm/eetoprofinterfaceimpl.cpp b/src/coreclr/vm/eetoprofinterfaceimpl.cpp index 78a85b964e27a2..0f48e80e499605 100644 --- a/src/coreclr/vm/eetoprofinterfaceimpl.cpp +++ b/src/coreclr/vm/eetoprofinterfaceimpl.cpp @@ -102,8 +102,32 @@ enum ClrToProfEntrypointFlags kEE2PNoTrigger = 0x00000004, }; -#define ASSERT_EVAC_COUNTER_NONZERO() \ - _ASSERTE(m_pProfilerInfo->dwProfilerEvacuationCounter.Load() > 0) +EvacuationCounterHolder::EvacuationCounterHolder(ProfilerInfo *pProfilerInfo) : + m_pProfilerInfo(pProfilerInfo), + m_pThread(GetThreadNULLOk()) +{ + _ASSERTE(m_pProfilerInfo != NULL); + if (m_pThread == NULL) + { + return; + } + + m_pThread->IncProfilerEvacuationCounter(m_pProfilerInfo->slot); +} + +EvacuationCounterHolder::~EvacuationCounterHolder() +{ + if (m_pThread == NULL) + { + return; + } + + m_pThread->DecProfilerEvacuationCounter(m_pProfilerInfo->slot); +} + +#define ASSERT_EVAC_COUNTER_NONZERO() \ + _ASSERTE((GetThreadNULLOk() == NULL) || \ + (GetThread()->GetProfilerEvacuationCounter(m_pProfilerInfo->slot) > 0)) #define CHECK_PROFILER_STATUS(ee2pFlags) \ /* If one of these asserts fires, perhaps you forgot to use */ \ diff --git a/src/coreclr/vm/eetoprofinterfaceimpl.h b/src/coreclr/vm/eetoprofinterfaceimpl.h index 4ec468a4150c7d..5453723fb8e022 100644 --- a/src/coreclr/vm/eetoprofinterfaceimpl.h +++ b/src/coreclr/vm/eetoprofinterfaceimpl.h @@ -476,6 +476,10 @@ class EEToProfInterfaceImpl HRESULT LoadAsNotficationOnly(BOOL *pbNotificationOnly); + ProfToEEInterfaceImpl *GetProfToEE() + { + return m_pProfToEE; + } private: // diff --git a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h index 646b8f9bd8f194..dd5e6837bb82e3 100644 --- a/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h @@ -188,16 +188,22 @@ ds_rt_config_value_get_default_port_suspend (void) static ds_ipc_result_t -ds_rt_generate_core_dump (DiagnosticsGenerateCoreDumpCommandPayload *payload) +ds_rt_generate_core_dump (DiagnosticsDumpCommandId commandId, DiagnosticsGenerateCoreDumpCommandPayload *payload) { STATIC_CONTRACT_NOTHROW; ds_ipc_result_t result = DS_IPC_E_FAIL; EX_TRY { + uint32_t flags = ds_generate_core_dump_command_payload_get_flags(payload); + if (commandId == DS_DUMP_COMMANDID_GENERATE_CORE_DUMP) + { + // For the old commmand, this payload field is a bool of whether to enable logging + flags = flags != 0 ? GenerateDumpFlagsLoggingEnabled : 0; + } if (GenerateDump (reinterpret_cast(ds_generate_core_dump_command_payload_get_dump_name (payload)), static_cast(ds_generate_core_dump_command_payload_get_dump_type (payload)), - (ds_generate_core_dump_command_payload_get_diagnostics (payload) != 0) ? true : false)) + flags)) result = DS_IPC_S_OK; } EX_CATCH {} diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 74a1f9f6be7822..1674aa2adc43b9 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -4178,8 +4178,8 @@ InitializeCrashDump() bool GenerateDump( LPCWSTR dumpName, - int dumpType, - bool diag) + INT dumpType, + ULONG32 flags) { #ifdef TARGET_UNIX MAKE_UTF8PTR_FROMWIDE_NOTHROW (dumpNameUtf8, dumpName); @@ -4189,10 +4189,10 @@ bool GenerateDump( } else { - return PAL_GenerateCoreDump(dumpNameUtf8, dumpType, diag); + return PAL_GenerateCoreDump(dumpNameUtf8, dumpType, flags); } #else // TARGET_UNIX - return GenerateCrashDump(dumpName, dumpType, diag); + return GenerateCrashDump(dumpName, dumpType, flags & GenerateDumpFlagsLoggingEnabled); #endif // TARGET_UNIX } @@ -9096,6 +9096,7 @@ void SetupWatsonBucketsForUEF(BOOL fUseLastThrownObject) struct { OBJECTREF oThrowable; + U1ARRAYREF oBuckets; } gc; ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); @@ -9197,9 +9198,10 @@ void SetupWatsonBucketsForUEF(BOOL fUseLastThrownObject) SetupWatsonBucketsForNonPreallocatedExceptions(gc.oThrowable); } - if (((EXCEPTIONREF)gc.oThrowable)->AreWatsonBucketsPresent()) + gc.oBuckets = ((EXCEPTIONREF)gc.oThrowable)->GetWatsonBucketReference(); + if (gc.oBuckets != NULL) { - pUEWatsonBucketTracker->CopyBucketsFromThrowable(gc.oThrowable); + pUEWatsonBucketTracker->CopyBuckets(gc.oBuckets); } if (pUEWatsonBucketTracker->RetrieveWatsonBuckets() == NULL) @@ -9519,6 +9521,7 @@ BOOL SetupWatsonBucketsForFailFast(EXCEPTIONREF refException) { OBJECTREF refException; OBJECTREF oInnerMostExceptionThrowable; + U1ARRAYREF oBuckets; } gc; ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); @@ -9669,10 +9672,11 @@ BOOL SetupWatsonBucketsForFailFast(EXCEPTIONREF refException) } // If it has the buckets, copy them over to the current Watson bucket tracker - if (((EXCEPTIONREF)gc.oInnerMostExceptionThrowable)->AreWatsonBucketsPresent()) + gc.oBuckets = ((EXCEPTIONREF)gc.oInnerMostExceptionThrowable)->GetWatsonBucketReference(); + if (gc.oBuckets != NULL) { pUEWatsonBucketTracker->ClearWatsonBucketDetails(); - pUEWatsonBucketTracker->CopyBucketsFromThrowable(gc.oInnerMostExceptionThrowable); + pUEWatsonBucketTracker->CopyBuckets(gc.oBuckets); if (pUEWatsonBucketTracker->RetrieveWatsonBuckets() != NULL) { LOG((LF_EH, LL_INFO1000, "SetupWatsonBucketsForFailFast - Got watson buckets from regular innermost exception.\n")); @@ -9711,11 +9715,12 @@ BOOL SetupWatsonBucketsForFailFast(EXCEPTIONREF refException) SetupWatsonBucketsForNonPreallocatedExceptions(gc.refException); } - if (((EXCEPTIONREF)gc.refException)->AreWatsonBucketsPresent()) + gc.oBuckets = ((EXCEPTIONREF)gc.refException)->GetWatsonBucketReference(); + if (gc.oBuckets != NULL) { // Copy the buckets to the current watson bucket tracker pUEWatsonBucketTracker->ClearWatsonBucketDetails(); - pUEWatsonBucketTracker->CopyBucketsFromThrowable(gc.refException); + pUEWatsonBucketTracker->CopyBuckets(gc.oBuckets); if (pUEWatsonBucketTracker->RetrieveWatsonBuckets() != NULL) { LOG((LF_EH, LL_INFO1000, "SetupWatsonBucketsForFailFast - Watson buckets copied from the exception object.\n")); @@ -9950,6 +9955,9 @@ void SetupInitialThrowBucketDetails(UINT_PTR adjustedIp) EX_TRY { CopyWatsonBucketsToThrowable(pUEWatsonBucketTracker->RetrieveWatsonBuckets()); + + // Technically this assert can fail, as another thread could clear the buckets after + // CopyWatsonBucketsToThrowable but before the assert runs, but it is very unlikely. _ASSERTE(((EXCEPTIONREF)gc.oCurrentThrowable)->AreWatsonBucketsPresent()); } EX_CATCH @@ -10686,7 +10694,7 @@ void EHWatsonBucketTracker::Init() // This method copies the bucketing details from the specified throwable // to the current Watson Bucket tracker. -void EHWatsonBucketTracker::CopyBucketsFromThrowable(OBJECTREF oThrowable) +void EHWatsonBucketTracker::CopyBuckets(U1ARRAYREF oBuckets) { #ifndef DACCESS_COMPILE CONTRACTL @@ -10694,8 +10702,7 @@ void EHWatsonBucketTracker::CopyBucketsFromThrowable(OBJECTREF oThrowable) NOTHROW; GC_NOTRIGGER; MODE_ANY; - PRECONDITION(oThrowable != NULL); - PRECONDITION(((EXCEPTIONREF)oThrowable)->AreWatsonBucketsPresent()); + PRECONDITION(oBuckets != NULL); PRECONDITION(IsWatsonEnabled()); } CONTRACTL_END; @@ -10704,16 +10711,16 @@ void EHWatsonBucketTracker::CopyBucketsFromThrowable(OBJECTREF oThrowable) struct { - OBJECTREF oFrom; + U1ARRAYREF oFromBuckets; } _gc; ZeroMemory(&_gc, sizeof(_gc)); GCPROTECT_BEGIN(_gc); - _gc.oFrom = oThrowable; + _gc.oFromBuckets = oBuckets; - LOG((LF_EH, LL_INFO1000, "EHWatsonBucketTracker::CopyEHWatsonBucketTracker - Copying bucketing details from throwable (%p) to tracker (%p)\n", - OBJECTREFToObject(_gc.oFrom), this)); + LOG((LF_EH, LL_INFO1000, "EHWatsonBucketTracker::CopyEHWatsonBucketTracker - Copying bucketing details from bucket (%p) to tracker (%p)\n", + OBJECTREFToObject(_gc.oFromBuckets), this)); // Watson bucket is a "GenericModeBlock" type. Set up an empty GenericModeBlock // to hold the bucket parameters. @@ -10728,8 +10735,7 @@ void EHWatsonBucketTracker::CopyBucketsFromThrowable(OBJECTREF oThrowable) else { // Get the raw array data pointer - U1ARRAYREF refWatsonBucketArray = ((EXCEPTIONREF)_gc.oFrom)->GetWatsonBucketReference(); - PTR_VOID pRawWatsonBucketArray = dac_cast(refWatsonBucketArray->GetDataPtr()); + PTR_VOID pRawWatsonBucketArray = dac_cast(_gc.oFromBuckets->GetDataPtr()); // Copy over the details to our new allocation memcpyNoGCRefs(pgmb, pRawWatsonBucketArray, sizeof(GenericModeBlock)); @@ -11527,8 +11533,9 @@ VOID ThrowBadFormatWorker(UINT resID, LPCWSTR imageName DEBUGARG(__in_z const ch msgStr += W(")"); } #endif - ThrowHR(COR_E_BADIMAGEFORMAT, msgStr); +#else // DACCESS_COMPILE + ThrowHR(COR_E_BADIMAGEFORMAT); #endif // #ifndef DACCESS_COMPILE } diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h index f338dd76f4cb37..f95a8b6784ea97 100644 --- a/src/coreclr/vm/excep.h +++ b/src/coreclr/vm/excep.h @@ -195,10 +195,20 @@ enum UnhandledExceptionLocation }; #ifdef HOST_WINDOWS + +// Must be the same as the copy in pal.h and the WriteDumpFlags enum in the diagnostics repo +enum +{ + GenerateDumpFlagsNone = 0x00, + GenerateDumpFlagsLoggingEnabled = 0x01, + GenerateDumpFlagsVerboseLoggingEnabled = 0x02, + GenerateDumpFlagsCrashReportEnabled = 0x04 +}; + void InitializeCrashDump(); void CreateCrashDumpIfEnabled(bool stackoverflow = false); #endif -bool GenerateDump(LPCWSTR dumpName, int dumpType, bool diag); +bool GenerateDump(LPCWSTR dumpName, INT dumpType, ULONG32 flags); // Generates crash dumps if enabled for both Windows and Linux void CrashDumpAndTerminateProcess(UINT exitCode); diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index 7e3a058f7b2b6b..3fefb7936069a4 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -515,8 +515,12 @@ template NOINLINE VOID ThrowBadFormatWorkerT(UINT resID, T * pImgObj DEBUGARG(__in_z const char *cond)) { +#ifdef DACCESS_COMPILE + ThrowBadFormatWorker(resID, nullptr DEBUGARG(cond)); +#else LPCWSTR tmpStr = GetPathForErrorMessagesT(pImgObj); ThrowBadFormatWorker(resID, tmpStr DEBUGARG(cond)); +#endif } diff --git a/src/coreclr/vm/exstatecommon.h b/src/coreclr/vm/exstatecommon.h index ba8086a5402fe1..b2abb9d9f3c1d3 100644 --- a/src/coreclr/vm/exstatecommon.h +++ b/src/coreclr/vm/exstatecommon.h @@ -483,7 +483,7 @@ class EHWatsonBucketTracker EHWatsonBucketTracker(); void Init(); void CopyEHWatsonBucketTracker(const EHWatsonBucketTracker& srcTracker); - void CopyBucketsFromThrowable(OBJECTREF oThrowable); + void CopyBuckets(U1ARRAYREF oBuckets); void SaveIpForWatsonBucket(UINT_PTR ip); UINT_PTR RetrieveWatsonBucketIp(); PTR_VOID RetrieveWatsonBuckets(); diff --git a/src/coreclr/vm/gcenv.ee.cpp b/src/coreclr/vm/gcenv.ee.cpp index f963146ffb6163..e03bd67d8ba0d1 100644 --- a/src/coreclr/vm/gcenv.ee.cpp +++ b/src/coreclr/vm/gcenv.ee.cpp @@ -1656,7 +1656,7 @@ void GCToEEInterface::AnalyzeSurvivorsFinished(size_t gcIndex, int condemnedGene { EX_TRY { - GenerateDump (GENAWARE_DUMP_FILE_NAME, 2, false); + GenerateDump (GENAWARE_DUMP_FILE_NAME, 2, GenerateDumpFlagsNone); } EX_CATCH {} EX_END_CATCH(SwallowAllExceptions); @@ -1732,3 +1732,8 @@ uint32_t GCToEEInterface::GetCurrentProcessCpuCount() { return ::GetCurrentProcessCpuCount(); } + +void GCToEEInterface::DiagAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) +{ + ProfilerAddNewRegion(generation, rangeStart, rangeEnd, rangeEndReserved); +} diff --git a/src/coreclr/vm/gcenv.ee.h b/src/coreclr/vm/gcenv.ee.h index 6ac79248a6d2c9..6403f2637b817f 100644 --- a/src/coreclr/vm/gcenv.ee.h +++ b/src/coreclr/vm/gcenv.ee.h @@ -85,6 +85,8 @@ class GCToEEInterface : public IGCToCLR { void LogStressMsg(unsigned level, unsigned facility, const StressLogMsg& msg); uint32_t GetCurrentProcessCpuCount(); + + void DiagAddNewRegion(int generation, BYTE * rangeStart, BYTE * rangeEnd, BYTE * rangeEndReserved); }; } // namespace standalone diff --git a/src/coreclr/vm/ilmarshalers.h b/src/coreclr/vm/ilmarshalers.h index ba07cd5b55c175..8d24d07500472d 100644 --- a/src/coreclr/vm/ilmarshalers.h +++ b/src/coreclr/vm/ilmarshalers.h @@ -988,11 +988,19 @@ class ILMarshaler m_nativeHome.InitHome(ILStubMarshalHome::HomeType_ILByrefLocal, pcsSetup->NewLocal(nativeFieldTypeByRef), &nativeType, /* unalignedIndirectStore */ true); + // During the cleanup pass, the managed typed is explicitly passed as null - see DestroyStructure(). This works + // except if the type has nested non-blittable fields. Not checking for null will compute invalid offsets that + // can cause an access violation during the field clean-up. + ILCodeLabel *pSkipComputeOffsetLabel = pcsSetup->NewCodeLabel(); + pcsSetup->EmitNOP("// field setup {"); pcsSetup->EmitNOP("// managed field setup {"); pcsSetup->EmitLDARG(StructMarshalStubs::MANAGED_STRUCT_ARGIDX); + pcsSetup->EmitDUP(); + pcsSetup->EmitBRFALSE(pSkipComputeOffsetLabel); pcsSetup->EmitLDC(managedOffset); pcsSetup->EmitADD(); + pcsSetup->EmitLabel(pSkipComputeOffsetLabel); EmitStoreManagedHomeAddr(pcsSetup); pcsSetup->EmitNOP("// } managed field setup"); pcsSetup->EmitNOP("// native field setup {"); diff --git a/src/coreclr/vm/interoplibinterface.h b/src/coreclr/vm/interoplibinterface.h index 367b419e2a3342..be99852b4e68d2 100644 --- a/src/coreclr/vm/interoplibinterface.h +++ b/src/coreclr/vm/interoplibinterface.h @@ -57,7 +57,7 @@ class ComWrappersNative static void MarkWrapperAsComActivated(_In_ IUnknown* wrapperMaybe); public: // Unwrapping support - static IUnknown* GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid, _Out_ INT64* wrapperId); + static IUnknown* GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid, _Out_ INT64* wrapperId, _Out_ bool* isAggregated); static bool HasManagedObjectComWrapper(_In_ OBJECTREF object, _Out_ bool* isActive); public: // GC interaction diff --git a/src/coreclr/vm/interoplibinterface_comwrappers.cpp b/src/coreclr/vm/interoplibinterface_comwrappers.cpp index 030cabfc3e92ea..fceb5ab419ed44 100644 --- a/src/coreclr/vm/interoplibinterface_comwrappers.cpp +++ b/src/coreclr/vm/interoplibinterface_comwrappers.cpp @@ -53,6 +53,9 @@ namespace // The EOC is "detached" and no longer used to map between identity and a managed object. // This will only be set if the EOC was inserted into the cache. Flags_Detached = 8, + + // This EOC is an aggregated instance + Flags_Aggregated = 16 }; DWORD Flags; @@ -176,7 +179,10 @@ namespace if (Result.Context != NULL) { GCX_PREEMP(); - InteropLib::Com::DestroyWrapperForExternal(Result.Context); + // We also request collection notification since this holder is presently + // only used for new activation of wrappers therefore the notification won't occur + // at the typical time of before finalization. + InteropLib::Com::DestroyWrapperForExternal(Result.Context, /* notifyIsBeingCollected */ true); } } InteropLib::Com::ExternalWrapperResult* operator&() @@ -309,52 +315,100 @@ namespace GC_TRIGGERS; MODE_COOPERATIVE; PRECONDITION(!IsLockHeld()); + PRECONDITION(!(withFlags & ExternalObjectContext::Flags_Collected)); + PRECONDITION(!(withFlags & ExternalObjectContext::Flags_Detached)); POSTCONDITION(RETVAL != NULL); } CONTRACT_END; struct { + PTRARRAYREF arrRefTmp; PTRARRAYREF arrRef; } gc; ::ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); + // Only add objects that are in the correct thread + // context, haven't been detached from the cache, and have + // the appropriate flags set. + // Define a macro predicate since it used in multiple places. + // If an instance is in the hashmap, it is active. This invariant + // holds because the GC is what marks and removes from the cache. +#define SELECT_OBJECT(XX) XX->ThreadContext == threadContext \ + && !XX->IsSet(ExternalObjectContext::Flags_Detached) \ + && (withFlags == ExternalObjectContext::Flags_None || XX->IsSet(withFlags)) + + // Determine the count of objects to return. + SIZE_T objCountMax = 0; + { + LockHolder lock(this); + Iterator end = _hashMap.End(); + for (Iterator curr = _hashMap.Begin(); curr != end; ++curr) + { + ExternalObjectContext* inst = *curr; + if (SELECT_OBJECT(inst)) + { + objCountMax++; + } + } + } + + // Allocate enumerable type to return. + gc.arrRef = (PTRARRAYREF)AllocateObjectArray((DWORD)objCountMax, g_pObjectClass); + CQuickArrayList localList; - // Determine objects to return + // Iterate over the hashmap again while populating the above array + // using the same predicate as before and holding onto context instances. + SIZE_T objCount = 0; + if (0 < objCountMax) { LockHolder lock(this); Iterator end = _hashMap.End(); for (Iterator curr = _hashMap.Begin(); curr != end; ++curr) { ExternalObjectContext* inst = *curr; - - // Only add objects that are in the correct thread - // context and have the appropriate flags set. - if (inst->ThreadContext == threadContext - && (withFlags == ExternalObjectContext::Flags_None || inst->IsSet(withFlags))) + if (SELECT_OBJECT(inst)) { localList.Push(inst); - STRESS_LOG1(LF_INTEROP, LL_INFO100, "Add EOC to Enumerable: 0x%p\n", inst); + + gc.arrRef->SetAt(objCount, inst->GetObjectRef()); + objCount++; + + STRESS_LOG1(LF_INTEROP, LL_INFO1000, "Add EOC to Enumerable: 0x%p\n", inst); } + + // There is a chance more objects were added to the hash while the + // lock was released during array allocation. Once we hit the computed max + // we stop to avoid looking longer than needed. + if (objCount == objCountMax) + break; } } - // Allocate enumerable type to return. - gc.arrRef = (PTRARRAYREF)AllocateObjectArray((DWORD)localList.Size(), g_pObjectClass); - - // Insert objects into enumerable. - // The ExternalObjectContexts in the hashmap are only - // removed and associated objects collected during a GC. Since - // this code is running in Cooperative mode they will never - // be null. - for (SIZE_T i = 0; i < localList.Size(); i++) +#undef SELECT_OBJECT + + // During the allocation of the array to return, a GC could have + // occurred and objects detached from this cache. In order to avoid + // having null array elements we will allocate a new array. + // This subsequent allocation is okay because the array we are + // replacing extends all object lifetimes. + if (objCount < objCountMax) { - ExternalObjectContext* inst = localList[i]; - gc.arrRef->SetAt(i, inst->GetObjectRef()); + gc.arrRefTmp = (PTRARRAYREF)AllocateObjectArray((DWORD)objCount, g_pObjectClass); + + void* dest = gc.arrRefTmp->GetDataPtr(); + void* src = gc.arrRef->GetDataPtr(); + SIZE_T elementSize = gc.arrRef->GetComponentSize(); + + memmoveGCRefs(dest, src, objCount * elementSize); + gc.arrRef = gc.arrRefTmp; } + // All objects are now referenced from the array so won't be collected + // at this point. This means we can safely iterate over the ExternalObjectContext + // instances. { // Separate the wrapper from the tracker runtime prior to // passing them onto the caller. This call is okay to make @@ -478,7 +532,11 @@ namespace if (!cxt->IsSet(ExternalObjectContext::Flags_Detached) && !GCHeapUtilities::GetGCHeap()->IsPromoted(OBJECTREFToObject(cxt->GetObjectRef()))) { + // Indicate the wrapper entry has been detached. cxt->MarkDetached(); + + // Notify the wrapper it was not promoted and is being collected. + InteropLib::Com::NotifyWrapperForExternalIsBeingCollected(cxt); } } } @@ -845,7 +903,11 @@ namespace : ExternalObjectContext::Flags_None) | (uniqueInstance ? ExternalObjectContext::Flags_None - : ExternalObjectContext::Flags_InCache); + : ExternalObjectContext::Flags_InCache) | + ((flags & CreateObjectFlags::CreateObjectFlags_Aggregated) != 0 + ? ExternalObjectContext::Flags_Aggregated + : ExternalObjectContext::Flags_None); + ExternalObjectContext::Construct( resultHolder.GetContext(), identity, @@ -1719,7 +1781,7 @@ bool GlobalComWrappersForTrackerSupport::TryGetOrCreateObjectForComInstance( objRef); } -IUnknown* ComWrappersNative::GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid, _Out_ INT64* wrapperId) +IUnknown* ComWrappersNative::GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid, _Out_ INT64* wrapperId, _Out_ bool* isAggregated) { CONTRACTL { @@ -1752,6 +1814,7 @@ IUnknown* ComWrappersNative::GetIdentityForObject(_In_ OBJECTREF* objectPROTECTE { ExternalObjectContext* context = reinterpret_cast(contextMaybe); *wrapperId = context->WrapperId; + *isAggregated = context->IsSet(ExternalObjectContext::Flags_Aggregated); IUnknown* identity = reinterpret_cast(context->Identity); GCX_PREEMP(); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index ea70bf8e0ac242..5f41caa0c3e85d 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -5572,7 +5572,7 @@ HCIMPL1_RAW(void, JIT_ReversePInvokeExitTrackTransitions, ReversePInvokeFrame* f #ifdef PROFILING_SUPPORTED if (CORProfilerTrackTransitions()) { - ProfilerUnmanagedToManagedTransitionMD(frame->pMD, COR_PRF_TRANSITION_RETURN); + ProfilerManagedToUnmanagedTransitionMD(frame->pMD, COR_PRF_TRANSITION_RETURN); } #endif } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 692c35eb6dae7e..75d3160dda7b1a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11946,6 +11946,50 @@ uint32_t CEEJitInfo::getExpectedTargetArchitecture() return IMAGE_FILE_MACHINE_NATIVE; } +bool CEEJitInfo::doesFieldBelongToClass(CORINFO_FIELD_HANDLE fldHnd, CORINFO_CLASS_HANDLE cls) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + bool result; + + JIT_TO_EE_TRANSITION(); + + FieldDesc* field = (FieldDesc*) fldHnd; + TypeHandle th(cls); + + _ASSERTE(!field->IsStatic()); + + // doesFieldBelongToClass implements the predicate of... + // if field is not associated with the class in any way, return false. + // if field is the only FieldDesc that the JIT might see for a given class handle + // and logical field pair then return true. This is needed as the field handle here + // is used as a key into a hashtable mapping writes to fields to value numbers. + // + // In the CoreCLR VM implementation, verifying that the canonical MethodTable of + // the field matches the type found via GetExactDeclaringType, as all instance fields + // are only held on the canonical MethodTable. + // This yields a truth table such as + + // BaseType._field, BaseType -> true + // BaseType._field, DerivedType -> true + // BaseType<__Canon>._field, BaseType<__Canon> -> true + // BaseType<__Canon>._field, BaseType -> true + // BaseType<__Canon>._field, BaseType -> true + // BaseType._field, BaseType -> true + // BaseType._field, BaseType -> false + + MethodTable* pMT = field->GetExactDeclaringType(th.GetMethodTable()); + result = (pMT != nullptr) && (pMT->GetCanonicalMethodTable() == field->GetApproxEnclosingMethodTable()->GetCanonicalMethodTable()); + + EE_TO_JIT_TRANSITION(); + + return result; +} + void CEEInfo::JitProcessShutdownWork() { LIMITED_METHOD_CONTRACT; @@ -14770,6 +14814,12 @@ uint32_t CEEInfo::getExpectedTargetArchitecture() return IMAGE_FILE_MACHINE_NATIVE; } +bool CEEInfo::doesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls) +{ + LIMITED_METHOD_CONTRACT; + UNREACHABLE_RET(); // only called on derived class. +} + void CEEInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap, ICorDebugInfo::OffsetMapping *pMap) { diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index c231cc865ccaea..a3378207880aae 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -693,6 +693,8 @@ class CEEJitInfo : public CEEInfo uint32_t getExpectedTargetArchitecture() override final; + bool doesFieldBelongToClass(CORINFO_FIELD_HANDLE fld, CORINFO_CLASS_HANDLE cls) override final; + void ResetForJitRetry() { CONTRACTL { diff --git a/src/coreclr/vm/object.cpp b/src/coreclr/vm/object.cpp index 36b100d6e9125a..af2201cbf4dce6 100644 --- a/src/coreclr/vm/object.cpp +++ b/src/coreclr/vm/object.cpp @@ -1033,6 +1033,41 @@ OBJECTREF::OBJECTREF(const OBJECTREF & objref) } +//------------------------------------------------------------- +// VolatileLoadWithoutBarrier constructor +//------------------------------------------------------------- +OBJECTREF::OBJECTREF(const OBJECTREF *pObjref, tagVolatileLoadWithoutBarrier tag) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_COOPERATIVE; + STATIC_CONTRACT_FORBID_FAULT; + + Object* objrefAsObj = VolatileLoadWithoutBarrier(&pObjref->m_asObj); + VALIDATEOBJECT(objrefAsObj); + + // !!! If this assert is fired, there are two possibilities: + // !!! 1. You are doing a type cast, e.g. *(OBJECTREF*)pObj + // !!! Instead, you should use ObjectToOBJECTREF(*(Object**)pObj), + // !!! or ObjectToSTRINGREF(*(StringObject**)pObj) + // !!! 2. There is a real GC hole here. + // !!! Either way you need to fix the code. + _ASSERTE(Thread::IsObjRefValid(pObjref)); + if ((objrefAsObj != 0) && + ((IGCHeap*)GCHeapUtilities::GetGCHeap())->IsHeapPointer( (BYTE*)this )) + { + _ASSERTE(!"Write Barrier violation. Must use SetObjectReference() to assign OBJECTREF's into the GC heap!"); + } + m_asObj = objrefAsObj; + + if (m_asObj != 0) { + ENABLESTRESSHEAP(); + } + + Thread::ObjectRefNew(this); +} + + //------------------------------------------------------------- // To allow NULL to be used as an OBJECTREF. //------------------------------------------------------------- diff --git a/src/coreclr/vm/object.h b/src/coreclr/vm/object.h index e35bd90fd68ab5..398b4f49030a2e 100644 --- a/src/coreclr/vm/object.h +++ b/src/coreclr/vm/object.h @@ -2418,7 +2418,7 @@ class ExceptionObject : public Object OBJECTREF GetInnerException() { LIMITED_METHOD_DAC_CONTRACT; - return _innerException; + return VolatileLoadWithoutBarrierOBJECTREF(&_innerException); } // Returns the innermost exception object - equivalent of the @@ -2431,7 +2431,7 @@ class ExceptionObject : public Object OBJECTREF oInnerMostException = NULL; OBJECTREF oCurrent = NULL; - oCurrent = _innerException; + oCurrent = GetInnerException(); while(oCurrent != NULL) { oInnerMostException = oCurrent; @@ -2469,7 +2469,7 @@ class ExceptionObject : public Object STRINGREF GetRemoteStackTraceString() { LIMITED_METHOD_DAC_CONTRACT; - return _remoteStackTraceString; + return (STRINGREF)VolatileLoadWithoutBarrierOBJECTREF(&_remoteStackTraceString); } void SetHelpURL(STRINGREF helpURL) @@ -2512,7 +2512,7 @@ class ExceptionObject : public Object U1ARRAYREF GetWatsonBucketReference() { LIMITED_METHOD_CONTRACT; - return _watsonBuckets; + return (U1ARRAYREF)VolatileLoadWithoutBarrierOBJECTREF(&_watsonBuckets); } // This method will return a BOOL to indicate if the @@ -2520,7 +2520,7 @@ class ExceptionObject : public Object BOOL AreWatsonBucketsPresent() { LIMITED_METHOD_CONTRACT; - return (_watsonBuckets != NULL)?TRUE:FALSE; + return (GetWatsonBucketReference() != NULL)?TRUE:FALSE; } // This method will save the IP to be used for watson bucketing. @@ -2545,7 +2545,7 @@ class ExceptionObject : public Object { LIMITED_METHOD_CONTRACT; - return _ipForWatsonBuckets; + return VolatileLoadWithoutBarrier(&_ipForWatsonBuckets); } // README: diff --git a/src/coreclr/vm/profilinghelper.cpp b/src/coreclr/vm/profilinghelper.cpp index ac2ea1469a4e3e..67bacc054bc265 100644 --- a/src/coreclr/vm/profilinghelper.cpp +++ b/src/coreclr/vm/profilinghelper.cpp @@ -166,7 +166,9 @@ void CurrentProfilerStatus::Set(ProfilerStatus newProfStatus) break; case kProfStatusNone: - _ASSERTE(newProfStatus == kProfStatusPreInitialize); + _ASSERTE((newProfStatus == kProfStatusPreInitialize) || + (newProfStatus == kProfStatusInitializingForStartupLoad) || + (newProfStatus == kProfStatusInitializingForAttachLoad)); break; case kProfStatusDetaching: @@ -1094,8 +1096,6 @@ HRESULT ProfilingAPIUtility::LoadProfiler( _ASSERTE((pvClientData == NULL) || (loadType == kAttachLoad)); ProfilerInfo profilerInfo; - // RAII type that will deregister if we bail at any point - ProfilerInfoHolder profilerInfoHolder(&profilerInfo); profilerInfo.Init(); profilerInfo.inUse = TRUE; @@ -1169,7 +1169,6 @@ HRESULT ProfilingAPIUtility::LoadProfiler( // Check if this profiler is notification only and load as appropriate BOOL notificationOnly = FALSE; { - EvacuationCounterHolder holder(&profilerInfo); HRESULT callHr = profilerInfo.pProfInterface->LoadAsNotficationOnly(¬ificationOnly); if (FAILED(callHr)) { @@ -1185,8 +1184,6 @@ HRESULT ProfilingAPIUtility::LoadProfiler( LogProfError(IDS_E_PROF_NOTIFICATION_LIMIT_EXCEEDED); return CORPROF_E_PROFILER_ALREADY_ACTIVE; } - - *pProfilerInfo = profilerInfo; } else { @@ -1197,13 +1194,14 @@ HRESULT ProfilingAPIUtility::LoadProfiler( return CORPROF_E_PROFILER_ALREADY_ACTIVE; } - // This profiler cannot be a notification only profiler, copy it over to the - // main slot and the ProfilerInfoHolder above will clear out the notification slot - g_profControlBlock.mainProfilerInfo = profilerInfo; + // This profiler cannot be a notification only profiler pProfilerInfo = &(g_profControlBlock.mainProfilerInfo); } + pProfilerInfo->curProfStatus.Set(profilerInfo.curProfStatus.Get()); + pProfilerInfo->pProfInterface = profilerInfo.pProfInterface; pProfilerInfo->pProfInterface->SetProfilerInfo(pProfilerInfo); + pProfilerInfo->inUse = TRUE; } // Now that the profiler is officially loaded and in Init status, call into the @@ -1396,8 +1394,6 @@ HRESULT ProfilingAPIUtility::LoadProfiler( } } - // Yay, the profiler is started up. Don't deregister it if we get to this point - profilerInfoHolder.SuppressRelease(); return S_OK; } @@ -1444,16 +1440,60 @@ BOOL ProfilingAPIUtility::IsProfilerEvacuated(ProfilerInfo *pProfilerInfo) // // (see // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization - // for details) - DWORD dwEvacCounter = pProfilerInfo->dwProfilerEvacuationCounter; - if (dwEvacCounter != 0) + // for details)Doing this under the thread store lock not only ensures we can + // iterate through the Thread objects safely, but also forces us to serialize with + // the GC. The latter is important, as server GC enters the profiler on non-EE + // Threads, and so no evacuation counters might be incremented during server GC even + // though control could be entering the profiler. { - LOG(( - LF_CORPROF, - LL_INFO100, - "**PROF: Profiler not yet evacuated because it has evac counter of %d (decimal).\n", - dwEvacCounter)); - return FALSE; + ThreadStoreLockHolder TSLockHolder; + + Thread * pThread = ThreadStore::GetAllThreadList( + NULL, // cursor thread; always NULL to begin with + 0, // mask to AND with Thread::m_State to filter returned threads + 0); // bits to match the result of the above AND. (m_State & 0 == 0, + // so we won't filter out any threads) + + // Note that, by not filtering out any of the threads, we're intentionally including + // stuff like TS_Dead or TS_Unstarted. But that keeps us on the safe + // side. If an EE Thread object exists, we want to check its counters to be + // absolutely certain it isn't executing in a profiler. + + while (pThread != NULL) + { + // Note that pThread is still in motion as we check its evacuation counter. + // This is ok, because we've already changed the profiler status to + // kProfStatusDetaching and flushed CPU buffers. So at this point the counter + // will typically only go down to 0 (and not increment anymore), with one + // small exception (below). So if we get a read of 0 below, the counter will + // typically stay there. Specifically: + // * pThread is most likely not about to increment its evacuation counter + // from 0 to 1 because pThread sees that the status is + // kProfStatusDetaching. + // * Note that there is a small race where pThread might actually + // increment its evac counter from 0 to 1 (if it dirty-read the + // profiler status a tad too early), but that implies that when + // pThread rechecks the profiler status (clean read) then pThread + // will immediately decrement the evac counter back to 0 and avoid + // calling into the EEToProfInterfaceImpl pointer. + // + // (see + // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization + // for details) + DWORD dwEvacCounter = pThread->GetProfilerEvacuationCounter(pProfilerInfo->slot); + if (dwEvacCounter != 0) + { + LOG(( + LF_CORPROF, + LL_INFO100, + "**PROF: Profiler not yet evacuated because OS Thread ID 0x%x has evac counter of %d (decimal).\n", + pThread->GetOSThreadId(), + dwEvacCounter)); + return FALSE; + } + + pThread = ThreadStore::GetAllThreadList(pThread, 0, 0); + } } // FUTURE: When rejit feature crew complete, add code to verify all rejitted diff --git a/src/coreclr/vm/profilinghelper.h b/src/coreclr/vm/profilinghelper.h index 1cf7ea4ab50005..ab64ee8287473c 100644 --- a/src/coreclr/vm/profilinghelper.h +++ b/src/coreclr/vm/profilinghelper.h @@ -136,11 +136,4 @@ class SetCallbackStateFlagsHolder DWORD m_dwOriginalFullState; }; -FORCEINLINE void DeregisterProfilerIfNotificationOnly(ProfilerInfo *pProfilerInfo) -{ - g_profControlBlock.DeRegisterProfilerInfo(pProfilerInfo); -} - -typedef Wrapper ProfilerInfoHolder; - #endif //__PROFILING_HELPER_H__ diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 40b3ce5b09476a..35bc318f1b20ea 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -719,20 +719,132 @@ struct GenerationDesc BYTE *rangeEndReserved; }; -struct GenerationTable -{ +class GenerationTable +{ +public: + GenerationTable(); + void AddRecord(int generation, BYTE* rangeStart, BYTE* rangeEnd, BYTE* rangeEndReserved); + void AddRecordNoLock(int generation, BYTE* rangeStart, BYTE* rangeEnd, BYTE* rangeEndReserved); + void Refresh(); + HRESULT GetGenerationBounds(ULONG cObjectRanges, ULONG* pcObjectRanges, COR_PRF_GC_GENERATION_RANGE* ranges); +private: + Crst mutex; ULONG count; ULONG capacity; static const ULONG defaultCapacity = 5; // that's the minimum for Gen0-2 + LOH + POH - GenerationTable *prev; GenerationDesc *genDescTable; -#ifdef _DEBUG - ULONG magic; -#define GENERATION_TABLE_MAGIC 0x34781256 -#define GENERATION_TABLE_BAD_MAGIC 0x55aa55aa -#endif }; +GenerationTable::GenerationTable() : mutex(CrstLeafLock, CRST_UNSAFE_ANYMODE) +{ + count = 0; + capacity = GenerationTable::defaultCapacity; + genDescTable = new (nothrow) GenerationDesc[capacity]; + if (genDescTable == NULL) + { + capacity = 0; + } +} + +void GenerationTable::AddRecord(int generation, BYTE* rangeStart, BYTE* rangeEnd, BYTE* rangeEndReserved) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; // can be called even on GC threads + PRECONDITION(0 <= generation && generation <= 4); + PRECONDITION(CheckPointer(rangeStart)); + PRECONDITION(CheckPointer(rangeEnd)); + PRECONDITION(CheckPointer(rangeEndReserved)); + } CONTRACT_END; + + CrstHolder holder(&mutex); + + // Because the segment/region are added to the heap before they are reported to the profiler, + // it is possible that the region is added to the heap, a racing GenerationTable refresh happened, + // that refresh would contain the new region, and then it get reported again here. + // This check will make sure we never add duplicated record to the table. + for (ULONG i = 0; i < count; i++) + { + if (genDescTable[i].rangeStart == rangeStart) + { + _ASSERTE (genDescTable[i].generation == generation); + _ASSERTE (genDescTable[i].rangeEnd == rangeEnd); + _ASSERTE (genDescTable[i].rangeEndReserved == rangeEndReserved); + RETURN; + } + } + AddRecordNoLock(generation, rangeStart, rangeEnd, rangeEndReserved); + RETURN; +} + +void GenerationTable::AddRecordNoLock(int generation, BYTE* rangeStart, BYTE* rangeEnd, BYTE* rangeEndReserved) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; // can be called even on GC threads + PRECONDITION(0 <= generation && generation <= 4); + PRECONDITION(CheckPointer(rangeStart)); + PRECONDITION(CheckPointer(rangeEnd)); + PRECONDITION(CheckPointer(rangeEndReserved)); + } CONTRACT_END; + + _ASSERTE (mutex.OwnedByCurrentThread()); + if (count >= capacity) + { + ULONG newCapacity = capacity == 0 ? GenerationTable::defaultCapacity : capacity * 2; + GenerationDesc *newGenDescTable = new (nothrow) GenerationDesc[newCapacity]; + if (newGenDescTable == NULL) + { + count = capacity = 0; + delete[] genDescTable; + genDescTable = nullptr; + RETURN; + } + memcpy(newGenDescTable, genDescTable, sizeof(genDescTable[0]) * count); + delete[] genDescTable; + genDescTable = newGenDescTable; + capacity = newCapacity; + } + _ASSERTE(count < capacity); + + genDescTable[count].generation = generation; + genDescTable[count].rangeStart = rangeStart; + genDescTable[count].rangeEnd = rangeEnd; + genDescTable[count].rangeEndReserved = rangeEndReserved; + + count = count + 1; + RETURN; +} + +HRESULT GenerationTable::GetGenerationBounds(ULONG cObjectRanges, ULONG* pcObjectRanges, COR_PRF_GC_GENERATION_RANGE* ranges) +{ + if ((cObjectRanges > 0) && (ranges == nullptr)) + { + return E_INVALIDARG; + } + CrstHolder holder(&mutex); + if (genDescTable == nullptr) + { + return E_FAIL; + } + ULONG copy = min(count, cObjectRanges); + for (ULONG i = 0; i < copy; i++) + { + ranges[i].generation = (COR_PRF_GC_GENERATION)genDescTable[i].generation; + ranges[i].rangeStart = (ObjectID)genDescTable[i].rangeStart; + ranges[i].rangeLength = genDescTable[i].rangeEnd - genDescTable[i].rangeStart; + ranges[i].rangeLengthReserved = genDescTable[i].rangeEndReserved - genDescTable[i].rangeStart; + } + if (pcObjectRanges != nullptr) + { + *pcObjectRanges = count; + } + return S_OK; +} //--------------------------------------------------------------------------------------- // @@ -769,46 +881,24 @@ static void GenWalkFunc(void * context, } CONTRACT_END; GenerationTable *generationTable = (GenerationTable *)context; + generationTable->AddRecordNoLock(generation, rangeStart, rangeEnd, rangeEndReserved); + RETURN; +} - _ASSERTE(generationTable->magic == GENERATION_TABLE_MAGIC); - - ULONG count = generationTable->count; - if (count >= generationTable->capacity) - { - ULONG newCapacity = generationTable->capacity == 0 ? GenerationTable::defaultCapacity : generationTable->capacity * 2; - GenerationDesc *newGenDescTable = new (nothrow) GenerationDesc[newCapacity]; - if (newGenDescTable == NULL) - { - // if we can't allocate a bigger table, we'll have to ignore this call - RETURN; - } - memcpy(newGenDescTable, generationTable->genDescTable, sizeof(generationTable->genDescTable[0]) * generationTable->count); - delete[] generationTable->genDescTable; - generationTable->genDescTable = newGenDescTable; - generationTable->capacity = newCapacity; - } - _ASSERTE(count < generationTable->capacity); - - GenerationDesc *genDescTable = generationTable->genDescTable; - - genDescTable[count].generation = generation; - genDescTable[count].rangeStart = rangeStart; - genDescTable[count].rangeEnd = rangeEnd; - genDescTable[count].rangeEndReserved = rangeEndReserved; - - generationTable->count = count + 1; +void GenerationTable::Refresh() +{ + // fill in the values by calling back into the gc, which will report + // the ranges by calling GenWalkFunc for each one + CrstHolder holder(&mutex); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); + this->count = 0; + hp->DiagDescrGenerations(GenWalkFunc, this); } // This is the table of generation bounds updated by the gc -// and read by the profiler. So this is a single writer, -// multiple readers scenario. +// and read by the profiler. static GenerationTable *s_currentGenerationTable; -// The generation table is updated atomically by replacing the -// pointer to it. The only tricky part is knowing when -// the old table can be deleted. -static Volatile s_generationTableLock; - // This is just so we can assert there's a single writer #ifdef ENABLE_CONTRACTS static Volatile s_generationTableWriterCount; @@ -837,67 +927,41 @@ void __stdcall UpdateGenerationBounds() // Notify the profiler of start of the collection if (CORProfilerTrackGC() || CORProfilerTrackBasicGC()) { - // generate a new generation table - GenerationTable *newGenerationTable = new (nothrow) GenerationTable(); - if (newGenerationTable == NULL) - RETURN; - newGenerationTable->count = 0; - newGenerationTable->capacity = GenerationTable::defaultCapacity; - // if there is already a current table, use its capacity as a guess for the capacity - if (s_currentGenerationTable != NULL) - newGenerationTable->capacity = s_currentGenerationTable->capacity; - newGenerationTable->prev = NULL; - newGenerationTable->genDescTable = new (nothrow) GenerationDesc[newGenerationTable->capacity]; - if (newGenerationTable->genDescTable == NULL) - newGenerationTable->capacity = 0; - -#ifdef _DEBUG - newGenerationTable->magic = GENERATION_TABLE_MAGIC; -#endif - // fill in the values by calling back into the gc, which will report - // the ranges by calling GenWalkFunc for each one - IGCHeap *hp = GCHeapUtilities::GetGCHeap(); - hp->DiagDescrGenerations(GenWalkFunc, newGenerationTable); - - // remember the old table and plug in the new one - GenerationTable *oldGenerationTable = s_currentGenerationTable; - s_currentGenerationTable = newGenerationTable; - // WARNING: tricky code! - // - // We sample the generation table lock *after* plugging in the new table - // We do so using an interlocked operation so the cpu can't reorder - // the write to the s_currentGenerationTable with the increment. - // If the interlocked increment returns 1, we know nobody can be using - // the old table (readers increment the lock before using the table, - // and decrement it afterwards). Any new readers coming in - // will use the new table. So it's safe to delete the old - // table. - // On the other hand, if the interlocked increment returns - // something other than one, we put the old table on a list - // dangling off of the new one. Next time around, we'll try again - // deleting any old tables. - if (FastInterlockIncrement(&s_generationTableLock) == 1) + if (s_currentGenerationTable == nullptr) { - // We know nobody can be using any of the old tables - while (oldGenerationTable != NULL) + EX_TRY { - _ASSERTE(oldGenerationTable->magic == GENERATION_TABLE_MAGIC); -#ifdef _DEBUG - oldGenerationTable->magic = GENERATION_TABLE_BAD_MAGIC; -#endif - GenerationTable *temp = oldGenerationTable; - oldGenerationTable = oldGenerationTable->prev; - delete[] temp->genDescTable; - delete temp; + s_currentGenerationTable = new (nothrow) GenerationTable(); } + EX_CATCH + { + } + EX_END_CATCH(SwallowAllExceptions) } - else + + if (s_currentGenerationTable == nullptr) { - // put the old table on a list - newGenerationTable->prev = oldGenerationTable; + RETURN; } - FastInterlockDecrement(&s_generationTableLock); + s_currentGenerationTable->Refresh(); + } +#endif // PROFILING_SUPPORTED + RETURN; +} + +void __stdcall ProfilerAddNewRegion(int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; // can be called even on GC threads + } CONTRACT_END; +#ifdef PROFILING_SUPPORTED + if (CORProfilerTrackGC() || CORProfilerTrackBasicGC()) + { + s_currentGenerationTable->AddRecord(generation, rangeStart, rangeEnd, rangeEndReserved); } #endif // PROFILING_SUPPORTED RETURN; @@ -1210,7 +1274,7 @@ bool AllocByClassHelper(Object * pBO, void * pv) _ASSERTE(pv != NULL); { - BEGIN_PROFILER_CALLBACK(CORProfilerTrackAllocations()); + BEGIN_PROFILER_CALLBACK(CORProfilerTrackGC()); // Pass along the call g_profControlBlock.AllocByClass( (ObjectID) pBO, @@ -1448,7 +1512,7 @@ HRESULT ProfToEEInterfaceImpl::SetEventMask(DWORD dwEventMask) "**PROF: SetEventMask 0x%08x.\n", dwEventMask)); - _ASSERTE(CORProfilerPresentOrInitializing()); + _ASSERTE(CORProfilerPresent()); return m_pProfilerInfo->pProfInterface->SetEventMask(dwEventMask, 0 /* No high bits */); } @@ -1480,7 +1544,7 @@ HRESULT ProfToEEInterfaceImpl::SetEventMask2(DWORD dwEventsLow, DWORD dwEventsHi "**PROF: SetEventMask2 0x%08x, 0x%08x.\n", dwEventsLow, dwEventsHigh)); - _ASSERTE(CORProfilerPresentOrInitializing()); + _ASSERTE(CORProfilerPresent()); return m_pProfilerInfo->pProfInterface->SetEventMask(dwEventsLow, dwEventsHigh); } @@ -8885,13 +8949,11 @@ HRESULT ProfToEEInterfaceImpl::GetGenerationBounds(ULONG cObjectRanges, // Yay! EE_THREAD_NOT_REQUIRED; - // Yay! - CANNOT_TAKE_LOCK; - + // Lock is required to ensure this is synchronized with GC's updates. + CAN_TAKE_LOCK; PRECONDITION(CheckPointer(pcObjectRanges)); PRECONDITION(cObjectRanges <= 0 || ranges != NULL); - PRECONDITION(s_generationTableLock >= 0); } CONTRACTL_END; @@ -8900,31 +8962,12 @@ HRESULT ProfToEEInterfaceImpl::GetGenerationBounds(ULONG cObjectRanges, LL_INFO1000, "**PROF: GetGenerationBounds.\n")); - // Announce we are using the generation table now - CounterHolder genTableLock(&s_generationTableLock); - - GenerationTable *generationTable = s_currentGenerationTable; - - if (generationTable == NULL) + if (s_currentGenerationTable == NULL) { return E_FAIL; } - _ASSERTE(generationTable->magic == GENERATION_TABLE_MAGIC); - - GenerationDesc *genDescTable = generationTable->genDescTable; - ULONG count = min(generationTable->count, cObjectRanges); - for (ULONG i = 0; i < count; i++) - { - ranges[i].generation = (COR_PRF_GC_GENERATION)genDescTable[i].generation; - ranges[i].rangeStart = (ObjectID)genDescTable[i].rangeStart; - ranges[i].rangeLength = genDescTable[i].rangeEnd - genDescTable[i].rangeStart; - ranges[i].rangeLengthReserved = genDescTable[i].rangeEndReserved - genDescTable[i].rangeStart; - } - - *pcObjectRanges = generationTable->count; - - return S_OK; + return s_currentGenerationTable->GetGenerationBounds(cObjectRanges, pcObjectRanges, ranges); } @@ -9020,7 +9063,6 @@ HRESULT ProfToEEInterfaceImpl::GetObjectGeneration(ObjectID objectId, PRECONDITION(objectId != NULL); PRECONDITION(CheckPointer(range)); - PRECONDITION(s_generationTableLock >= 0); } CONTRACTL_END; @@ -9032,36 +9074,22 @@ HRESULT ProfToEEInterfaceImpl::GetObjectGeneration(ObjectID objectId, _ASSERTE((GetThreadNULLOk() == NULL) || (GetThreadNULLOk()->PreemptiveGCDisabled())); - - - // Announce we are using the generation table now - CounterHolder genTableLock(&s_generationTableLock); - - GenerationTable *generationTable = s_currentGenerationTable; - - if (generationTable == NULL) - { - return E_FAIL; - } - _ASSERTE(generationTable->magic == GENERATION_TABLE_MAGIC); + IGCHeap *hp = GCHeapUtilities::GetGCHeap(); - GenerationDesc *genDescTable = generationTable->genDescTable; - ULONG count = generationTable->count; - for (ULONG i = 0; i < count; i++) - { - if (genDescTable[i].rangeStart <= (BYTE *)objectId && (BYTE *)objectId < genDescTable[i].rangeEndReserved) - { - range->generation = (COR_PRF_GC_GENERATION)genDescTable[i].generation; - range->rangeStart = (ObjectID)genDescTable[i].rangeStart; - range->rangeLength = genDescTable[i].rangeEnd - genDescTable[i].rangeStart; - range->rangeLengthReserved = genDescTable[i].rangeEndReserved - genDescTable[i].rangeStart; + uint8_t* pStart; + uint8_t* pAllocated; + uint8_t* pReserved; + unsigned int generation = hp->GetGenerationWithRange((Object*)objectId, &pStart, &pAllocated, &pReserved); - return S_OK; - } - } + UINT_PTR rangeLength = pAllocated - pStart; + UINT_PTR rangeLengthReserved = pReserved - pStart; - return E_FAIL; + range->generation = (COR_PRF_GC_GENERATION)generation; + range->rangeStart = (ObjectID)pStart; + range->rangeLength = rangeLength; + range->rangeLengthReserved = rangeLengthReserved; + return S_OK; } HRESULT ProfToEEInterfaceImpl::GetReJITIDs( diff --git a/src/coreclr/vm/syncblk.cpp b/src/coreclr/vm/syncblk.cpp index 1a2c9358bf1baa..b6e3f58bd21286 100644 --- a/src/coreclr/vm/syncblk.cpp +++ b/src/coreclr/vm/syncblk.cpp @@ -840,7 +840,7 @@ void SyncBlockCache::Grow() if (!(newSyncTableSize > m_SyncTableSize)) // Make sure we actually found room to grow! { - COMPlusThrowOM(); + EX_THROW(EEMessageException, (kOutOfMemoryException, IDS_EE_OUT_OF_SYNCBLOCKS)); } newSyncTable = new SyncTableEntry[newSyncTableSize]; diff --git a/src/coreclr/vm/syncblk.h b/src/coreclr/vm/syncblk.h index 3b79753069976e..2a7bfb34da5e04 100644 --- a/src/coreclr/vm/syncblk.h +++ b/src/coreclr/vm/syncblk.h @@ -621,6 +621,11 @@ class InteropSyncBlockInfo { LIMITED_METHOD_CONTRACT; ZeroMemory(this, sizeof(InteropSyncBlockInfo)); + +#if defined(FEATURE_COMWRAPPERS) + // The GC thread does enumerate these objects so add CRST_UNSAFE_COOPGC. + m_managedObjectComWrapperLock.Init(CrstManagedObjectWrapperMap, CRST_UNSAFE_COOPGC); +#endif // FEATURE_COMWRAPPERS } #ifndef DACCESS_COMPILE ~InteropSyncBlockInfo(); @@ -799,8 +804,6 @@ class InteropSyncBlockInfo if (FastInterlockCompareExchangePointer((ManagedObjectComWrapperByIdMap**)&m_managedObjectComWrapperMap, (ManagedObjectComWrapperByIdMap *)map, NULL) == NULL) { map.SuppressRelease(); - // The GC thread does enumerate these objects so add CRST_UNSAFE_COOPGC. - m_managedObjectComWrapperLock.Init(CrstManagedObjectWrapperMap, CRST_UNSAFE_COOPGC); } _ASSERTE(m_managedObjectComWrapperMap != NULL); diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index b38dc33185afbf..e454953181f1e5 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -1481,6 +1481,11 @@ Thread::Thread() m_fInteropDebuggingHijacked = FALSE; m_profilerCallbackState = 0; + for (int i = 0; i < MAX_NOTIFICATION_PROFILERS + 1; ++i) + { + m_dwProfilerEvacuationCounters[i] = 0; + } + m_pProfilerFilterContext = NULL; m_CacheStackBase = 0; diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index f579984f7ba21c..af2a7b32d31643 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -3667,6 +3667,16 @@ class Thread //--------------------------------------------------------------- DWORD m_profilerCallbackState; +#if defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA) + //--------------------------------------------------------------- + // m_dwProfilerEvacuationCounters keeps track of how many profiler + // callback calls remain on the stack + //--------------------------------------------------------------- + // Why volatile? + // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. + Volatile m_dwProfilerEvacuationCounters[MAX_NOTIFICATION_PROFILERS + 1]; +#endif // defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA) + private: UINT32 m_workerThreadPoolCompletionCount; static UINT64 s_workerThreadPoolCompletionCountOverflow; @@ -3799,6 +3809,38 @@ class Thread m_pProfilerFilterContext = pContext; } +#ifdef PROFILING_SUPPORTED + FORCEINLINE DWORD GetProfilerEvacuationCounter(size_t slot) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(slot >= 0 && slot <= MAX_NOTIFICATION_PROFILERS); + return m_dwProfilerEvacuationCounters[slot]; + } + + FORCEINLINE void IncProfilerEvacuationCounter(size_t slot) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(slot >= 0 && slot <= MAX_NOTIFICATION_PROFILERS); +#ifdef _DEBUG + DWORD newValue = +#endif // _DEBUG + ++m_dwProfilerEvacuationCounters[slot]; + _ASSERTE(newValue != 0U); + } + + FORCEINLINE void DecProfilerEvacuationCounter(size_t slot) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(slot >= 0 && slot <= MAX_NOTIFICATION_PROFILERS); +#ifdef _DEBUG + DWORD newValue = +#endif // _DEBUG + --m_dwProfilerEvacuationCounters[slot]; + _ASSERTE(newValue != (DWORD)-1); + } + +#endif // PROFILING_SUPPORTED + // Used by the profiler API to find which flags have been set on the Thread object, // in order to authorize a profiler's call into ICorProfilerInfo(2). DWORD GetProfilerCallbackFullState() diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 9400fd130132f6..ac857948d5137b 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -157,6 +157,8 @@ class OBJECTREF { }; public: + enum class tagVolatileLoadWithoutBarrier { tag }; + //------------------------------------------------------------- // Default constructor, for non-initializing declarations: // @@ -169,6 +171,12 @@ class OBJECTREF { //------------------------------------------------------------- OBJECTREF(const OBJECTREF & objref); + //------------------------------------------------------------- + // Copy constructor, for passing OBJECTREF's as function arguments + // using a volatile without barrier load + //------------------------------------------------------------- + OBJECTREF(const OBJECTREF * pObjref, tagVolatileLoadWithoutBarrier tag); + //------------------------------------------------------------- // To allow NULL to be used as an OBJECTREF. //------------------------------------------------------------- @@ -302,6 +310,7 @@ class REF : public OBJECTREF #define OBJECTREFToObject(objref) ((objref).operator-> ()) #define ObjectToSTRINGREF(obj) (STRINGREF(obj)) #define STRINGREFToObject(objref) (*( (StringObject**) &(objref) )) +#define VolatileLoadWithoutBarrierOBJECTREF(pObj) (OBJECTREF(pObj, OBJECTREF::tagVolatileLoadWithoutBarrier::tag)) // the while (0) syntax below is to force a trailing semicolon on users of the macro #define VALIDATEOBJECT(obj) do {if ((obj) != NULL) (obj)->Validate();} while (0) @@ -316,6 +325,7 @@ class REF : public OBJECTREF #define OBJECTREFToObject(objref) ((PTR_Object) (objref)) #define ObjectToSTRINGREF(obj) ((PTR_StringObject) (obj)) #define STRINGREFToObject(objref) ((PTR_StringObject) (objref)) +#define VolatileLoadWithoutBarrierOBJECTREF(pObj) VolatileLoadWithoutBarrier(pObj) #endif // _DEBUG_IMPL diff --git a/src/coreclr/vm/weakreferencenative.cpp b/src/coreclr/vm/weakreferencenative.cpp index ab2b6f9887c46e..c61467b8cf111e 100644 --- a/src/coreclr/vm/weakreferencenative.cpp +++ b/src/coreclr/vm/weakreferencenative.cpp @@ -108,6 +108,7 @@ struct WeakHandleSpinLockHolder // // In order to qualify to be used with a HNDTYPE_WEAK_NATIVE_COM, the incoming object must: // * be an RCW +// * not be an aggregated RCW // * respond to a QI for IWeakReferenceSource // * succeed when asked for an IWeakReference* // @@ -149,7 +150,14 @@ NativeComWeakHandleInfo* GetComWeakReferenceInfo(OBJECTREF* pObject) #endif { #ifdef FEATURE_COMWRAPPERS - pWeakReferenceSource = reinterpret_cast(ComWrappersNative::GetIdentityForObject(pObject, IID_IWeakReferenceSource, &wrapperId)); + bool isAggregated = false; + pWeakReferenceSource = reinterpret_cast(ComWrappersNative::GetIdentityForObject(pObject, IID_IWeakReferenceSource, &wrapperId, &isAggregated)); + if (isAggregated) + { + // If the RCW is an aggregated RCW, then the managed object cannot be recreated from the IUnknown as the outer IUnknown wraps the managed object. + // In this case, don't create a weak reference backed by a COM weak reference. + pWeakReferenceSource = nullptr; + } #endif } @@ -448,7 +456,7 @@ FCIMPL3(void, WeakReferenceNative::Create, WeakReferenceObject * pThisUNSAFE, Ob _ASSERTE(gc.pThis->GetMethodTable()->CanCastToClass(pWeakReferenceMT)); // Create the handle. -#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) NativeComWeakHandleInfo *comWeakHandleInfo = nullptr; if (gc.pTarget != NULL) { @@ -690,7 +698,7 @@ FCIMPL1(Object *, WeakReferenceNative::GetTarget, WeakReferenceObject * pThisUNS OBJECTREF pTarget = GetWeakReferenceTarget(pThis); -#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) // If we found an object, or we're not a native COM weak reference, then we're done. Othewrise // we can try to create a new RCW to the underlying native COM object if it's still alive. if (pTarget != NULL || !IsNativeComWeakReferenceHandle(pThis->m_Handle)) @@ -718,7 +726,7 @@ FCIMPL1(Object *, WeakReferenceOfTNative::GetTarget, WeakReferenceObject * pThis OBJECTREF pTarget = GetWeakReferenceTarget(pThis); -#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) +#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) // If we found an object, or we're not a native COM weak reference, then we're done. Othewrise // we can try to create a new RCW to the underlying native COM object if it's still alive. if (pTarget != NULL || !IsNativeComWeakReferenceHandle(pThis->m_Handle)) diff --git a/src/coreclr/vm/win32threadpool.cpp b/src/coreclr/vm/win32threadpool.cpp index 4f8646d73fa73a..7ffbc34948a471 100644 --- a/src/coreclr/vm/win32threadpool.cpp +++ b/src/coreclr/vm/win32threadpool.cpp @@ -4023,6 +4023,51 @@ DWORD WINAPI ThreadpoolMgr::GateThreadStart(LPVOID lpArgs) // CPU usage statistics int elementsNeeded = NumberOfProcessors > g_SystemInfo.dwNumberOfProcessors ? NumberOfProcessors : g_SystemInfo.dwNumberOfProcessors; + + // + // When CLR threads are not using all groups, GetCPUBusyTime_NT will read element X from + // the "prevCPUInfo.usageBuffer" array if and only if "prevCPUInfo.affinityMask" contains a + // set bit in bit position X. This implies that GetCPUBusyTime_NT would read past the end + // of the "usageBuffer" array if the index of the highest set bit in "affinityMask" was + // ever larger than the index of the last array element. + // + // If necessary, expand "elementsNeeded" to ensure that the index of the last array element + // is always at least as large as the index of the highest set bit in the "affinityMask". + // + // This expansion is necessary in any case where the mask returned by GetCurrentProcessCpuMask + // (which is just a wrapper around the Win32 GetProcessAffinityMask API) contains set bits + // at indices greater than or equal to the larger of the basline CPU count values (i.e., + // ThreadpoolMgr::NumberOfProcessors and g_SystemInfo.dwNumberOfProcessors) that were + // captured earlier on (during ThreadpoolMgr::Initialize and during EEStartupHelper, + // respectively). Note that in the relevant scenario (i.e., when CLR threads are not using + // all groups) the mask and CPU counts are all collected via "group-unaware" APIs and are + // all "group-local" values as a result. + // + // Expansion is necessary in at least the following cases: + // + // - If the baseline CPU counts were captured while running in groups that contain fewer + // CPUs (in a multi-group system with heterogenous CPU counts across groups), but this code + // is now running in a group that contains a larger number of CPUs. + // + // - If CPUs were hot-added to the system and then added to the current process affinity + // mask at some point after the baseline CPU counts were captured. + // + if (!CPUGroupInfo::CanEnableThreadUseAllCpuGroups()) + { + int elementsNeededToCoverMask = 0; + DWORD_PTR remainingMask = prevCPUInfo.affinityMask; + while (remainingMask != 0) + { + elementsNeededToCoverMask++; + remainingMask >>= 1; + } + + if (elementsNeeded < elementsNeededToCoverMask) + { + elementsNeeded = elementsNeededToCoverMask; + } + } + if (!ClrSafeInt::multiply(elementsNeeded, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), prevCPUInfo.usageBufferSize)) return 0; diff --git a/src/installer/Directory.Build.targets b/src/installer/Directory.Build.targets index c6e8cf1a140291..dccb8277ba7674 100644 --- a/src/installer/Directory.Build.targets +++ b/src/installer/Directory.Build.targets @@ -15,5 +15,5 @@ - + diff --git a/src/installer/pkg/Directory.Build.props b/src/installer/pkg/Directory.Build.props index 10f36b399c73b6..f51718676368a2 100644 --- a/src/installer/pkg/Directory.Build.props +++ b/src/installer/pkg/Directory.Build.props @@ -3,7 +3,6 @@ $(TargetArchitecture) - $(ArtifactsBinDir)$(OutputRid).$(Configuration)\corehost diff --git a/src/installer/pkg/THIRD-PARTY-NOTICES.TXT b/src/installer/pkg/THIRD-PARTY-NOTICES.TXT index 445eab67c7ff77..f9fae685f9cf00 100644 --- a/src/installer/pkg/THIRD-PARTY-NOTICES.TXT +++ b/src/installer/pkg/THIRD-PARTY-NOTICES.TXT @@ -875,8 +875,103 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License notice for musl +----------------------- + +musl as a whole is licensed under the following standard MIT license: + +Copyright © 2005-2020 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for "Faster Unsigned Division by Constants" +---------------------------------------------------------- + +Reference implementations of computing and using the "magic number" approach to dividing +by constants, including codegen instructions. The unsigned division incorporates the +"round down" optimization per ridiculous_fish. + +This is free and unencumbered software. Any copyright is dedicated to the Public Domain. + +License notice for mimalloc +--------------------------- + +MIT License + +Copyright (c) 2019 Microsoft Corporation, Daan Leijen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +License notice for Apple header files +------------------------------------- + +Copyright (c) 1980, 1986, 1993 + The Regents of the University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the University of + California, Berkeley and its contributors. +4. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + License notice for Angular v8.0 --------------------------------------------- +-------------------------------- + The MIT License (MIT) ===================== @@ -900,8 +995,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -License notice for corefx - License notice for BedrockFramework =================================== @@ -1211,3 +1304,172 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License for fastmod (https://github.com/lemire/fastmod) and ibm-fpgen (https://github.com/nigeltao/parse-number-fxx-test-data) +-------------------------------------- + + Copyright 2018 Daniel Lemire + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +License notice for JavaScript queues +------------------------------------- + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. + +Statement of Purpose +The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). +Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. +For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: +the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; +moral rights retained by the original author(s) and/or performer(s); +publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; +rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; +rights protecting the extraction, dissemination, use and reuse of data in a Work; +database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and +other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. +2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. +3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. +4. Limitations and Disclaimers. +a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. +b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. +c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. +d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. + +License notice for MSBuild Locator +------------------------------------- + +https://github.com/Microsoft/MSBuildLocator + +Copyright (c) 2018 .NET Foundation and Contributors + +This software is licensed subject to the MIT license, available at +https://opensource.org/licenses/MIT + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for Newtonsoft.Json +=================================== + +The MIT License (MIT) + +Copyright (c) 2007 James Newton-King + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License notice for NuGet.Client +------------------------------- + +In reference to: https://github.com/dotnet/templating/blob/main/build/nuget.exe + +https://github.com/NuGet/NuGet.Client/blob/dev/LICENSE.txt + +Copyright (c) .NET Foundation. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +these files except in compliance with the License. You may obtain a copy of the +License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed +under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. + +License notice for Roslyn Clr Heap Allocation Analyzer +------------------------------------- + +https://github.com/Microsoft/RoslynClrHeapAllocationAnalyzer + +Copyright (c) 2018 Microsoft Corporation + +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + +License notice for StyleCop Analyzers +------------------------------------- + +The MIT License (MIT) + +Copyright (c) Tunnel Vision Laboratories, LLC + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +License notice for corefx +------------------------------------- + +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/installer/pkg/projects/Directory.Build.targets b/src/installer/pkg/projects/Directory.Build.targets index 095938d03a4f84..f985295d2cd28d 100644 --- a/src/installer/pkg/projects/Directory.Build.targets +++ b/src/installer/pkg/projects/Directory.Build.targets @@ -6,6 +6,14 @@ Needs to happen in Directory.Build.targets to allow all the pkgproj's to set Version property first. --> $(Version) + + + $(PackageOutputPath) + + + <_Crossgen2SymbolFilesToPackage Include="@(Reference->'$(CoreCLRArtifactsPath)PDB\%(FileName).pdb')" /> + + <_Crossgen2SymbolFilesToPackage Include="@(NativeRuntimeAsset->'$(CoreCLRArtifactsPdbDir)%(FileName).pdb')" Condition="'$(TargetOS)' == 'windows' and '%(FileName)' != 'crossgen2'" /> + <_Crossgen2SymbolFilesToPackage Include="@(NativeRuntimeAsset->'$(CoreCLRArtifactsPath)%(FileName)%(Extension)$(SymbolsSuffix)')" Condition="'$(TargetOS)' != 'windows' and '%(FileName)' != 'crossgen2'" /> + <_Crossgen2SymbolFilesToPackage Remove="@(_Crossgen2SymbolFilesToPackage)" Condition="!Exists('%(Identity)')" /> + + <_SymbolFilesToPackage Include="@(_Crossgen2SymbolFilesToPackage)" TargetPath="tools/" /> + + + <_diaSymTargetArch>$(TargetArchitecture) diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Ref.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Ref.sfxproj index f1e52a78e99c12..18a665f80baac5 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Ref.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Ref.sfxproj @@ -4,6 +4,7 @@ TargetingPack true + false dotnet-targeting-pack dotnet-targeting-pack $(SharedFrameworkName).PGO @@ -19,4 +20,8 @@ + + + + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj index a3f364815d63c4..7d5a874a8547d1 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.Composite.sfxproj @@ -7,7 +7,7 @@ dotnet-runtime-internal-composite $(SharedFrameworkName).Composite $(SharedFrameworkName).Composite.PGO - true + true dotnet-runtime-composite-symbols true true diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj index 4fa48f4e0c96cc..ae250acbad5a29 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.sfxproj @@ -8,7 +8,7 @@ dotnet-runtime dotnet-runtime-internal $(SharedFrameworkName).PGO - true + true dotnet-runtime-symbols NetCore.SharedFramework true diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/PlatformManifest.txt b/src/installer/pkg/sfx/Microsoft.NETCore.App/PlatformManifest.txt new file mode 100644 index 00000000000000..981251ae96d2bf --- /dev/null +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/PlatformManifest.txt @@ -0,0 +1,338 @@ +System.Globalization.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Globalization.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +System.IO.Compression.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.IO.Compression.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.IO.Compression.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Net.Http.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Net.Http.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Net.Http.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Net.Security.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Net.Security.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Net.Security.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Security.Cryptography.Native.Apple.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Security.Cryptography.Native.Apple.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Security.Cryptography.Native.OpenSsl.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Security.Cryptography.Native.OpenSsl.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Security.Cryptography.Native.OpenSsl.so|Microsoft.NETCore.App.Ref||0.0.0.0 +clrcompression.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +Microsoft.CSharp.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +Microsoft.VisualBasic.Core.dll|Microsoft.NETCore.App.Ref|11.0.0.0|6.0.21.52210 +Microsoft.Win32.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +Microsoft.Win32.Registry.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.AppContext.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Buffers.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Collections.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Collections.Concurrent.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Collections.Immutable.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Collections.NonGeneric.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Collections.Specialized.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ComponentModel.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ComponentModel.Annotations.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ComponentModel.EventBasedAsync.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ComponentModel.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ComponentModel.TypeConverter.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Console.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Data.Common.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Data.DataSetExtensions.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Diagnostics.Contracts.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.Debug.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.DiagnosticSource.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.FileVersionInfo.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.Process.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.StackTrace.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.TextWriterTraceListener.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.Tools.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.TraceSource.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Diagnostics.Tracing.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Drawing.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Dynamic.Runtime.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Formats.Asn1.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Globalization.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Globalization.Calendars.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Globalization.Extensions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.Compression.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.Compression.Brotli.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.Compression.ZipFile.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.FileSystem.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.FileSystem.AccessControl.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.FileSystem.DriveInfo.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.FileSystem.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.FileSystem.Watcher.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.IsolatedStorage.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.MemoryMappedFiles.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.Pipes.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.Pipes.AccessControl.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.IO.UnmanagedMemoryStream.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Linq.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Linq.Expressions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Linq.Parallel.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Linq.Queryable.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Memory.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Http.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Http.Json.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.HttpListener.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Mail.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.NameResolution.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.NetworkInformation.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Ping.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Quic.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Requests.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Security.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.ServicePoint.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.Sockets.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.WebClient.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.WebHeaderCollection.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.WebProxy.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.WebSockets.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Net.WebSockets.Client.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Numerics.Vectors.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ObjectModel.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.DataContractSerialization.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Runtime.InteropServices.JavaScript.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Uri.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Xml.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Xml.Linq.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.DispatchProxy.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.Emit.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.Emit.ILGeneration.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.Emit.Lightweight.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.Extensions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.Metadata.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Reflection.TypeExtensions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Resources.Reader.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Resources.ResourceManager.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Resources.Writer.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.CompilerServices.Unsafe.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.CompilerServices.VisualC.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Extensions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Handles.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.InteropServices.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.InteropServices.RuntimeInformation.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Intrinsics.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Loader.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Numerics.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Serialization.Formatters.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Serialization.Json.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Serialization.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Runtime.Serialization.Xml.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.AccessControl.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Claims.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.Algorithms.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.Cng.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.Csp.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.Encoding.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.OpenSsl.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.Primitives.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Cryptography.X509Certificates.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Principal.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.Principal.Windows.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Security.SecureString.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Text.Encoding.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Text.Encoding.CodePages.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Text.Encoding.Extensions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Text.Encodings.Web.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Text.Json.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Text.RegularExpressions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Channels.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Overlapped.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Tasks.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Tasks.Dataflow.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Tasks.Extensions.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Tasks.Parallel.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Thread.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.ThreadPool.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Threading.Timer.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Transactions.Local.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.ValueTuple.dll|Microsoft.NETCore.App.Ref|4.0.3.0|6.0.21.52210 +System.Web.HttpUtility.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Xml.ReaderWriter.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Xml.XDocument.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Xml.XmlDocument.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Xml.XmlSerializer.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Xml.XPath.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Xml.XPath.XDocument.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +mscorlib.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +Microsoft.VisualBasic.dll|Microsoft.NETCore.App.Ref|10.0.0.0|6.0.21.52210 +System.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.ComponentModel.DataAnnotations.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Configuration.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Core.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Data.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Drawing.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.IO.Compression.FileSystem.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Net.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Numerics.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Runtime.Serialization.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Security.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.ServiceProcess.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.ServiceModel.Web.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Transactions.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Web.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Windows.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Xml.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Xml.Serialization.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +System.Xml.Linq.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +WindowsBase.dll|Microsoft.NETCore.App.Ref|4.0.0.0|6.0.21.52210 +netstandard.dll|Microsoft.NETCore.App.Ref|2.1.0.0|6.0.21.52210 +System.Private.CoreLib.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.DataContractSerialization.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Uri.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Xml.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +System.Private.Xml.Linq.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +libSystem.Globalization.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Globalization.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.IO.Compression.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.IO.Compression.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.IO.Compression.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Net.Http.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Net.Http.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Net.Http.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Net.Security.Native.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Net.Security.Native.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Net.Security.Native.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.Apple.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.Apple.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.Android.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.Android.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.OpenSsl.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.OpenSsl.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libSystem.Security.Cryptography.Native.OpenSsl.so|Microsoft.NETCore.App.Ref||0.0.0.0 +coreclr.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libcoreclr.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libcoreclr.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +clretwrc.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +clrjit.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libclrjit.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libclrjit.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +dbgshim.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libdbgshim.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libdbgshim.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +mscordaccore.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libmscordaccore.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libmscordaccore.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +mscordbi.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libmscordbi.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libmscordbi.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +mscorrc.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +api-ms-win-core-console-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-console-l1-2-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-datetime-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-debug-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-errorhandling-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-file-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-file-l1-2-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-file-l2-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-handle-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-heap-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-interlocked-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-libraryloader-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-localization-l1-2-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-memory-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-namedpipe-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-processenvironment-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-processthreads-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-processthreads-l1-1-1.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-profile-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-rtlsupport-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-string-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-synch-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-synch-l1-2-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-sysinfo-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-timezone-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-core-util-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-conio-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-convert-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-environment-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-filesystem-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-heap-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-locale-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-math-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-multibyte-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-private-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-process-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-runtime-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-stdio-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-string-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-time-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +api-ms-win-crt-utility-l1-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +API-MS-Win-core-xstate-l2-1-0.dll|Microsoft.NETCore.App.Ref||10.0.19041.1 +ucrtbase.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +msquic.dll|Microsoft.NETCore.App.Ref||1.8.0.0 +System.IO.Compression.Native.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +createdump.exe|Microsoft.NETCore.App.Ref||6.0.21.52210 +createdump|Microsoft.NETCore.App.Ref||0.0.0.0 +libcoreclrtraceptprovider.so|Microsoft.NETCore.App.Ref||0.0.0.0 +Microsoft.DiaSymReader.Native.x86.dll|Microsoft.NETCore.App.Ref||14.28.29715.1 +Microsoft.DiaSymReader.Native.amd64.dll|Microsoft.NETCore.App.Ref||14.28.29715.1 +Microsoft.DiaSymReader.Native.arm.dll|Microsoft.NETCore.App.Ref||14.28.29715.1 +Microsoft.DiaSymReader.Native.arm64.dll|Microsoft.NETCore.App.Ref||14.28.29715.1 +libmonosgen-2.0.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmonosgen-2.0.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmonosgen-2.0.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libmonosgen-2.0.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +llc|Microsoft.NETCore.App.Ref||0.0.0.0 +mono-aot-cross|Microsoft.NETCore.App.Ref||0.0.0.0 +mono-aot-cross.exe|Microsoft.NETCore.App.Ref||6.0.21.52210 +opt|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-diagnostics_tracing.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libmono-component-diagnostics_tracing.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-diagnostics_tracing.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-diagnostics_tracing-static.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-diagnostics_tracing-stub-static.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-diagnostics_tracing-static.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-diagnostics_tracing-stub-static.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-hot_reload.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libmono-component-hot_reload.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-hot_reload.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-hot_reload-static.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-hot_reload-stub-static.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-hot_reload-static.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-hot_reload-stub-static.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-debugger.dll|Microsoft.NETCore.App.Ref||6.0.21.52210 +libmono-component-debugger.so|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-debugger.dylib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-debugger-static.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-debugger-stub-static.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-debugger-static.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-component-debugger-stub-static.lib|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-ee-interp.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-icall-table.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-ilgen.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libmono-profiler-aot.a|Microsoft.NETCore.App.Ref||0.0.0.0 +System.Private.Runtime.InteropServices.Javascript.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +dotnet.js|Microsoft.NETCore.App.Ref||0.0.0.0 +dotnet.wasm|Microsoft.NETCore.App.Ref||0.0.0.0 +dotnet.timezones.blat|Microsoft.NETCore.App.Ref||0.0.0.0 +icudt.dat|Microsoft.NETCore.App.Ref||0.0.0.0 +icudt_no_CJK.dat|Microsoft.NETCore.App.Ref||0.0.0.0 +icudt_CJK.dat|Microsoft.NETCore.App.Ref||0.0.0.0 +icudt_EFIGS.dat|Microsoft.NETCore.App.Ref||0.0.0.0 +icudt_optimal.dat|Microsoft.NETCore.App.Ref||0.0.0.0 +icudt_optimal_no_CJK.dat|Microsoft.NETCore.App.Ref||0.0.0.0 +binding_support.js|Microsoft.NETCore.App.Ref||0.0.0.0 +dotnet_support.js|Microsoft.NETCore.App.Ref||0.0.0.0 +library_mono.js|Microsoft.NETCore.App.Ref||0.0.0.0 +pal_random.js|Microsoft.NETCore.App.Ref||0.0.0.0 +corebindings.c|Microsoft.NETCore.App.Ref||0.0.0.0 +driver.c|Microsoft.NETCore.App.Ref||0.0.0.0 +pinvoke.c|Microsoft.NETCore.App.Ref||0.0.0.0 +pinvoke.h|Microsoft.NETCore.App.Ref||0.0.0.0 +emcc-default.rsp|Microsoft.NETCore.App.Ref||0.0.0.0 +emcc-props.json|Microsoft.NETCore.App.Ref||0.0.0.0 +libicudata.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libicui18n.a|Microsoft.NETCore.App.Ref||0.0.0.0 +libicuuc.a|Microsoft.NETCore.App.Ref||0.0.0.0 +mscordaccore_amd64_amd64_6.0.21.52210.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 +mscordaccore_amd64_amd64_6.0.21.52210.dll|Microsoft.NETCore.App.Ref|6.0.0.0|6.0.21.52210 diff --git a/src/installer/pkg/sfx/bundle/osx_resources/cs.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/cs.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/cs.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/cs.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/de.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/de.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/de.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/de.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/en.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/en.lproj/conclusion.html index 40f415ad8d9b72..a41e496b2e46aa 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/en.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/en.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/es.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/es.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/es.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/es.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/fr.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/fr.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/fr.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/fr.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/it.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/it.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/it.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/it.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/ja.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/ja.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/ja.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/ja.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/ko.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/ko.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/ko.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/ko.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/pl.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/pl.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/pl.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/pl.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/bundle/osx_resources/pt-br.lproj/conclusion.html b/src/installer/pkg/sfx/bundle/osx_resources/pt-br.lproj/conclusion.html index e16c4b3148bcd4..af3bf5fd20ea09 100644 --- a/src/installer/pkg/sfx/bundle/osx_resources/pt-br.lproj/conclusion.html +++ b/src/installer/pkg/sfx/bundle/osx_resources/pt-br.lproj/conclusion.html @@ -5,7 +5,7 @@
-

The following was installed at /usr/local/share/dotnet +

The following was installed

  • {SharedFxBrandName}
diff --git a/src/installer/pkg/sfx/installers/dotnet-host.proj b/src/installer/pkg/sfx/installers/dotnet-host.proj index 953b0f4f8522f9..184770cb8c6089 100644 --- a/src/installer/pkg/sfx/installers/dotnet-host.proj +++ b/src/installer/pkg/sfx/installers/dotnet-host.proj @@ -4,6 +4,7 @@ true dotnet-host dotnet-host-internal + / Host NetCore.SharedHost true @@ -11,21 +12,27 @@ sharedhost Dotnet_CLI_SharedHost HostSrc + afterInstallExecute false true sharedhost false - osx_scripts/host + osx_scripts/host The .NET Shared Host. - $(MSBuildThisFileDirectory)rpm_scripts/host - $(RpmScriptsDirectory)/after_install.sh - $(RpmScriptsDirectory)/after_remove.sh + + {FD6988BF-5CCB-4202-3752-072442B1070B} + {97C9F490-5379-6902-7B80-D2723CA59D95} + {181630A5-53EA-4D70-E563-06F64946DE38} + + + + @@ -35,21 +42,37 @@ + + <_DestinationPath>$(OutputPath) + <_DestinationPath Condition="'$(BuildRpmPackage)' == 'true'">$(OutputPath)usr/share/dotnet/ + <_UsrBinPath>$(OutputPath)usr/bin/ + + + + + + Destination="$(_DestinationPath)dotnet$(ExeSuffix)" /> + Destination="$(_DestinationPath)ThirdPartyNotices.txt" /> + + + + @@ -71,11 +94,43 @@ - - + + + <_MacOSIntermediatesPath>$(IntermediateOutputPath)macos/ + + $(_MacOSIntermediatesPath)scripts + + + <_MacOSScript Include="$(MacOSScriptsTemplateDirectory)/*" Destination="$(MacOSScriptsDirectory)/%(FileName)%(Extension)"/> + + + + + <_UnameMachineRegex>$(InstallerTargetArchitecture) + <_UnameMachineRegex Condition="'$(InstallerTargetArchitecture)' == 'arm64'">arm64|aarch64 + <_UnameMachineRegex Condition="'$(InstallerTargetArchitecture)' == 'x64'">amd64|x86_64 + <_MacOSScriptsTemplateProperties>InstallerTargetArchitecture=$(InstallerTargetArchitecture);UnameMachineRegex=$(_UnameMachineRegex) + + + + + + + + + + + + diff --git a/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj b/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj index 2c5fa5d8188867..b9eb792a38fade 100644 --- a/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj +++ b/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj @@ -14,7 +14,6 @@ HostFxrSrc true hostfxr - osx_scripts/hostfxr The .NET HostFxr diff --git a/src/installer/pkg/sfx/installers/host.wxs b/src/installer/pkg/sfx/installers/host.wxs index 773246beb70f1a..6ff59fa6c29c83 100644 --- a/src/installer/pkg/sfx/installers/host.wxs +++ b/src/installer/pkg/sfx/installers/host.wxs @@ -24,8 +24,29 @@ + + + + + + + + + + + + + + + + + + NOT NON_NATIVE_ARCHITECTURE + + + - + @@ -47,6 +68,16 @@ + + + + - - + + + + + NON_NATIVE_ARCHITECTURE + + + \ No newline at end of file diff --git a/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall b/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall index 531cb93fd382fc..3eba436d925092 100755 --- a/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall +++ b/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. @@ -6,13 +6,23 @@ PACKAGE=$1 INSTALL_DESTINATION=$2 +[ "${InstallerTargetArchitecture}" == "x64" ] && X64_INSTALL_DESTINATION=$2 || X64_INSTALL_DESTINATION=$2/x64 # A temporary fix for the permissions issue(s) chmod 755 $INSTALL_DESTINATION/dotnet -# Add the installation directory to the system-wide paths -# But first create the directory if it doesn't exist -mkdir -p /etc/paths.d -echo $INSTALL_DESTINATION | tee /etc/paths.d/dotnet +mkdir -p /etc/dotnet +# set install_location (legacy location) to x64 location (regardless of wether or not we're installing x64) +echo $X64_INSTALL_DESTINATION | tee /etc/dotnet/install_location +# set install_location_arch to point to this installed location +echo $INSTALL_DESTINATION | tee /etc/dotnet/install_location_${InstallerTargetArchitecture} + +# if we're running on the native architecture +if [[ "$(uname -m)" =~ ${UnameMachineRegex} && "$(sysctl -i -n sysctl.proc_translated)" != "1" ]]; then + # Add the installation directory to the system-wide paths + # But first create the directory if it doesn't exist + mkdir -p /etc/paths.d + echo $INSTALL_DESTINATION | tee /etc/paths.d/dotnet +fi exit 0 diff --git a/src/installer/pkg/sfx/installers/osx_scripts/hostfxr/postinstall b/src/installer/pkg/sfx/installers/osx_scripts/hostfxr/postinstall deleted file mode 100755 index 2d0ceb82786936..00000000000000 --- a/src/installer/pkg/sfx/installers/osx_scripts/hostfxr/postinstall +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -# -# Licensed to the .NET Foundation under one or more agreements. -# The .NET Foundation licenses this file to you under the MIT license. -# - -PACKAGE=$1 -INSTALL_DESTINATION=$2 - -# A temporary fix for the permissions issue(s) -chmod 755 $INSTALL_DESTINATION/dotnet - -# Add the installation directory to the system-wide paths -echo $INSTALL_DESTINATION | tee /etc/paths.d/dotnet - -exit 0 diff --git a/src/installer/prepare-artifacts.proj b/src/installer/prepare-artifacts.proj index 159125bc2d03d5..228c234ae4ff0e 100644 --- a/src/installer/prepare-artifacts.proj +++ b/src/installer/prepare-artifacts.proj @@ -122,6 +122,10 @@ $(InstallersRelativePath)workloads/$(SdkBandVersion)/%(Filename)%(Extension) true + + + + diff --git a/src/installer/tests/Assets/TestProjects/AppWithSubDirs/Program.cs b/src/installer/tests/Assets/TestProjects/AppWithSubDirs/Program.cs index c1a31dec98665a..0a5d0149fff216 100644 --- a/src/installer/tests/Assets/TestProjects/AppWithSubDirs/Program.cs +++ b/src/installer/tests/Assets/TestProjects/AppWithSubDirs/Program.cs @@ -12,6 +12,21 @@ public static void Main(string[] args) { string baseDir = Path.Combine(AppContext.BaseDirectory, "Sentence"); + // singlefile app redirects a number of known internal PInvokes to their implementations + // which are statically linked into the host. + // Use of File IO, Console APIs and the like uses and tests those mechanisms extensively. + // + // There are also two PInvokes in the hostpolicy itself. Test them here. + // We are not looking for a success, just that we can get to these methods - + // we should not see errors like "Unable to find an entry point". + try + { + new System.Runtime.Loader.AssemblyDependencyResolver("qwerty"); + } + catch (InvalidOperationException ex) when (ex.Message.Contains("Failed to locate managed application")) + { + } + string Part(string dir="", string subdir="", string subsubdir="") { return File.ReadAllText(Path.Combine(baseDir, dir, subdir, subsubdir, "word")); diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs index 5a8830556f54b6..6f637a1f586907 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs @@ -77,7 +77,7 @@ public DotNetFramework RuntimeConfig(Action runtimeConfigCustomiz { string runtimeConfigPath = Path.Combine(_path, _name + ".runtimeconfig.json"); _backup.Backup(runtimeConfigPath); - RuntimeConfig runtimeConfig = HostActivation.RuntimeConfig.FromFile(runtimeConfigPath); + RuntimeConfig runtimeConfig = Test.RuntimeConfig.FromFile(runtimeConfigPath); runtimeConfigCustomizer(runtimeConfig); runtimeConfig.Save(); diff --git a/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj b/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj index 55c14ce9d5a6b5..9724d3326e75a0 100644 --- a/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj +++ b/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj @@ -5,7 +5,6 @@ HostActivation.Tests HostActivation.Tests true - $(DefineConstants);WINDOWS ha true @@ -17,7 +16,6 @@ - diff --git a/src/installer/tests/HostActivation.Tests/InstallLocationCommandResultExtensions.cs b/src/installer/tests/HostActivation.Tests/InstallLocationCommandResultExtensions.cs index c85b7d3e56cc5d..c4a8438d8117e4 100644 --- a/src/installer/tests/HostActivation.Tests/InstallLocationCommandResultExtensions.cs +++ b/src/installer/tests/HostActivation.Tests/InstallLocationCommandResultExtensions.cs @@ -3,6 +3,7 @@ using System; +using System.IO; using System.Runtime.InteropServices; using FluentAssertions; using Microsoft.DotNet.Cli.Build.Framework; @@ -45,14 +46,14 @@ public static AndConstraint HaveUsedGlobalInstallLocati return assertion.HaveStdErrContaining($"Using global installation location [{installLocation}]"); } - public static AndConstraint HaveFoundDefaultInstallLocationInConfigFile(this CommandResultAssertions assertion, string installLocation) + public static AndConstraint HaveLookedForDefaultInstallLocation(this CommandResultAssertions assertion, string installLocationPath) { - return assertion.HaveStdErrContaining($"Found install location path '{installLocation}'."); + return assertion.HaveStdErrContaining($"Looking for install_location file in '{Path.Combine(installLocationPath, "install_location")}'."); } - public static AndConstraint HaveFoundArchSpecificInstallLocationInConfigFile(this CommandResultAssertions assertion, string installLocation, string arch) + public static AndConstraint HaveLookedForArchitectureSpecificInstallLocation(this CommandResultAssertions assertion, string installLocationPath, string architecture) { - return assertion.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{arch}')."); + return assertion.HaveStdErrContaining($"Looking for architecture specific install_location file in '{Path.Combine(installLocationPath, "install_location_" + architecture.ToLowerInvariant())}'."); } } } diff --git a/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs b/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs index 120b899cff451b..3829a30e682e09 100644 --- a/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs +++ b/src/installer/tests/HostActivation.Tests/MultiArchInstallLocation.cs @@ -71,6 +71,31 @@ public void EnvironmentVariable_ArchSpecificDotnetRootIsUsedOverDotnetRoot() .And.NotHaveStdErrContaining("Using environment variable DOTNET_ROOT="); } + [Fact] + public void EnvironmentVariable_DotNetRootIsUsedOverInstallLocationIfSet() + { + var fixture = sharedTestState.PortableAppFixture + .Copy(); + + var appExe = fixture.TestProject.AppExe; + var arch = fixture.RepoDirProvider.BuildArchitecture.ToUpper(); + var dotnet = fixture.BuiltDotnet.BinPath; + + using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(appExe)) + { + registeredInstallLocationOverride.SetInstallLocation((arch, "some/install/location")); + + Command.Create(appExe) + .EnableTracingAndCaptureOutputs() + .ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) + .DotNetRoot(dotnet, arch) + .Execute() + .Should().Pass() + .And.HaveUsedDotNetRootInstallLocation(dotnet, fixture.CurrentRid, arch) + .And.NotHaveStdErrContaining("Using global install location"); + } + } + [Fact] public void EnvironmentVariable_DotnetRootPathDoesNotExist() { @@ -122,7 +147,6 @@ public void EnvironmentVariable_DotnetRootPathExistsButHasNoHost() } [Fact] - [SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] public void InstallLocationFile_ArchSpecificLocationIsPickedFirst() { var fixture = sharedTestState.PortableAppFixture @@ -142,40 +166,19 @@ public void InstallLocationFile_ArchSpecificLocationIsPickedFirst() (arch2, path2) }); - Command.Create(appExe) + CommandResult result = Command.Create(appExe) .EnableTracingAndCaptureOutputs() .ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) .DotNetRoot(null) - .Execute() - .Should().HaveFoundDefaultInstallLocationInConfigFile(path1) - .And.HaveFoundArchSpecificInstallLocationInConfigFile(path1, arch1) - .And.HaveFoundArchSpecificInstallLocationInConfigFile(path2, arch2) - .And.HaveUsedGlobalInstallLocation(path2); - } - } + .Execute(); - [Fact] - [SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] - public void InstallLocationFile_OnlyFirstLineMayNotSpecifyArchitecture() - { - var fixture = sharedTestState.PortableAppFixture - .Copy(); + if (!OperatingSystem.IsWindows()) + { + result.Should() + .HaveLookedForArchitectureSpecificInstallLocation(registeredInstallLocationOverride.PathValueOverride, arch2); + } - var appExe = fixture.TestProject.AppExe; - using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(appExe)) - { - registeredInstallLocationOverride.SetInstallLocation(new (string, string)[] { - (string.Empty, "a/b/c"), - (string.Empty, "x/y/z"), - }); - Command.Create(appExe) - .EnableTracingAndCaptureOutputs() - .ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) - .DotNetRoot(null) - .Execute() - .Should().HaveFoundDefaultInstallLocationInConfigFile("a/b/c") - .And.HaveStdErrContaining($"Only the first line in '{registeredInstallLocationOverride.PathValueOverride}' may not have an architecture prefix.") - .And.HaveUsedConfigFileInstallLocation("a/b/c"); + result.Should().HaveUsedGlobalInstallLocation(path2); } } @@ -200,7 +203,7 @@ public void InstallLocationFile_ReallyLongInstallPathIsParsedCorrectly() .ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) .DotNetRoot(null) .Execute() - .Should().HaveFoundDefaultInstallLocationInConfigFile(reallyLongPath) + .Should().HaveLookedForDefaultInstallLocation(registeredInstallLocationOverride.PathValueOverride) .And.HaveUsedConfigFileInstallLocation(reallyLongPath); } } @@ -218,16 +221,15 @@ public void InstallLocationFile_MissingFile() { Directory.CreateDirectory(testArtifactsPath); - string directory = Path.Combine(testArtifactsPath, "installLocationOverride"); - Directory.CreateDirectory(directory); - string nonExistentLocationFile = Path.Combine(directory, "install_location"); + string installLocationDirectory = Path.Combine(testArtifactsPath, "installLocationOverride"); + Directory.CreateDirectory(installLocationDirectory); string defaultInstallLocation = Path.Combine(testArtifactsPath, "defaultInstallLocation"); Command.Create(appExe) .CaptureStdErr() .EnvironmentVariable( - Constants.TestOnlyEnvironmentVariables.InstallLocationFilePath, - nonExistentLocationFile) + Constants.TestOnlyEnvironmentVariables.InstallLocationPath, + installLocationDirectory) .EnvironmentVariable( Constants.TestOnlyEnvironmentVariables.DefaultInstallPath, defaultInstallLocation) diff --git a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs index aaabf8e571bcd2..d9feb540d70bce 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs @@ -461,6 +461,52 @@ public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_only() } } + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // Multi-level lookup is only supported on Windows. + public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_only_self_register_program_files() + { + var f = new SdkResolutionFixture(sharedTestState); + + string expectedFrameworkNames = string.Join(';', new[] + { + "HostFxr.Test.A", + "HostFxr.Test.A", + "HostFxr.Test.B", + }); + + string expectedFrameworkVersions = string.Join(';', new[] + { + "1.2.3", + "3.0.0", + "5.6.7-A", + }); + + string expectedFrameworkPaths = string.Join(';', new[] + { + Path.Combine(f.ProgramFilesGlobalFrameworksDir, "HostFxr.Test.A"), + Path.Combine(f.ProgramFilesGlobalFrameworksDir, "HostFxr.Test.A"), + Path.Combine(f.ProgramFilesGlobalFrameworksDir, "HostFxr.Test.B"), + }); + + using (TestOnlyProductBehavior.Enable(f.Dotnet.GreatestVersionHostFxrFilePath)) + { + // We pass f.WorkingDir so that we don't resolve dotnet_dir to the global installation + // in the native side. + f.Dotnet.Exec(f.AppDll, new[] { "hostfxr_get_dotnet_environment_info", f.WorkingDir }) + .EnvironmentVariable("TEST_MULTILEVEL_LOOKUP_PROGRAM_FILES", f.ProgramFiles) + // Test with a self-registered path the same as ProgramFiles, with a trailing slash. Expect this to be de-duped + .EnvironmentVariable("TEST_MULTILEVEL_LOOKUP_SELF_REGISTERED", Path.Combine(f.ProgramFiles, "dotnet") + Path.DirectorySeparatorChar) + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should().Pass() + .And.HaveStdOutContaining("hostfxr_get_dotnet_environment_info:Success") + .And.HaveStdOutContaining($"hostfxr_get_dotnet_environment_info framework names:[{expectedFrameworkNames}]") + .And.HaveStdOutContaining($"hostfxr_get_dotnet_environment_info framework versions:[{expectedFrameworkVersions}]") + .And.HaveStdOutContaining($"hostfxr_get_dotnet_environment_info framework paths:[{expectedFrameworkPaths}]"); + } + } + [Fact] public void Hostfxr_get_dotnet_environment_info_global_install_path() { diff --git a/src/installer/tests/HostActivation.Tests/NativeHosting/Nethost.cs b/src/installer/tests/HostActivation.Tests/NativeHosting/Nethost.cs index 0af2ce34774127..792bf4faf6f8f6 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHosting/Nethost.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHosting/Nethost.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 HostActivation.Tests; using Microsoft.DotNet.Cli.Build.Framework; using System; using System.IO; @@ -88,6 +89,7 @@ public void GetHostFxrPath_DotNetRootParameter(bool explicitLoad, bool useAssemb } [Theory] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61131", TestPlatforms.OSX)] [InlineData(true, false, true, false)] [InlineData(true, false, true, true)] [InlineData(true, false, false, false)] @@ -179,6 +181,7 @@ public void GetHostFxrPath_HostFxrAlreadyLoaded() } [Theory] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61131", TestPlatforms.OSX)] [SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] [InlineData("{0}", false, true)] [InlineData("{0}\n", false, true)] @@ -216,12 +219,21 @@ public void GetHostFxrPath_InstallLocationFile(string value, bool shouldUseArchS .DotNetRoot(null) .Execute(); - result.Should().HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'."); + if (shouldUseArchSpecificInstallLocation) + { + result.Should().HaveLookedForArchitectureSpecificInstallLocation( + registeredInstallLocationOverride.PathValueOverride, + sharedState.RepoDirectories.BuildArchitecture); + } + else + { + result.Should().HaveLookedForDefaultInstallLocation(registeredInstallLocationOverride.PathValueOverride); + } if (shouldPass) { result.Should().Pass() - .And.HaveStdErrContaining($"Using install location '{installLocation}'.") + .And.HaveUsedConfigFileInstallLocation(installLocation) .And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower()); } else @@ -235,35 +247,7 @@ public void GetHostFxrPath_InstallLocationFile(string value, bool shouldUseArchS } [Fact] - [SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] - public void GetHostFxrPath_GlobalInstallation_HasMoreThanOneDefaultInstallationPath() - { - string installLocation = Path.Combine(sharedState.ValidInstallRoot, "dotnet"); - using (var registeredInstallLocationOverride = new RegisteredInstallLocationOverride(sharedState.NethostPath)) - { - registeredInstallLocationOverride.SetInstallLocation(new (string, string)[] { - (string.Empty, installLocation), (string.Empty, installLocation) - }); - - CommandResult result = Command.Create(sharedState.NativeHostPath, GetHostFxrPath) - .EnableTracingAndCaptureOutputs() - .ApplyRegisteredInstallLocationOverride(registeredInstallLocationOverride) - .EnvironmentVariable( // Redirect the default install location to an invalid location so that it doesn't cause the test to pass - Constants.TestOnlyEnvironmentVariables.DefaultInstallPath, - sharedState.InvalidInstallRoot) - .DotNetRoot(null) - .Execute(); - - result.Should().Pass() - .And.HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.") - .And.HaveStdErrContaining($"Found install location path '{installLocation}'.") - .And.HaveStdErrContaining($"Only the first line in '{registeredInstallLocationOverride.PathValueOverride}' may not have an architecture prefix.") - .And.HaveStdErrContaining($"Using install location '{installLocation}'.") - .And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower()); - } - } - - [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61131", TestPlatforms.OSX)] [SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] public void GetHostFxrPath_GlobalInstallation_HasNoDefaultInstallationPath() { @@ -285,14 +269,16 @@ public void GetHostFxrPath_GlobalInstallation_HasNoDefaultInstallationPath() .Execute(); result.Should().Pass() - .And.HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.") - .And.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{sharedState.RepoDirectories.BuildArchitecture.ToLower()}').") - .And.HaveStdErrContaining($"Using install location '{installLocation}'.") + .And.HaveLookedForArchitectureSpecificInstallLocation( + registeredInstallLocationOverride.PathValueOverride, + sharedState.RepoDirectories.BuildArchitecture) + .And.HaveUsedConfigFileInstallLocation(installLocation) .And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower()); } } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/61131", TestPlatforms.OSX)] [SkipOnPlatform(TestPlatforms.Windows, "This test targets the install_location config file which is only used on Linux and macOS.")] public void GetHostFxrPath_GlobalInstallation_ArchitectureSpecificPathIsPickedOverDefaultPath() { @@ -314,10 +300,10 @@ public void GetHostFxrPath_GlobalInstallation_ArchitectureSpecificPathIsPickedOv .Execute(); result.Should().Pass() - .And.HaveStdErrContaining($"Looking for install_location file in '{registeredInstallLocationOverride.PathValueOverride}'.") - .And.HaveStdErrContaining($"Found install location path '{installLocation}/a/b/c'.") - .And.HaveStdErrContaining($"Found architecture-specific install location path: '{installLocation}' ('{sharedState.RepoDirectories.BuildArchitecture.ToLower()}').") - .And.HaveStdErrContaining($"Using install location '{installLocation}'.") + .And.HaveLookedForArchitectureSpecificInstallLocation( + registeredInstallLocationOverride.PathValueOverride, + sharedState.RepoDirectories.BuildArchitecture) + .And.HaveUsedConfigFileInstallLocation(installLocation) .And.HaveStdOutContaining($"hostfxr_path: {sharedState.HostFxrPath}".ToLower()); } } diff --git a/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs b/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs index 4b1b28e32f3ee2..b0b52d901efd2c 100644 --- a/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs +++ b/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs @@ -526,7 +526,7 @@ public void AppHost_GUI_FrameworkDependent_MissingRuntimeFramework_ErrorReported .MultilevelLookup(false) .Start(); - WaitForPopupFromProcess(command.Process); + WindowsUtils.WaitForPopupFromProcess(command.Process); command.Process.Kill(); var result = command.WaitForExit(true) @@ -559,7 +559,7 @@ public void AppHost_GUI_MissingRuntime_ErrorReportedInDialog() .MultilevelLookup(false) .Start(); - WaitForPopupFromProcess(command.Process); + WindowsUtils.WaitForPopupFromProcess(command.Process); command.Process.Kill(); var expectedErrorCode = Constants.ErrorCode.CoreHostLibMissingFailure.ToString("x"); @@ -590,7 +590,7 @@ public void AppHost_GUI_NoCustomErrorWriter_FrameworkMissing_ErrorReportedInDial Directory.CreateDirectory(dotnetWithMockHostFxr); string expectedErrorCode = Constants.ErrorCode.FrameworkMissingFailure.ToString("x"); - var dotnetBuilder = new DotNetBuilder(dotnetWithMockHostFxr, sharedTestState.RepoDirectories.BuiltDotnet, "hostfxrFrameworkMissingFailure") + var dotnetBuilder = new DotNetBuilder(dotnetWithMockHostFxr, sharedTestState.RepoDirectories.BuiltDotnet, "mockhostfxrFrameworkMissingFailure") .RemoveHostFxr() .AddMockHostFxr(new Version(2, 2, 0)); var dotnet = dotnetBuilder.Build(); @@ -601,7 +601,7 @@ public void AppHost_GUI_NoCustomErrorWriter_FrameworkMissing_ErrorReportedInDial .MultilevelLookup(false) .Start(); - WaitForPopupFromProcess(command.Process); + WindowsUtils.WaitForPopupFromProcess(command.Process); command.Process.Kill(); command.WaitForExit(true) @@ -689,50 +689,6 @@ private string CreateAStore(TestProjectFixture testProjectFixture) return storeoutputDirectory; } -#if WINDOWS - private delegate bool EnumThreadWindowsDelegate(IntPtr hWnd, IntPtr lParam); - - [DllImport("user32.dll")] - private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadWindowsDelegate plfn, IntPtr lParam); - - private IntPtr WaitForPopupFromProcess(Process process, int timeout = 60000) - { - IntPtr windowHandle = IntPtr.Zero; - int timeRemaining = timeout; - while (timeRemaining > 0) - { - foreach (ProcessThread thread in process.Threads) - { - // We take the last window we find. There really should only be one at most anyways. - EnumThreadWindows(thread.Id, - (hWnd, lParam) => { - windowHandle = hWnd; - return true; - }, - IntPtr.Zero); - } - - if (windowHandle != IntPtr.Zero) - { - break; - } - - System.Threading.Thread.Sleep(100); - timeRemaining -= 100; - } - - // Do not fail if the window could be detected, sometimes the check is fragile and doesn't work. - // Not worth the trouble trying to figure out why (only happens rarely in the CI system). - // We will rely on product tracing in the failure case. - return windowHandle; - } -#else - private IntPtr WaitForPopupFromProcess(Process process, int timeout = 60000) - { - throw new PlatformNotSupportedException(); - } -#endif - public class SharedTestState : IDisposable { public TestProjectFixture PortableAppFixture_Built { get; } diff --git a/src/installer/tests/HostActivation.Tests/RegisteredInstallLocationOverride.cs b/src/installer/tests/HostActivation.Tests/RegisteredInstallLocationOverride.cs index d37cfafe649537..fcb29470d9eeb0 100644 --- a/src/installer/tests/HostActivation.Tests/RegisteredInstallLocationOverride.cs +++ b/src/installer/tests/HostActivation.Tests/RegisteredInstallLocationOverride.cs @@ -56,10 +56,11 @@ public RegisteredInstallLocationOverride(string productBinaryPath) // On Linux/macOS the install location is registered in a file which is normally // located in /etc/dotnet/install_location // So we need to redirect it to a different place here. - string directory = Path.Combine(TestArtifact.TestArtifactsPath, "installLocationOverride"); + string directory = Path.Combine(TestArtifact.TestArtifactsPath, "installLocationOverride" + Process.GetCurrentProcess().Id.ToString()); + if (Directory.Exists(directory)) + Directory.Delete(directory, true); Directory.CreateDirectory(directory); - PathValueOverride = Path.Combine(directory, "install_location." + Process.GetCurrentProcess().Id.ToString()); - File.WriteAllText(PathValueOverride, ""); + PathValueOverride = directory; } } @@ -78,9 +79,12 @@ public void SetInstallLocation(params (string Architecture, string Path)[] locat } else { - File.WriteAllText(PathValueOverride, string.Join(Environment.NewLine, - locations.Select(l => string.Format("{0}{1}", - (!string.IsNullOrWhiteSpace(l.Architecture) ? l.Architecture + "=" : ""), l.Path)))); + foreach (var location in locations) + { + string installLocationFileName = "install_location" + + (!string.IsNullOrWhiteSpace(location.Architecture) ? ("_" + location.Architecture) : string.Empty); + File.WriteAllText(Path.Combine(PathValueOverride, installLocationFileName), location.Path); + } } } @@ -127,7 +131,7 @@ public static Command ApplyRegisteredInstallLocationOverride( else { return command.EnvironmentVariable( - Constants.TestOnlyEnvironmentVariables.InstallLocationFilePath, + Constants.TestOnlyEnvironmentVariables.InstallLocationPath, registeredInstallLocationOverride.PathValueOverride); } } diff --git a/src/installer/tests/HostActivation.Tests/StartupHooks.cs b/src/installer/tests/HostActivation.Tests/StartupHooks.cs index a0533a60fd4772..3e1685356167f9 100644 --- a/src/installer/tests/HostActivation.Tests/StartupHooks.cs +++ b/src/installer/tests/HostActivation.Tests/StartupHooks.cs @@ -13,6 +13,7 @@ public class StartupHooks : IClassFixture { private SharedTestState sharedTestState; private string startupHookVarName = "DOTNET_STARTUP_HOOKS"; + private string startupHookRuntimeConfigName = "STARTUP_HOOKS"; private string startupHookSupport = "System.StartupHookProvider.IsSupported"; public StartupHooks(StartupHooks.SharedTestState fixture) @@ -105,6 +106,64 @@ public void Muxer_activation_of_Multiple_StartupHooks_Succeeds() .And.HaveStdOutContaining("Hello World"); } + [Fact] + public void Muxer_activation_of_RuntimeConfig_StartupHook_Succeeds() + { + var fixture = sharedTestState.PortableAppFixture.Copy(); + var dotnet = fixture.BuiltDotnet; + var appDll = fixture.TestProject.AppDll; + + var startupHookFixture = sharedTestState.StartupHookFixture.Copy(); + var startupHookDll = startupHookFixture.TestProject.AppDll; + + RuntimeConfig.FromFile(fixture.TestProject.RuntimeConfigJson) + .WithProperty(startupHookRuntimeConfigName, startupHookDll) + .Save(); + + // RuntimeConfig defined startup hook + dotnet.Exec(appDll) + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should().Pass() + .And.HaveStdOutContaining("Hello from startup hook!") + .And.HaveStdOutContaining("Hello World"); + } + + [Fact] + public void Muxer_activation_of_RuntimeConfig_And_Environment_StartupHooks_SucceedsInExpectedOrder() + { + var fixture = sharedTestState.PortableAppFixture.Copy(); + var dotnet = fixture.BuiltDotnet; + var appDll = fixture.TestProject.AppDll; + + var startupHookFixture = sharedTestState.StartupHookFixture.Copy(); + var startupHookDll = startupHookFixture.TestProject.AppDll; + + RuntimeConfig.FromFile(fixture.TestProject.RuntimeConfigJson) + .WithProperty(startupHookRuntimeConfigName, startupHookDll) + .Save(); + + var startupHook2Fixture = sharedTestState.StartupHookWithDependencyFixture.Copy(); + var startupHook2Dll = startupHook2Fixture.TestProject.AppDll; + + // include any char to counter output from other threads such as in #57243 + const string wildcardPattern = @"[\r\n\s.]*"; + + // RuntimeConfig and Environment startup hooks in expected order + dotnet.Exec(appDll) + .EnvironmentVariable(startupHookVarName, startupHook2Dll) + .CaptureStdOut() + .CaptureStdErr() + .Execute() + .Should().Pass() + .And.HaveStdOutMatching("Hello from startup hook with dependency!" + + wildcardPattern + + "Hello from startup hook!" + + wildcardPattern + + "Hello World"); + } + // Empty startup hook variable [Fact] public void Muxer_activation_of_Empty_StartupHook_Variable_Succeeds() diff --git a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj index 8dcef20c22dea9..73a3fda2b55fd4 100644 --- a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj +++ b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/Microsoft.DotNet.CoreSetup.Packaging.Tests.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NETCoreTests.cs b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NETCoreTests.cs index 65d19d7983c413..cda507f61480de 100644 --- a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NETCoreTests.cs +++ b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NETCoreTests.cs @@ -18,7 +18,7 @@ public void NETCoreTargetingPackIsValid() "Microsoft.NETCore.App.Ref")) { // Allow no targeting pack in case this is a servicing build. - // This condition should be tightened: https://github.com/dotnet/core-setup/issues/8830 + // This condition should be tightened: https://github.com/dotnet/runtime/issues/3836 if (tester == null) { return; diff --git a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NuGetArtifactTester.cs b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NuGetArtifactTester.cs index 4af9206f6b3513..292e3522d961e1 100644 --- a/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NuGetArtifactTester.cs +++ b/src/installer/tests/Microsoft.DotNet.CoreSetup.Packaging.Tests/NuGetArtifactTester.cs @@ -41,10 +41,7 @@ public static NuGetArtifactTester OpenOrNull( "Shipping", $"{id}.{dirs.MicrosoftNETCoreAppVersion}.nupkg"); - // If the nuspec exists, the nupkg should exist. - Assert.True(File.Exists(nupkgPath)); - - return new NuGetArtifactTester(nupkgPath); + return File.Exists(nupkgPath) ? new NuGetArtifactTester(nupkgPath) : null; } public PackageIdentity Identity { get; } diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleTestBase.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleTestBase.cs index 18aba06f6d9786..669b300cb838ad 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleTestBase.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleTestBase.cs @@ -25,7 +25,7 @@ public static string UseSingleFileSelfContainedHost(TestProjectFixture testFixtu var publishedHostPath = BundleHelper.GetHostPath(testFixture); HostWriter.CreateAppHost(singleFileHost, publishedHostPath, - BundleHelper.GetAppPath(testFixture)); + BundleHelper.GetAppName(testFixture)); return publishedHostPath; } @@ -37,7 +37,7 @@ public static string UseFrameworkDependentHost(TestProjectFixture testFixture) var publishedHostPath = BundleHelper.GetHostPath(testFixture); HostWriter.CreateAppHost(appHost, publishedHostPath, - BundleHelper.GetAppPath(testFixture)); + BundleHelper.GetAppName(testFixture)); return publishedHostPath; } diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs index 66212592138151..9442777b7a5fdc 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.IO; using BundleTests.Helpers; using Microsoft.DotNet.Cli.Build.Framework; using Microsoft.DotNet.CoreSetup.Test; @@ -22,9 +23,7 @@ public BundledAppWithSubDirs(SharedTestState fixture) private void RunTheApp(string path, TestProjectFixture fixture) { Command.Create(path) - .EnvironmentVariable("COREHOST_TRACE", "1") - .CaptureStdErr() - .CaptureStdOut() + .EnableTracingAndCaptureOutputs() .EnvironmentVariable("DOTNET_ROOT", fixture.BuiltDotnet.BinPath) .EnvironmentVariable("DOTNET_ROOT(x86)", fixture.BuiltDotnet.BinPath) .EnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0") @@ -52,6 +51,47 @@ public void Bundled_Framework_dependent_App_Run_Succeeds(BundleOptions options) RunTheApp(singleFile, fixture); } + [InlineData(BundleOptions.None)] + [InlineData(BundleOptions.BundleNativeBinaries)] + [InlineData(BundleOptions.BundleAllContent)] + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] // GUI app host is only supported on Windows. + public void Bundled_Framework_dependent_App_GUI_DownlevelHostFxr_ErrorDialog(BundleOptions options) + { + var fixture = sharedTestState.TestFrameworkDependentFixture.Copy(); + UseFrameworkDependentHost(fixture); + var singleFile = BundleHelper.BundleApp(fixture, options); + AppHostExtensions.SetWindowsGraphicalUserInterfaceBit(singleFile); + + string dotnetWithMockHostFxr = SharedFramework.CalculateUniqueTestDirectory(Path.Combine(TestArtifact.TestArtifactsPath, "bundleErrors")); + using (new TestArtifact(dotnetWithMockHostFxr)) + { + Directory.CreateDirectory(dotnetWithMockHostFxr); + string expectedErrorCode = Constants.ErrorCode.BundleExtractionFailure.ToString("x"); + + var dotnetBuilder = new DotNetBuilder(dotnetWithMockHostFxr, sharedTestState.RepoDirectories.BuiltDotnet, "mockhostfxrBundleVersionFailure") + .RemoveHostFxr() + .AddMockHostFxr(new Version(5, 0, 0)); + var dotnet = dotnetBuilder.Build(); + + Command command = Command.Create(singleFile) + .EnableTracingAndCaptureOutputs() + .DotNetRoot(dotnet.BinPath, sharedTestState.RepoDirectories.BuildArchitecture) + .MultilevelLookup(false) + .Start(); + + WindowsUtils.WaitForPopupFromProcess(command.Process); + command.Process.Kill(); + + command + .WaitForExit(true) + .Should().Fail() + .And.HaveStdErrContaining("Bundle header version compatibility check failed.") + .And.HaveStdErrContaining($"Showing error dialog for application: '{Path.GetFileName(singleFile)}' - error code: 0x{expectedErrorCode}") + .And.HaveStdErrContaining("apphost_version="); + } + } + [InlineData(BundleOptions.None)] [InlineData(BundleOptions.BundleNativeBinaries)] [InlineData(BundleOptions.BundleAllContent)] diff --git a/src/installer/tests/TestUtils/Command.cs b/src/installer/tests/TestUtils/Command.cs index 3c3e5607dde90a..91f85be3584324 100644 --- a/src/installer/tests/TestUtils/Command.cs +++ b/src/installer/tests/TestUtils/Command.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; @@ -120,7 +121,7 @@ private static bool ShouldUseCmd(string executable) } else { - // Search the path to see if we can find it + // Search the path to see if we can find it foreach (var path in System.Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) { var candidate = Path.Combine(path, executable + ".exe"); @@ -196,7 +197,20 @@ public Command Start() ReportExecBegin(); - Process.Start(); + // Retry if we hit ETXTBSY due to Linux race + // https://github.com/dotnet/runtime/issues/58964 + for (int i = 0; ; i++) + { + try + { + Process.Start(); + break; + } + catch (Win32Exception e) when (i < 4 && e.Message.Contains("Text file busy")) + { + Thread.Sleep(i * 20); + } + } if (Process.StartInfo.RedirectStandardOutput) { diff --git a/src/installer/tests/HostActivation.Tests/CommandExtensions.cs b/src/installer/tests/TestUtils/CommandExtensions.cs similarity index 81% rename from src/installer/tests/HostActivation.Tests/CommandExtensions.cs rename to src/installer/tests/TestUtils/CommandExtensions.cs index d8460c1368bdb5..38c4cbff3ba448 100644 --- a/src/installer/tests/HostActivation.Tests/CommandExtensions.cs +++ b/src/installer/tests/TestUtils/CommandExtensions.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.DotNet.CoreSetup.Test; using System; using System.IO; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public static class CommandExtensions { @@ -38,11 +39,11 @@ public static Command EnableTracingAndCaptureOutputs(this Command command) public static Command DotNetRoot(this Command command, string dotNetRoot, string architecture = null) { if (!string.IsNullOrEmpty(architecture)) - return command.EnvironmentVariable($"DOTNET_ROOT_{architecture.ToUpper()}", dotNetRoot); + return command.EnvironmentVariable(Constants.DotnetRoot.ArchitectureEnvironmentVariablePrefix + architecture.ToUpper(), dotNetRoot); return command - .EnvironmentVariable("DOTNET_ROOT", dotNetRoot) - .EnvironmentVariable("DOTNET_ROOT(x86)", dotNetRoot); + .EnvironmentVariable(Constants.DotnetRoot.EnvironmentVariable, dotNetRoot) + .EnvironmentVariable(Constants.DotnetRoot.WindowsX86EnvironmentVariable, dotNetRoot); } public static Command MultilevelLookup(this Command command, bool enable) diff --git a/src/installer/tests/HostActivation.Tests/Constants.cs b/src/installer/tests/TestUtils/Constants.cs similarity index 86% rename from src/installer/tests/HostActivation.Tests/Constants.cs rename to src/installer/tests/TestUtils/Constants.cs index f7e743aa99aa38..e36df4bd2cdb39 100644 --- a/src/installer/tests/HostActivation.Tests/Constants.cs +++ b/src/installer/tests/TestUtils/Constants.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { - internal static class Constants + public static class Constants { public const string MicrosoftNETCoreApp = "Microsoft.NETCore.App"; @@ -53,7 +53,7 @@ public static class TestOnlyEnvironmentVariables public const string DefaultInstallPath = "_DOTNET_TEST_DEFAULT_INSTALL_PATH"; public const string RegistryPath = "_DOTNET_TEST_REGISTRY_PATH"; public const string GloballyRegisteredPath = "_DOTNET_TEST_GLOBALLY_REGISTERED_PATH"; - public const string InstallLocationFilePath = "_DOTNET_TEST_INSTALL_LOCATION_FILE_PATH"; + public const string InstallLocationPath = "_DOTNET_TEST_INSTALL_LOCATION_PATH"; } public static class RuntimeId @@ -72,6 +72,13 @@ public static class HostTracing public const string TraceFileEnvironmentVariable = "COREHOST_TRACEFILE"; } + public static class DotnetRoot + { + public const string EnvironmentVariable = "DOTNET_ROOT"; + public const string WindowsX86EnvironmentVariable = "DOTNET_ROOT(x86)"; + public const string ArchitectureEnvironmentVariablePrefix = "DOTNET_ROOT_"; + } + public static class ErrorCode { public const int InvalidArgFailure = unchecked((int)0x80008081); @@ -81,6 +88,7 @@ public static class ErrorCode public const int LibHostInvalidArgs = unchecked((int)0x80008092); public const int AppArgNotRunnable = unchecked((int)0x80008094); public const int FrameworkMissingFailure = unchecked((int)0x80008096); + public const int BundleExtractionFailure = unchecked((int)0x8000809f); public const int COMPlusException = unchecked((int)0xe0434352); public const int SIGABRT = 134; diff --git a/src/installer/tests/HostActivation.Tests/DotNetBuilder.cs b/src/installer/tests/TestUtils/DotNetBuilder.cs similarity index 95% rename from src/installer/tests/HostActivation.Tests/DotNetBuilder.cs rename to src/installer/tests/TestUtils/DotNetBuilder.cs index 0a8d54559e2275..d4cb58340ca6ed 100644 --- a/src/installer/tests/HostActivation.Tests/DotNetBuilder.cs +++ b/src/installer/tests/TestUtils/DotNetBuilder.cs @@ -5,7 +5,7 @@ using System; using System.IO; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { /// /// Helper class for creating a mock version of a dotnet installation @@ -68,16 +68,19 @@ public DotNetBuilder AddMicrosoftNETCoreAppFrameworkMockHostPolicy(string versio /// Use a mock version of HostFxr. /// /// Version to add - /// - /// Currently, the only mock version of HostFxr that we have is mockhostfxr_2_2. - /// public DotNetBuilder AddMockHostFxr(Version version) { string hostfxrPath = Path.Combine(_path, "host", "fxr", version.ToString()); Directory.CreateDirectory(hostfxrPath); - bool hasCustomErrorWriter = version.Major >= 3; - string mockHostFxrFileName = RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform(hasCustomErrorWriter ? "mockhostfxr" : "mockhostfxr_2_2"); + string mockHostFxrFileNameBase = version switch + { + { Major: 2, Minor: 2 } => "mockhostfxr_2_2", + { Major: 5, Minor: 0 } => "mockhostfxr_5_0", + _ => throw new InvalidOperationException($"Unsupported version {version} of mockhostfxr.") + }; + + string mockHostFxrFileName = RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform(mockHostFxrFileNameBase); File.Copy( Path.Combine(_repoDirectories.Artifacts, "corehost_test", mockHostFxrFileName), Path.Combine(hostfxrPath, RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform("hostfxr")), diff --git a/src/installer/tests/TestUtils/FileUtils.cs b/src/installer/tests/TestUtils/FileUtils.cs index 8da68f684734bf..a66ead73e0b026 100644 --- a/src/installer/tests/TestUtils/FileUtils.cs +++ b/src/installer/tests/TestUtils/FileUtils.cs @@ -5,7 +5,7 @@ using System.IO; using System.IO.MemoryMappedFiles; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public static class FileUtils { diff --git a/src/installer/tests/HostActivation.Tests/NetCoreAppBuilder.cs b/src/installer/tests/TestUtils/NetCoreAppBuilder.cs similarity index 99% rename from src/installer/tests/HostActivation.Tests/NetCoreAppBuilder.cs rename to src/installer/tests/TestUtils/NetCoreAppBuilder.cs index ba5e101558c29d..f4909cde996799 100644 --- a/src/installer/tests/HostActivation.Tests/NetCoreAppBuilder.cs +++ b/src/installer/tests/TestUtils/NetCoreAppBuilder.cs @@ -7,7 +7,7 @@ using System.IO; using System.Linq; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public class NetCoreAppBuilder { diff --git a/src/installer/tests/HostActivation.Tests/RuntimeConfig.cs b/src/installer/tests/TestUtils/RuntimeConfig.cs similarity index 99% rename from src/installer/tests/HostActivation.Tests/RuntimeConfig.cs rename to src/installer/tests/TestUtils/RuntimeConfig.cs index eaa95cb2dcced0..2a8418f4713280 100644 --- a/src/installer/tests/HostActivation.Tests/RuntimeConfig.cs +++ b/src/installer/tests/TestUtils/RuntimeConfig.cs @@ -8,7 +8,7 @@ using System.IO; using System.Linq; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public class RuntimeConfig { diff --git a/src/installer/tests/HostActivation.Tests/SharedFramework.cs b/src/installer/tests/TestUtils/SharedFramework.cs similarity index 99% rename from src/installer/tests/HostActivation.Tests/SharedFramework.cs rename to src/installer/tests/TestUtils/SharedFramework.cs index a887b2bf65160a..408cf58f37b4e1 100644 --- a/src/installer/tests/HostActivation.Tests/SharedFramework.cs +++ b/src/installer/tests/TestUtils/SharedFramework.cs @@ -10,7 +10,7 @@ namespace Microsoft.DotNet.CoreSetup.Test /// /// Helper class for creating, modifying and cleaning up shared frameworks /// - internal static class SharedFramework + public static class SharedFramework { private static readonly Mutex id_mutex = new Mutex(); diff --git a/src/installer/tests/TestUtils/TestArtifact.cs b/src/installer/tests/TestUtils/TestArtifact.cs index 8483e4c88f7a8a..e1ca67416377ee 100644 --- a/src/installer/tests/TestUtils/TestArtifact.cs +++ b/src/installer/tests/TestUtils/TestArtifact.cs @@ -3,7 +3,6 @@ #nullable enable -using Microsoft.DotNet.CoreSetup.Test.HostActivation; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/installer/tests/TestUtils/TestUtils.csproj b/src/installer/tests/TestUtils/TestUtils.csproj index 35cb3e19e9d77a..1ca28978738f78 100644 --- a/src/installer/tests/TestUtils/TestUtils.csproj +++ b/src/installer/tests/TestUtils/TestUtils.csproj @@ -15,6 +15,8 @@ + + diff --git a/src/installer/tests/TestUtils/WindowsUtils.cs b/src/installer/tests/TestUtils/WindowsUtils.cs new file mode 100644 index 00000000000000..aff4c1fef8297b --- /dev/null +++ b/src/installer/tests/TestUtils/WindowsUtils.cs @@ -0,0 +1,54 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.DotNet.CoreSetup.Test +{ + public static class WindowsUtils + { + private delegate bool EnumThreadWindowsDelegate(IntPtr hWnd, IntPtr lParam); + + [DllImport("user32.dll")] + private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadWindowsDelegate plfn, IntPtr lParam); + + public static IntPtr WaitForPopupFromProcess(Process process, int timeout = 60000) + { + if (!OperatingSystem.IsWindows()) + { + throw new PlatformNotSupportedException(); + } + + IntPtr windowHandle = IntPtr.Zero; + int timeRemaining = timeout; + while (timeRemaining > 0) + { + foreach (ProcessThread thread in process.Threads) + { + // We take the last window we find. There really should only be one at most anyways. + EnumThreadWindows(thread.Id, + (hWnd, lParam) => { + windowHandle = hWnd; + return true; + }, + IntPtr.Zero); + } + + if (windowHandle != IntPtr.Zero) + { + break; + } + + System.Threading.Thread.Sleep(100); + timeRemaining -= 100; + } + + // Do not fail if the window could be detected, sometimes the check is fragile and doesn't work. + // Not worth the trouble trying to figure out why (only happens rarely in the CI system). + // We will rely on product tracing in the failure case. + return windowHandle; + } + } +} diff --git a/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs b/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs index 3b864790b25252..c905ca1bd6996e 100644 --- a/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs +++ b/src/libraries/Common/src/Internal/Cryptography/HashProviderCng.cs @@ -127,10 +127,15 @@ public override void Reset() { if (_reusable && !_running) return; + DestroyHash(); + BCryptCreateHashFlags flags = _reusable ? + BCryptCreateHashFlags.BCRYPT_HASH_REUSABLE_FLAG : + BCryptCreateHashFlags.None; + SafeBCryptHashHandle hHash; - NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(_hAlgorithm, out hHash, IntPtr.Zero, 0, _key, _key == null ? 0 : _key.Length, BCryptCreateHashFlags.None); + NTSTATUS ntStatus = Interop.BCrypt.BCryptCreateHash(_hAlgorithm, out hHash, IntPtr.Zero, 0, _key, _key == null ? 0 : _key.Length, flags); if (ntStatus != NTSTATUS.STATUS_SUCCESS) throw Interop.BCrypt.CreateCryptographicException(ntStatus); diff --git a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs index f38bb375b347e5..7fbaf9cc32eab8 100644 --- a/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs +++ b/src/libraries/Common/src/Interop/Linux/OpenLdap/Interop.Ldap.cs @@ -136,8 +136,9 @@ static Ldap() [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_set_option", CharSet = CharSet.Ansi)] public static extern int ldap_set_option_referral([In] ConnectionHandle ldapHandle, [In] LdapOption option, ref LdapReferralCallback outValue); + // Note that ldap_start_tls_s has a different signature across Windows LDAP and OpenLDAP [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_start_tls_s", CharSet = CharSet.Ansi)] - public static extern int ldap_start_tls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls); + public static extern int ldap_start_tls(ConnectionHandle ldapHandle, IntPtr serverControls, IntPtr clientControls); [DllImport(Libraries.OpenLdap, EntryPoint = "ldap_parse_result", CharSet = CharSet.Ansi)] public static extern int ldap_parse_result([In] ConnectionHandle ldapHandle, [In] IntPtr result, ref int serverError, ref IntPtr dn, ref IntPtr message, ref IntPtr referral, ref IntPtr control, byte freeIt); diff --git a/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs b/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs index fd4b968c132ea8..af75653dd2f3c4 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs @@ -25,6 +25,9 @@ internal static partial class libproc // Constants from sys\resource.h private const int RUSAGE_INFO_V3 = 3; + // Constants from sys/errno.h + private const int EPERM = 1; + // Defines from proc_info.h internal enum ThreadRunState { @@ -120,7 +123,14 @@ internal static unsafe int[] proc_listallpids() { // Get the number of processes currently running to know how much data to allocate int numProcesses = proc_listallpids(null, 0); - if (numProcesses <= 0) + if (numProcesses == 0 && Marshal.GetLastPInvokeError() == EPERM) + { + // An app running in App Sandbox does not have permissions to list other running processes + // and so the `proc_listallpids` function returns 0 and sets errno to 1. As a fallback + // we return at least an array with the PID of the current process which we always know. + return new[] { Environment.ProcessId }; + } + else if (numProcesses <= 0) { throw new Win32Exception(SR.CantGetAllPids); } diff --git a/src/libraries/Common/src/Interop/OSX/System.Native/Interop.SearchPath.iOS.cs b/src/libraries/Common/src/Interop/OSX/System.Native/Interop.SearchPath.iOS.cs new file mode 100644 index 00000000000000..8d73184ca4d50a --- /dev/null +++ b/src/libraries/Common/src/Interop/OSX/System.Native/Interop.SearchPath.iOS.cs @@ -0,0 +1,14 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Sys + { + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SearchPath_TempDirectory")] + internal static extern string SearchPathTempDirectory(); + } +} diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.PosixFAllocate.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FAllocate.cs similarity index 63% rename from src/libraries/Common/src/Interop/Unix/System.Native/Interop.PosixFAllocate.cs rename to src/libraries/Common/src/Interop/Unix/System.Native/Interop.FAllocate.cs index 2866ed38935bdf..71155e0f35e67e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.PosixFAllocate.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FAllocate.cs @@ -9,9 +9,9 @@ internal static partial class Interop internal static partial class Sys { /// - /// Returns -1 on ENOSPC, -2 on EFBIG. On success or ignorable error, 0 is returned. + /// Returns -1 on error, 0 on success. /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PosixFAllocate", SetLastError = false)] - internal static extern int PosixFAllocate(SafeFileHandle fd, long offset, long length); + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FAllocate", SetLastError = true)] + internal static extern int FAllocate(SafeFileHandle fd, long offset, long length); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetEnv.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetEnv.cs new file mode 100644 index 00000000000000..d83d6700b51622 --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetEnv.cs @@ -0,0 +1,14 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal unsafe partial class Sys + { + [DllImport(Interop.Libraries.SystemNative, EntryPoint = "SystemNative_GetEnv")] + internal static extern unsafe IntPtr GetEnv(string name); + } +} \ No newline at end of file diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs new file mode 100644 index 00000000000000..abe8ff0e1916ec --- /dev/null +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetEnviron.cs @@ -0,0 +1,17 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal unsafe partial class Sys + { + [DllImport(Interop.Libraries.SystemNative, EntryPoint = "SystemNative_GetEnviron")] + internal static extern unsafe IntPtr GetEnviron(); + + [DllImport(Interop.Libraries.SystemNative, EntryPoint = "SystemNative_FreeEnviron")] + internal static extern unsafe void FreeEnviron(IntPtr environ); + } +} \ No newline at end of file diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs index 15d6aa3c2f147a..fbd95d485e8415 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs @@ -80,6 +80,7 @@ private static DriveType GetDriveType(string fileSystemName) // This list is based primarily on "man fs", "man mount", "mntent.h", "/proc/filesystems", coreutils "stat.c", // and "wiki.debian.org/FileSystem". It can be extended over time as we find additional file systems that should // be recognized as a particular drive type. + // Keep this in sync with the UnixFileSystemTypes enum in Interop.UnixFileSystemTypes.cs switch (fileSystemName) { case "cddafs": diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs index 892e5ccaaed336..d86dcfbe4e59ae 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UnixFileSystemTypes.cs @@ -28,6 +28,7 @@ internal enum UnixFileSystemTypes : long befs = 0x42465331, bdevfs = 0x62646576, bfs = 0x1BADFACE, + bpf_fs = 0xCAFE4A11, binfmt_misc = 0x42494E4D, bootfs = 0xA56D3FF9, btrfs = 0x9123683E, @@ -53,6 +54,7 @@ internal enum UnixFileSystemTypes : long ext2 = 0xEF53, ext3 = 0xEF53, ext4 = 0xEF53, + f2fs = 0xF2F52010, fat = 0x4006, fd = 0xF00D1E, fhgfs = 0x19830326, @@ -122,6 +124,7 @@ internal enum UnixFileSystemTypes : long sysv2 = 0x012FF7B6, sysv4 = 0x012FF7B5, tmpfs = 0x01021994, + tracefs = 0x74726163, ubifs = 0x24051905, udf = 0x15013346, ufs = 0x00011954, diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs index 924c2da14d4b59..4e82a6faf507e9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs @@ -105,18 +105,28 @@ internal static unsafe SafeEvpPKeyHandle DecodePkcs8PrivateKey( } [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey); + private static extern int CryptoNative_GetPkcs8PrivateKeySize(IntPtr pkey, out int p8size); private static int GetPkcs8PrivateKeySize(IntPtr pkey) { - int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey); + const int Success = 1; + const int Error = -1; + const int MissingPrivateKey = -2; - if (ret < 0) + int ret = CryptoNative_GetPkcs8PrivateKeySize(pkey, out int p8size); + + switch (ret) { - throw CreateOpenSslCryptographicException(); + case Success: + return p8size; + case Error: + throw CreateOpenSslCryptographicException(); + case MissingPrivateKey: + throw new CryptographicException(SR.Cryptography_CSP_NoPrivateKey); + default: + Debug.Fail($"Unexpected return '{ret}' value from {nameof(CryptoNative_GetPkcs8PrivateKeySize)}."); + throw new CryptographicException(); } - - return ret; } [DllImport(Libraries.CryptoNative)] diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 73a9d32bb45c84..ae608c372778c9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -59,7 +59,7 @@ internal static SafeSslHandle AllocateSslContext(SslProtocols protocols, SafeX50 throw CreateSslException(SR.net_allocate_ssl_context_failed); } - if (!Interop.Ssl.Tls13Supported) + if (!Interop.Ssl.Capabilities.Tls13Supported) { if (protocols != SslProtocols.None && CipherSuitesPolicyPal.WantsTls13(protocols)) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index 29154b77da6325..64db5a15147a4c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -141,9 +141,13 @@ internal static partial class Ssl } [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Tls13Supported")] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool Tls13SupportedImpl(); - internal static readonly bool Tls13Supported = Tls13SupportedImpl(); + private static extern int Tls13SupportedImpl(); + + internal static class Capabilities + { + // needs separate type (separate static cctor) to be sure OpenSSL is initialized. + internal static readonly bool Tls13Supported = Tls13SupportedImpl() != 0; + } internal static SafeSharedX509NameStackHandle SslGetClientCAList(SafeSslHandle ssl) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileOperations.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileOperations.cs index cc4896c1c52e48..c43b4fd19d21d2 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileOperations.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileOperations.cs @@ -23,7 +23,8 @@ internal static partial class FileOperations internal const int FILE_FLAG_OVERLAPPED = 0x40000000; internal const int FILE_LIST_DIRECTORY = 0x0001; - } + internal const int FILE_WRITE_ATTRIBUTES = 0x100; + } } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.REPARSE_DATA_BUFFER.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.REPARSE_DATA_BUFFER.cs index 3bcb9162d57bfc..123ac9235b9fdc 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.REPARSE_DATA_BUFFER.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.REPARSE_DATA_BUFFER.cs @@ -14,24 +14,29 @@ internal static partial class Kernel32 internal const uint SYMLINK_FLAG_RELATIVE = 1; // https://msdn.microsoft.com/library/windows/hardware/ff552012.aspx - // We don't need all the struct fields; omitting the rest. [StructLayout(LayoutKind.Sequential)] - internal unsafe struct REPARSE_DATA_BUFFER + internal unsafe struct SymbolicLinkReparseBuffer { internal uint ReparseTag; internal ushort ReparseDataLength; internal ushort Reserved; - internal SymbolicLinkReparseBuffer ReparseBufferSymbolicLink; + internal ushort SubstituteNameOffset; + internal ushort SubstituteNameLength; + internal ushort PrintNameOffset; + internal ushort PrintNameLength; + internal uint Flags; + } - [StructLayout(LayoutKind.Sequential)] - internal struct SymbolicLinkReparseBuffer - { - internal ushort SubstituteNameOffset; - internal ushort SubstituteNameLength; - internal ushort PrintNameOffset; - internal ushort PrintNameLength; - internal uint Flags; - } + [StructLayout(LayoutKind.Sequential)] + internal struct MountPointReparseBuffer + { + public uint ReparseTag; + public ushort ReparseDataLength; + public ushort Reserved; + public ushort SubstituteNameOffset; + public ushort SubstituteNameLength; + public ushort PrintNameOffset; + public ushort PrintNameLength; } } } diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs index 1b86a149072899..463de2572b2b3f 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs @@ -109,6 +109,7 @@ internal static partial class WinHttp public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = 0x00000080; public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = 0x00000200; public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = 0x00000800; + public const uint WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 = 0x00002000; public const uint SECURITY_FLAG_IGNORE_UNKNOWN_CA = 0x00000100; public const uint SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = 0x00002000; @@ -167,6 +168,7 @@ internal static partial class WinHttp public const uint WINHTTP_OPTION_TCP_KEEPALIVE = 152; public const uint WINHTTP_OPTION_STREAM_ERROR_CODE = 159; + public const uint WINHTTP_OPTION_REQUIRE_STREAM_END = 160; public enum WINHTTP_WEB_SOCKET_BUFFER_TYPE { diff --git a/src/libraries/Common/src/Roslyn/GetBestTypeByMetadataName.cs b/src/libraries/Common/src/Roslyn/GetBestTypeByMetadataName.cs new file mode 100644 index 00000000000000..c86d7f2e00ebc4 --- /dev/null +++ b/src/libraries/Common/src/Roslyn/GetBestTypeByMetadataName.cs @@ -0,0 +1,138 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.CodeAnalysis.DotnetRuntime.Extensions +{ + internal static class RoslynExtensions + { + // Copied from: https://github.com/dotnet/roslyn/blob/main/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/CompilationExtensions.cs + /// + /// Gets a type by its metadata name to use for code analysis within a . This method + /// attempts to find the "best" symbol to use for code analysis, which is the symbol matching the first of the + /// following rules. + /// + /// + /// + /// If only one type with the given name is found within the compilation and its referenced assemblies, that + /// type is returned regardless of accessibility. + /// + /// + /// If the current defines the symbol, that symbol is returned. + /// + /// + /// If exactly one referenced assembly defines the symbol in a manner that makes it visible to the current + /// , that symbol is returned. + /// + /// + /// Otherwise, this method returns . + /// + /// + /// + /// The to consider for analysis. + /// The fully-qualified metadata type name to find. + /// The symbol to use for code analysis; otherwise, . + public static INamedTypeSymbol? GetBestTypeByMetadataName(this Compilation compilation, string fullyQualifiedMetadataName) + { + // Try to get the unique type with this name, ignoring accessibility + var type = compilation.GetTypeByMetadataName(fullyQualifiedMetadataName); + + // Otherwise, try to get the unique type with this name originally defined in 'compilation' + type ??= compilation.Assembly.GetTypeByMetadataName(fullyQualifiedMetadataName); + + // Otherwise, try to get the unique accessible type with this name from a reference + if (type is null) + { + foreach (var module in compilation.Assembly.Modules) + { + foreach (var referencedAssembly in module.ReferencedAssemblySymbols) + { + var currentType = referencedAssembly.GetTypeByMetadataName(fullyQualifiedMetadataName); + if (currentType is null) + continue; + + switch (currentType.GetResultantVisibility()) + { + case SymbolVisibility.Public: + case SymbolVisibility.Internal when referencedAssembly.GivesAccessTo(compilation.Assembly): + break; + + default: + continue; + } + + if (type is object) + { + // Multiple visible types with the same metadata name are present + return null; + } + + type = currentType; + } + } + } + + return type; + } + + // copied from https://github.com/dotnet/roslyn/blob/main/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/ISymbolExtensions.cs + private static SymbolVisibility GetResultantVisibility(this ISymbol symbol) + { + // Start by assuming it's visible. + SymbolVisibility visibility = SymbolVisibility.Public; + + switch (symbol.Kind) + { + case SymbolKind.Alias: + // Aliases are uber private. They're only visible in the same file that they + // were declared in. + return SymbolVisibility.Private; + + case SymbolKind.Parameter: + // Parameters are only as visible as their containing symbol + return GetResultantVisibility(symbol.ContainingSymbol); + + case SymbolKind.TypeParameter: + // Type Parameters are private. + return SymbolVisibility.Private; + } + + while (symbol != null && symbol.Kind != SymbolKind.Namespace) + { + switch (symbol.DeclaredAccessibility) + { + // If we see anything private, then the symbol is private. + case Accessibility.NotApplicable: + case Accessibility.Private: + return SymbolVisibility.Private; + + // If we see anything internal, then knock it down from public to + // internal. + case Accessibility.Internal: + case Accessibility.ProtectedAndInternal: + visibility = SymbolVisibility.Internal; + break; + + // For anything else (Public, Protected, ProtectedOrInternal), the + // symbol stays at the level we've gotten so far. + } + + symbol = symbol.ContainingSymbol; + } + + return visibility; + } + + // Copied from: https://github.com/dotnet/roslyn/blob/main/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/SymbolVisibility.cs +#pragma warning disable CA1027 // Mark enums with FlagsAttribute + private enum SymbolVisibility +#pragma warning restore CA1027 // Mark enums with FlagsAttribute + { + Public = 0, + Internal = 1, + Private = 2, + Friend = Internal, + } + } +} diff --git a/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs b/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs index 4928270b06f170..23b1d5959aced5 100644 --- a/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs +++ b/src/libraries/Common/tests/SourceGenerators/RoslynTestUtils.cs @@ -48,10 +48,10 @@ public static Project CreateTestProject(IEnumerable? references, bool } return new AdhocWorkspace() - .AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())) - .AddProject("Test", "test.dll", "C#") - .WithMetadataReferences(refs) - .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithNullableContextOptions(NullableContextOptions.Enable)); + .AddSolution(SolutionInfo.Create(SolutionId.CreateNewId(), VersionStamp.Create())) + .AddProject("Test", "test.dll", "C#") + .WithMetadataReferences(refs) + .WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary).WithNullableContextOptions(NullableContextOptions.Enable)); } public static Task CommitChanges(this Project proj, params string[] ignorables) @@ -141,23 +141,44 @@ public static TextSpan MakeSpan(string text, int spanNum) /// Runs a Roslyn generator over a set of source files. /// public static async Task<(ImmutableArray, ImmutableArray)> RunGenerator( +#if ROSLYN4_0_OR_GREATER + IIncrementalGenerator generator, +#else ISourceGenerator generator, +#endif IEnumerable? references, IEnumerable sources, - AnalyzerConfigOptionsProvider? optionsProvider = null, bool includeBaseReferences = true, CancellationToken cancellationToken = default) { Project proj = CreateTestProject(references, includeBaseReferences); - proj = proj.WithDocuments(sources); - Assert.True(proj.Solution.Workspace.TryApplyChanges(proj.Solution)); - Compilation? comp = await proj!.GetCompilationAsync(CancellationToken.None).ConfigureAwait(false); + return RunGenerator(comp!, generator, cancellationToken); + } - CSharpGeneratorDriver cgd = CSharpGeneratorDriver.Create(new[] { generator }, optionsProvider: optionsProvider); - GeneratorDriver gd = cgd.RunGenerators(comp!, cancellationToken); + /// + /// Runs a Roslyn generator given a Compilation. + /// + public static (ImmutableArray, ImmutableArray) RunGenerator( + Compilation compilation, +#if ROSLYN4_0_OR_GREATER + IIncrementalGenerator generator, +#else + ISourceGenerator generator, +#endif + CancellationToken cancellationToken = default) + { +#if ROSLYN4_0_OR_GREATER + // workaround https://github.com/dotnet/roslyn/pull/55866. We can remove "LangVersion=Preview" when we get a Roslyn build with that change. + CSharpParseOptions options = CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.Preview); + CSharpGeneratorDriver cgd = CSharpGeneratorDriver.Create(new[] { generator.AsSourceGenerator() }, parseOptions: options); +#else + CSharpGeneratorDriver cgd = CSharpGeneratorDriver.Create(new[] { generator }); +#endif + + GeneratorDriver gd = cgd.RunGenerators(compilation, cancellationToken); GeneratorDriverRunResult r = gd.GetRunResult(); return (r.Results[0].Diagnostics, r.Results[0].GeneratedSources); diff --git a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/linuxclient/Dockerfile b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/linuxclient/Dockerfile index 8bb94ba8aa9924..853582e7bcf3c1 100644 --- a/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/linuxclient/Dockerfile +++ b/src/libraries/Common/tests/System/Net/EnterpriseTests/setup/linuxclient/Dockerfile @@ -1,31 +1,12 @@ -# Switch to mcr.microsoft.com/dotnet-buildtools/prereqs ubuntu 18.04 images when they are fixed -FROM ubuntu:18.04 +FROM mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-20211022152710-047508b # Prevents dialog prompting when installing packages ARG DEBIAN_FRONTEND=noninteractive -# This 'RUN' step can be removed once dotnet-buildtools/prereqs image is fixed -# -# Makes the image capable of building and running tests in dotnet-runtime repo. -# Add retries to apt-get since the ubuntu package servers have had errors lately such as: -# "E: Failed to fetch http://archive.ubuntu.com/ubuntu/pool/main/p/publicsuffix/publicsuffix_20180223.1310-1_all.deb Undetermined Error [IP: 91.189.88.31 80]" -ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 -RUN echo "APT::Acquire::Retries \"10\";" > /etc/apt/apt.conf.d/80-retries && \ - apt-get update && \ - apt-get install -y --no-install-recommends apt-transport-https ca-certificates gnupg software-properties-common wget && \ - wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | apt-key add - && \ - apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' && \ - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | apt-key add - && \ - apt-add-repository 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main' && \ - apt-get update && \ - apt-get install -y --no-install-recommends cmake llvm-9 clang-9 lldb-6.0 liblldb-6.0-dev libunwind8 libunwind-dev gettext libicu-dev liblttng-ust-dev libssl-dev libnuma-dev libkrb5-dev locales && \ - locale-gen en_US.UTF-8 && \ - update-locale LANG=en_US.UTF-8 - # Install Kerberos, NTLM, and diagnostic tools COPY ./common/krb5.conf /etc/krb5.conf RUN apt-get update && \ - apt-get install -y --no-install-recommends krb5-user gss-ntlmssp iputils-ping dnsutils nano curl + apt-get install -y --no-install-recommends krb5-user gss-ntlmssp iputils-ping dnsutils nano # Set environment variable to turn on enterprise tests ENV DOTNET_RUNTIME_ENTERPRISETESTS_ENABLED 1 diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs index 958cb2abc1e156..346098414b39bd 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackStream.cs @@ -20,10 +20,10 @@ internal sealed class Http3LoopbackStream : IDisposable private const int MaximumVarIntBytes = 8; private const long VarIntMax = (1L << 62) - 1; - private const long DataFrame = 0x0; - private const long HeadersFrame = 0x1; - private const long SettingsFrame = 0x4; - private const long GoAwayFrame = 0x7; + public const long DataFrame = 0x0; + public const long HeadersFrame = 0x1; + public const long SettingsFrame = 0x4; + public const long GoAwayFrame = 0x7; public const long ControlStream = 0x0; public const long PushStream = 0x1; diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs index 41718d37eb869e..7d0a476dd1a951 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Authentication.cs @@ -203,7 +203,7 @@ public static IEnumerable Authentication_TestData() { yield return new object[] { "Basic realm=\"testrealm\"", true }; yield return new object[] { "Basic ", true }; - yield return new object[] { "Basic realm=withoutquotes", true }; + yield return new object[] { "Basic realm=PLACEHOLDERwithoutquotes", true }; yield return new object[] { "basic ", true }; yield return new object[] { "bAsiC ", true }; yield return new object[] { "basic", true }; diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs index 88ac334a06de97..439cadf32ae620 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Decompression.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Linq; using System.Net.Test.Common; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -26,19 +27,29 @@ public abstract class HttpClientHandler_Decompression_Test : HttpClientHandlerTe #endif public HttpClientHandler_Decompression_Test(ITestOutputHelper output) : base(output) { } + public static IEnumerable DecompressedResponse_MethodSpecified_DecompressedContentReturned_MemberData() => + from compressionName in new[] { "gzip", "zlib", "deflate", "br" } + from all in new[] { false, true } + from copyTo in new[] { false, true } + from contentLength in new[] { 0, 1, 12345 } + select new object[] { compressionName, all, copyTo, contentLength }; + [Theory] - [InlineData("gzip", false)] - [InlineData("gzip", true)] - [InlineData("deflate", false)] - [InlineData("deflate", true)] - [InlineData("br", false)] - [InlineData("br", true)] + [MemberData(nameof(DecompressedResponse_MethodSpecified_DecompressedContentReturned_MemberData))] [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")] - public async Task DecompressedResponse_MethodSpecified_DecompressedContentReturned(string encodingName, bool all) + public async Task DecompressedResponse_MethodSpecified_DecompressedContentReturned(string compressionName, bool all, bool useCopyTo, int contentLength) { + if (IsWinHttpHandler && + (compressionName == "br" || compressionName == "zlib")) + { + // brotli and zlib not supported on WinHttpHandler + return; + } + Func compress; DecompressionMethods methods; - switch (encodingName) + string encodingName = compressionName; + switch (compressionName) { case "gzip": compress = s => new GZipStream(s, CompressionLevel.Optimal, leaveOpen: true); @@ -47,32 +58,27 @@ public async Task DecompressedResponse_MethodSpecified_DecompressedContentReturn #if !NETFRAMEWORK case "br": - if (IsWinHttpHandler) - { - // Brotli only supported on SocketsHttpHandler. - return; - } - compress = s => new BrotliStream(s, CompressionLevel.Optimal, leaveOpen: true); methods = all ? DecompressionMethods.Brotli : _all; break; - case "deflate": - // WinHttpHandler continues to use DeflateStream as it doesn't have a newer build than netstandard2.0 - // and doesn't have access to ZLibStream. - compress = IsWinHttpHandler ? - new Func(s => new DeflateStream(s, CompressionLevel.Optimal, leaveOpen: true)) : - new Func(s => new ZLibStream(s, CompressionLevel.Optimal, leaveOpen: true)); + case "zlib": + compress = s => new ZLibStream(s, CompressionLevel.Optimal, leaveOpen: true); methods = all ? DecompressionMethods.Deflate : _all; + encodingName = "deflate"; break; #endif + case "deflate": + compress = s => new DeflateStream(s, CompressionLevel.Optimal, leaveOpen: true); + methods = all ? DecompressionMethods.Deflate : _all; + break; + default: - Assert.Contains(encodingName, new[] { "br", "deflate", "gzip" }); - return; + throw new Exception($"Unexpected compression: {compressionName}"); } - var expectedContent = new byte[12345]; + var expectedContent = new byte[contentLength]; new Random(42).NextBytes(expectedContent); await LoopbackServer.CreateClientAndServerAsync(async uri => @@ -81,7 +87,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => using (HttpClient client = CreateHttpClient(handler)) { handler.AutomaticDecompression = methods; - Assert.Equal(expectedContent, await client.GetByteArrayAsync(uri)); + AssertExtensions.SequenceEqual(expectedContent, await client.GetByteArrayAsync(TestAsync, useCopyTo, uri)); } }, async server => { @@ -99,33 +105,39 @@ await server.AcceptConnectionAsync(async connection => public static IEnumerable DecompressedResponse_MethodNotSpecified_OriginalContentReturned_MemberData() { - yield return new object[] + foreach (bool useCopyTo in new[] { false, true }) { - "gzip", - new Func(s => new GZipStream(s, CompressionLevel.Optimal, leaveOpen: true)), - DecompressionMethods.None - }; + yield return new object[] + { + "gzip", + new Func(s => new GZipStream(s, CompressionLevel.Optimal, leaveOpen: true)), + DecompressionMethods.None, + useCopyTo + }; #if !NETFRAMEWORK - yield return new object[] - { - "deflate", - new Func(s => new ZLibStream(s, CompressionLevel.Optimal, leaveOpen: true)), - DecompressionMethods.Brotli - }; - yield return new object[] - { - "br", - new Func(s => new BrotliStream(s, CompressionLevel.Optimal, leaveOpen: true)), - DecompressionMethods.Deflate | DecompressionMethods.GZip - }; + yield return new object[] + { + "deflate", + new Func(s => new ZLibStream(s, CompressionLevel.Optimal, leaveOpen: true)), + DecompressionMethods.Brotli, + useCopyTo + }; + yield return new object[] + { + "br", + new Func(s => new BrotliStream(s, CompressionLevel.Optimal, leaveOpen: true)), + DecompressionMethods.Deflate | DecompressionMethods.GZip, + useCopyTo + }; #endif + } } [Theory] [MemberData(nameof(DecompressedResponse_MethodNotSpecified_OriginalContentReturned_MemberData))] [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")] public async Task DecompressedResponse_MethodNotSpecified_OriginalContentReturned( - string encodingName, Func compress, DecompressionMethods methods) + string encodingName, Func compress, DecompressionMethods methods, bool useCopyTo) { var expectedContent = new byte[12345]; new Random(42).NextBytes(expectedContent); @@ -143,7 +155,7 @@ await LoopbackServer.CreateClientAndServerAsync(async uri => using (HttpClient client = CreateHttpClient(handler)) { handler.AutomaticDecompression = methods; - Assert.Equal(compressedContent, await client.GetByteArrayAsync(uri)); + AssertExtensions.SequenceEqual(compressedContent, await client.GetByteArrayAsync(TestAsync, useCopyTo, uri)); } }, async server => { @@ -156,6 +168,33 @@ await server.AcceptConnectionAsync(async connection => }); } + [Theory] + [InlineData("gzip", DecompressionMethods.GZip)] +#if !NETFRAMEWORK + [InlineData("deflate", DecompressionMethods.Deflate)] + [InlineData("br", DecompressionMethods.Brotli)] +#endif + [SkipOnPlatform(TestPlatforms.Browser, "AutomaticDecompression not supported on Browser")] + public async Task DecompressedResponse_EmptyBody_Success(string encodingName, DecompressionMethods methods) + { + await LoopbackServer.CreateClientAndServerAsync(async uri => + { + using (HttpClientHandler handler = CreateHttpClientHandler()) + using (HttpClient client = CreateHttpClient(handler)) + { + handler.AutomaticDecompression = methods; + Assert.Equal(Array.Empty(), await client.GetByteArrayAsync(TestAsync, useCopyTo: false, uri)); + } + }, async server => + { + await server.AcceptConnectionAsync(async connection => + { + await connection.ReadRequestHeaderAsync(); + await connection.WriteStringAsync($"HTTP/1.1 200 OK\r\nContent-Encoding: {encodingName}\r\n\r\n"); + }); + }); + } + [Theory] #if NETCOREAPP [InlineData(DecompressionMethods.Brotli, "br", "")] diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs index 9fd29a905f97f2..5e8b94d33705cc 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.RemoteServer.cs @@ -136,7 +136,7 @@ public async Task GetAsync_ServerNeedsBasicAuthAndSetDefaultCredentials_StatusCo handler.Credentials = CredentialCache.DefaultCredentials; using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler)) { - Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); + Uri uri = remoteServer.BasicAuthUriForCreds(Username, Password); using (HttpResponseMessage response = await client.GetAsync(uri)) { Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -153,7 +153,7 @@ public async Task GetAsync_ServerNeedsAuthAndSetCredential_StatusCodeOK(Configur handler.Credentials = _credential; using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler)) { - Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); + Uri uri = remoteServer.BasicAuthUriForCreds(Username, Password); using (HttpResponseMessage response = await client.GetAsync(uri)) { Assert.Equal(HttpStatusCode.OK, response.StatusCode); @@ -167,7 +167,7 @@ public async Task GetAsync_ServerNeedsAuthAndNoCredential_StatusCodeUnauthorized { using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer)) { - Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); + Uri uri = remoteServer.BasicAuthUriForCreds(Username, Password); using (HttpResponseMessage response = await client.GetAsync(uri)) { Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); @@ -1033,7 +1033,7 @@ public async Task GetAsync_AllowAutoRedirectTrue_RedirectToUriWithParams_Request { HttpClientHandler handler = CreateHttpClientHandler(); handler.AllowAutoRedirect = true; - Uri targetUri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); + Uri targetUri = remoteServer.BasicAuthUriForCreds(Username, Password); using (HttpClient client = CreateHttpClientForRemoteServer(remoteServer, handler)) { Uri uri = remoteServer.RedirectUriForDestinationUri( @@ -1133,8 +1133,8 @@ public async Task GetAsync_CredentialIsNetworkCredentialUriRedirect_StatusCodeUn { Uri redirectUri = remoteServer.RedirectUriForCreds( statusCode: 302, - userName: Username, - password: Password); + Username, + Password); using (HttpResponseMessage unAuthResponse = await client.GetAsync(redirectUri)) { Assert.Equal(HttpStatusCode.Unauthorized, unAuthResponse.StatusCode); @@ -1153,15 +1153,15 @@ public async Task HttpClientHandler_CredentialIsNotCredentialCacheAfterRedirect_ { Uri redirectUri = remoteServer.RedirectUriForCreds( statusCode: 302, - userName: Username, - password: Password); + Username, + Password); using (HttpResponseMessage unAuthResponse = await client.GetAsync(redirectUri)) { Assert.Equal(HttpStatusCode.Unauthorized, unAuthResponse.StatusCode); } // Use the same handler to perform get request, authentication should succeed after redirect. - Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); + Uri uri = remoteServer.BasicAuthUriForCreds(Username, Password); using (HttpResponseMessage authResponse = await client.GetAsync(uri)) { Assert.Equal(HttpStatusCode.OK, authResponse.StatusCode); @@ -1180,11 +1180,11 @@ public async Task GetAsync_CredentialIsCredentialCacheUriRedirect_StatusCodeOK(C return; } - Uri uri = remoteServer.BasicAuthUriForCreds(userName: Username, password: Password); + Uri uri = remoteServer.BasicAuthUriForCreds(Username, Password); Uri redirectUri = remoteServer.RedirectUriForCreds( statusCode: statusCode, - userName: Username, - password: Password); + Username, + Password); _output.WriteLine(uri.AbsoluteUri); _output.WriteLine(redirectUri.AbsoluteUri); var credentialCache = new CredentialCache(); @@ -1237,8 +1237,9 @@ public static IEnumerable RemoteServersAndCompressionUris() { yield return new object[] { remoteServer, remoteServer.GZipUri }; - // Remote deflate endpoint isn't correctly following the deflate protocol. - //yield return new object[] { remoteServer, remoteServer.DeflateUri }; + // Remote deflate endpoint isn't correctly following the deflate protocol, + // but SocketsHttpHandler makes it work, anyway. + yield return new object[] { remoteServer, remoteServer.DeflateUri }; } } @@ -1271,10 +1272,6 @@ public async Task GetAsync_SetAutomaticDecompression_ContentDecompressed_GZip(Co } } - // The remote server endpoint was written to use DeflateStream, which isn't actually a correct - // implementation of the deflate protocol (the deflate protocol requires the zlib wrapper around - // deflate). Until we can get that updated (and deal with previous releases still testing it - // via a DeflateStream-based implementation), we utilize httpbin.org to help validate behavior. [OuterLoop("Uses external servers")] [Theory] [InlineData("http://httpbin.org/deflate", "\"deflated\": true")] diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs index da250bf305f32c..5a643c09aec385 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.SslProtocols.cs @@ -121,7 +121,7 @@ public async Task GetAsync_AllowedSSLVersion_Succeeds(SslProtocols acceptedProto #if !NETFRAMEWORK handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13; #else - handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12; + handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | (SslProtocols)12288; #endif #pragma warning restore 0618 } diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 17fcd64ee26d80..291611cd60ffcc 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -399,7 +399,7 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() } const string content = "hello world"; - + string authSafeValue = "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; // Using examples from https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields // Exercises all exposed request.Headers and request.Content.Headers strongly-typed properties await LoopbackServerFactory.CreateClientAndServerAsync(async uri => @@ -421,7 +421,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => request.Headers.Add("Access-Control-Request-Method", "GET"); request.Headers.Add("Access-Control-Request-Headers", "GET"); request.Headers.Add("Age", "12"); - request.Headers.Authorization = new AuthenticationHeaderValue("Basic", "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); + request.Headers.Authorization = new AuthenticationHeaderValue("Basic", authSafeValue); request.Headers.CacheControl = new CacheControlHeaderValue() { NoCache = true }; request.Headers.Connection.Add("close"); request.Headers.Add("Cookie", "$Version=1; Skin=new"); @@ -444,7 +444,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => request.Headers.MaxForwards = 10; request.Headers.Add("Origin", "http://www.example-social-network.com"); request.Headers.Pragma.Add(new NameValueHeaderValue("no-cache")); - request.Headers.ProxyAuthorization = new AuthenticationHeaderValue("Basic", "QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); + request.Headers.ProxyAuthorization = new AuthenticationHeaderValue("Basic", authSafeValue); request.Headers.Range = new RangeHeaderValue(500, 999); request.Headers.Referrer = new Uri("http://en.wikipedia.org/wiki/Main_Page"); request.Headers.TE.Add(new TransferCodingWithQualityHeaderValue("trailers")); @@ -504,7 +504,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => Assert.Equal("GET", requestData.GetSingleHeaderValue("Access-Control-Request-Headers")); } Assert.Equal("12", requestData.GetSingleHeaderValue("Age")); - Assert.Equal("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", requestData.GetSingleHeaderValue("Authorization")); + Assert.Equal($"Basic {authSafeValue}", requestData.GetSingleHeaderValue("Authorization")); Assert.Equal("no-cache", requestData.GetSingleHeaderValue("Cache-Control")); if (PlatformDetection.IsNotBrowser) { @@ -512,7 +512,7 @@ await LoopbackServerFactory.CreateClientAndServerAsync(async uri => Assert.Equal("Tue, 15 Nov 1994 08:12:31 GMT", requestData.GetSingleHeaderValue("Date")); Assert.Equal("100-continue", requestData.GetSingleHeaderValue("Expect")); Assert.Equal("http://www.example-social-network.com", requestData.GetSingleHeaderValue("Origin")); - Assert.Equal("Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", requestData.GetSingleHeaderValue("Proxy-Authorization")); + Assert.Equal($"Basic {authSafeValue}", requestData.GetSingleHeaderValue("Proxy-Authorization")); Assert.Equal("Mozilla/5.0", requestData.GetSingleHeaderValue("User-Agent")); Assert.Equal("http://en.wikipedia.org/wiki/Main_Page", requestData.GetSingleHeaderValue("Referer")); Assert.Equal("MyTrailer", requestData.GetSingleHeaderValue("Trailer")); diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs index 7d56c4ce48838b..798b23907cc9c0 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTestBase.cs @@ -196,5 +196,47 @@ public static Task ReadAsStreamAsync(this HttpContent content, bool asyn #endif } } + + public static Task GetByteArrayAsync(this HttpClient client, bool async, bool useCopyTo, Uri uri) + { +#if NETCOREAPP + return Task.Run(async () => + { + var m = new HttpRequestMessage(HttpMethod.Get, uri); + using HttpResponseMessage r = async ? await client.SendAsync(m, HttpCompletionOption.ResponseHeadersRead) : client.Send(m, HttpCompletionOption.ResponseHeadersRead); + using Stream s = async ? await r.Content.ReadAsStreamAsync() : r.Content.ReadAsStream(); + + var result = new MemoryStream(); + if (useCopyTo) + { + if (async) + { + await s.CopyToAsync(result); + } + else + { + s.CopyTo(result); + } + } + else + { + byte[] buffer = new byte[100]; + while (true) + { + int bytesRead = async ? await s.ReadAsync(buffer) : s.Read(buffer); + if (bytesRead == 0) + { + break; + } + result.Write(buffer.AsSpan(0, bytesRead)); + } + } + return result.ToArray(); + }); +#else + // For WinHttpHandler on .NET Framework, we fall back to ignoring async and useCopyTo. + return client.GetByteArrayAsync(uri); +#endif + } } } diff --git a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs index 7594b4908010fc..ff4b34630525bd 100644 --- a/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs +++ b/src/libraries/Common/tests/System/Net/Http/LoopbackServer.cs @@ -866,6 +866,12 @@ public override async Task ReadRequestBodyAsync() return buffer; } + public void CompleteRequestProcessing() + { + _contentLength = 0; + _bodyRead = false; + } + public override async Task SendResponseAsync(HttpStatusCode statusCode = HttpStatusCode.OK, IList headers = null, string content = "", bool isFinal = true, int requestId = 0) { MemoryStream headerBytes = new MemoryStream(); diff --git a/src/libraries/Common/tests/System/Net/Sockets/TestSettings.cs b/src/libraries/Common/tests/System/Net/Sockets/TestSettings.cs index 0accade3d3f445..164b4b8632a43b 100644 --- a/src/libraries/Common/tests/System/Net/Sockets/TestSettings.cs +++ b/src/libraries/Common/tests/System/Net/Sockets/TestSettings.cs @@ -8,7 +8,8 @@ namespace System.Net.Sockets.Tests public static class TestSettings { // Timeout values in milliseconds. - public const int PassingTestTimeout = 10000; + public const int PassingTestTimeout = 10_000; + public const int PassingTestLongTimeout = 30_000; public const int FailingTestTimeout = 100; public static Task WhenAllOrAnyFailedWithTimeout(params Task[] tasks) => tasks.WhenAllOrAnyFailed(PassingTestTimeout); diff --git a/src/libraries/Common/tests/System/Runtime/Serialization/Utils.cs b/src/libraries/Common/tests/System/Runtime/Serialization/Utils.cs index ca01381a6dff10..2e2ac299c2c53b 100644 --- a/src/libraries/Common/tests/System/Runtime/Serialization/Utils.cs +++ b/src/libraries/Common/tests/System/Runtime/Serialization/Utils.cs @@ -9,6 +9,8 @@ using System.Threading.Tasks; using System.Xml.Linq; using System.Linq; +using System.Reflection; +using System.Runtime.Loader; using Xunit; internal static class Utils @@ -351,3 +353,30 @@ private static bool IsPrefixedAttributeValue(string atrValue, out string localPr return false; } } + +internal class TestAssemblyLoadContext : AssemblyLoadContext +{ + private AssemblyDependencyResolver _resolver; + + public TestAssemblyLoadContext(string name, bool isCollectible, string mainAssemblyToLoadPath = null) : base(name, isCollectible) + { + if (!PlatformDetection.IsBrowser) + _resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath ?? Assembly.GetExecutingAssembly().Location); + } + + protected override Assembly Load(AssemblyName name) + { + if (PlatformDetection.IsBrowser) + { + return base.Load(name); + } + + string assemblyPath = _resolver.ResolveAssemblyToPath(name); + if (assemblyPath != null) + { + return LoadFromAssemblyPath(assemblyPath); + } + + return null; + } +} diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs index 2b814f581f90d5..197fcc49f113b7 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDiffieHellman/ECDhKeyFileTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.EcDiffieHellman.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64389", TestPlatforms.Windows)] public class ECDhKeyFileTests : ECKeyFileTests { protected override ECDiffieHellman CreateKey() diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs index 46f88abb735a0d..d95a3f060622ec 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/ECDsa/ECDsaKeyFileTests.cs @@ -7,6 +7,7 @@ namespace System.Security.Cryptography.EcDsa.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64389", TestPlatforms.Windows)] public class ECDsaKeyFileTests : ECKeyFileTests { protected override ECDsa CreateKey() diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs index 99492706f7ec99..db93bcd06c4550 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Unix.cs @@ -41,6 +41,8 @@ public static partial class PlatformDetection public static bool IsMacOsCatalinaOrHigher => IsOSX && Environment.OSVersion.Version >= new Version(10, 15); public static bool IsMacOsAppleSilicon => IsOSX && IsArm64Process; public static bool IsNotMacOsAppleSilicon => !IsMacOsAppleSilicon; + public static bool IsAppSandbox => Environment.GetEnvironmentVariable("APP_SANDBOX_CONTAINER_ID") != null; + public static bool IsNotAppSandbox => !IsAppSandbox; // RedHat family covers RedHat and CentOS public static bool IsRedHatFamily => IsRedHatFamilyAndVersion(); @@ -55,6 +57,11 @@ public static partial class PlatformDetection GetOpenSslVersion() : throw new PlatformNotSupportedException(); + private static readonly Version s_openssl3Version = new Version(3, 0, 0); + public static bool IsOpenSsl3 => !IsOSXLike && !IsWindows && !IsAndroid && !IsBrowser ? + GetOpenSslVersion() >= s_openssl3Version : + false; + /// /// If gnulibc is available, returns the release, such as "stable". /// Otherwise returns "glibc_not_found". diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs index 078f29be48e685..cf5e4b86b87b84 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.Windows.cs @@ -57,6 +57,9 @@ public static partial class PlatformDetection public static bool IsWindows10Version2004Build19573OrGreater => IsWindowsVersionOrLater(10, 0, 19573); + // Windows 11 aka 21H2 + public static bool IsWindows10Version22000OrGreater => IsWindowsVersionOrLater(10, 0, 22000); + public static bool IsWindowsIoTCore { get @@ -231,6 +234,8 @@ public static bool IsInAppContainer } } + public static bool CanRunImpersonatedTests => PlatformDetection.IsNotWindowsNanoServer && PlatformDetection.IsWindowsAndElevated; + private static int s_isWindowsElevated = -1; public static bool IsWindowsAndElevated { diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index efef067dbce645..6b77b65fefd101 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -48,6 +48,7 @@ public static partial class PlatformDetection public static bool IsNotArm64Process => !IsArm64Process; public static bool IsArmOrArm64Process => IsArmProcess || IsArm64Process; public static bool IsNotArmNorArm64Process => !IsArmOrArm64Process; + public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86; public static bool IsArgIteratorSupported => IsMonoRuntime || (IsWindows && IsNotArmProcess); public static bool IsArgIteratorNotSupported => !IsArgIteratorSupported; public static bool Is32BitProcess => IntPtr.Size == 4; @@ -189,7 +190,12 @@ private static bool GetAlpnSupport() if (IsOpenSslSupported) { - return OpenSslVersion.Major >= 1 && (OpenSslVersion.Minor >= 1 || OpenSslVersion.Build >= 2); + if (OpenSslVersion.Major >= 3) + { + return true; + } + + return OpenSslVersion.Major == 1 && (OpenSslVersion.Minor >= 1 || OpenSslVersion.Build >= 2); } if (IsAndroid) @@ -267,6 +273,28 @@ private static bool GetStaticNonPublicBooleanPropertyValue(string typeName, stri public static bool IsIcuGlobalization => ICUVersion > new Version(0,0,0,0); public static bool IsNlsGlobalization => IsNotInvariantGlobalization && !IsIcuGlobalization; + public static bool IsSubstAvailable + { + get + { + try + { + if (IsWindows) + { + string systemRoot = Environment.GetEnvironmentVariable("SystemRoot"); + if (string.IsNullOrWhiteSpace(systemRoot)) + { + return false; + } + string system32 = Path.Combine(systemRoot, "System32"); + return File.Exists(Path.Combine(system32, "subst.exe")); + } + } + catch { } + return false; + } + } + private static Version GetICUVersion() { int version = 0; diff --git a/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs b/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs new file mode 100644 index 00000000000000..b0355f923295e4 --- /dev/null +++ b/src/libraries/Common/tests/TestUtilities/System/WindowsIdentityFixture.cs @@ -0,0 +1,148 @@ +// 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.ComponentModel; +using System.Linq; +using System.Net; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.Win32.SafeHandles; +using Xunit; + +namespace System +{ + public class WindowsIdentityFixture : IDisposable + { + public WindowsTestAccount TestAccount { get; private set; } + + public WindowsIdentityFixture() + { + TestAccount = new WindowsTestAccount("CorFxTstWiIde01kiu"); + } + + public void Dispose() + { + TestAccount.Dispose(); + } + } + + public sealed class WindowsTestAccount : IDisposable + { + private readonly string _userName; + private SafeAccessTokenHandle _accountTokenHandle; + public SafeAccessTokenHandle AccountTokenHandle => _accountTokenHandle; + public string AccountName { get; private set; } + + public WindowsTestAccount(string userName) + { + Assert.True(PlatformDetection.IsWindowsAndElevated); + + _userName = userName; + CreateUser(); + } + + private void CreateUser() + { + string testAccountPassword; + using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) + { + byte[] randomBytes = new byte[33]; + rng.GetBytes(randomBytes); + + // Add special chars to ensure it satisfies password requirements. + testAccountPassword = Convert.ToBase64String(randomBytes) + "_-As@!%*(1)4#2"; + + USER_INFO_1 userInfo = new USER_INFO_1 + { + usri1_name = _userName, + usri1_password = testAccountPassword, + usri1_priv = 1 + }; + + // Create user and remove/create if already exists + uint result = NetUserAdd(null, 1, ref userInfo, out uint param_err); + + // error codes https://docs.microsoft.com/en-us/windows/desktop/netmgmt/network-management-error-codes + // 0 == NERR_Success + if (result == 2224) // NERR_UserExists + { + result = NetUserDel(null, userInfo.usri1_name); + if (result != 0) + { + throw new Win32Exception((int)result); + } + result = NetUserAdd(null, 1, ref userInfo, out param_err); + if (result != 0) + { + throw new Win32Exception((int)result); + } + } + else if (result != 0) + { + throw new Win32Exception((int)result); + } + + const int LOGON32_PROVIDER_DEFAULT = 0; + const int LOGON32_LOGON_INTERACTIVE = 2; + + if (!LogonUser(_userName, ".", testAccountPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out _accountTokenHandle)) + { + _accountTokenHandle = null; + throw new Exception($"Failed to get SafeAccessTokenHandle for test account {_userName}", new Win32Exception()); + } + + bool gotRef = false; + try + { + _accountTokenHandle.DangerousAddRef(ref gotRef); + IntPtr logonToken = _accountTokenHandle.DangerousGetHandle(); + AccountName = new WindowsIdentity(logonToken).Name; + } + finally + { + if (gotRef) + _accountTokenHandle.DangerousRelease(); + } + } + } + + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] + private static extern bool LogonUser(string userName, string domain, string password, int logonType, int logonProvider, out SafeAccessTokenHandle safeAccessTokenHandle); + + [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern uint NetUserAdd([MarshalAs(UnmanagedType.LPWStr)]string servername, uint level, ref USER_INFO_1 buf, out uint parm_err); + + [DllImport("netapi32.dll")] + internal static extern uint NetUserDel([MarshalAs(UnmanagedType.LPWStr)]string servername, [MarshalAs(UnmanagedType.LPWStr)]string username); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct USER_INFO_1 + { + public string usri1_name; + public string usri1_password; + public uint usri1_password_age; + public uint usri1_priv; + public string usri1_home_dir; + public string usri1_comment; + public uint usri1_flags; + public string usri1_script_path; + } + + public void Dispose() + { + _accountTokenHandle?.Dispose(); + + uint result = NetUserDel(null, _userName); + + // 2221= NERR_UserNotFound + if (result != 0 && result != 2221) + { + throw new Win32Exception((int)result); + } + } + } + } + diff --git a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj index 375fca4e582f8d..8400cd7e721e69 100644 --- a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj +++ b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj @@ -33,6 +33,7 @@ + + - - diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index e81806e83421f2..85f79abb6ce913 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -25,6 +25,13 @@ + + + true + + + + false @@ -109,6 +116,9 @@ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(TestArchiveRoot)runtime/ + true + $(ArtifactsDir)bundles\ + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'ref', '$(NetCoreAppCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'runtime', '$(NetCoreAppCurrent)-$(TargetOS)-$(Configuration)-$(TargetArchitecture)')) @@ -138,7 +148,7 @@ $([MSBuild]::NormalizeDirectory($(SdkWithNoWorkloadForTestingPath))) $(SdkWithNoWorkloadForTestingPath)version-$(SdkVersionForWorkloadTesting).stamp - $(SdkWithWorkloadForTestingPath)workload.stamp + $(SdkWithNoWorkloadForTestingPath)workload.stamp $(ArtifactsBinDir)dotnet-workload\ $([MSBuild]::NormalizeDirectory($(SdkWithWorkloadForTestingPath))) diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index ca9b42f35ca9f1..a1e5b08838bbf6 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -218,8 +218,9 @@ + - true + true @@ -228,9 +229,11 @@ true + true + @@ -260,6 +263,7 @@ Returns="@(_AnalyzerPackFile)"> <_analyzerPath>analyzers/dotnet + <_analyzerPath Condition="'$(AnalyzerRoslynVersion)' != ''">$(_analyzerPath)/roslyn$(AnalyzerRoslynVersion) <_analyzerPath Condition="'$(AnalyzerLanguage)' != ''">$(_analyzerPath)/$(AnalyzerLanguage) diff --git a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml deleted file mode 100644 index 13579d318e7039..00000000000000 --- a/src/libraries/Microsoft.Bcl.AsyncInterfaces/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - CP0001 - lib/netstandard2.0/Microsoft.Bcl.AsyncInterfaces.dll - lib/netstandard2.1/Microsoft.Bcl.AsyncInterfaces.dll - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Microsoft.Diagnostics.Tracing.EventSource.Redist.csproj b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Microsoft.Diagnostics.Tracing.EventSource.Redist.csproj index 9e17bd12e7cb72..6d2b9e91c040d9 100644 --- a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Microsoft.Diagnostics.Tracing.EventSource.Redist.csproj +++ b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/src/Microsoft.Diagnostics.Tracing.EventSource.Redist.csproj @@ -10,7 +10,7 @@ Microsoft.Diagnostics.Tracing.EventSource $(MSBuildProjectName) Microsoft.Diagnostics.Tracing.EventSource $(DefineConstants);NO_EVENTCOMMANDEXECUTED_SUPPORT;ES_BUILD_STANDALONE;FEATURE_MANAGED_ETW;TARGET_WINDOWS - net461-windows + net461 enable true true diff --git a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/tests/Microsoft.Diagnostics.Tracing.EventSource.Redist.Tests.csproj b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/tests/Microsoft.Diagnostics.Tracing.EventSource.Redist.Tests.csproj index 46457b709cc375..7ad4466cda7690 100644 --- a/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/tests/Microsoft.Diagnostics.Tracing.EventSource.Redist.Tests.csproj +++ b/src/libraries/Microsoft.Diagnostics.Tracing.EventSource.Redist/tests/Microsoft.Diagnostics.Tracing.EventSource.Redist.Tests.csproj @@ -2,7 +2,7 @@ $(DefineConstants);USE_MDT_EVENTSOURCE true - net461-windows + net461 ..\..\System.Diagnostics.Tracing\tests diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.sln b/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.sln index cbb219a495e05c..6fb211776e5f5c 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.sln +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/Microsoft.Extensions.Caching.Memory.sln @@ -23,8 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{78971B06-2519-45B7-B761-C8A30C168EBE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{727A5FD3-0146-4E1E-81B6-E71D0C1A055E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{BDC4E2D9-627A-4DE2-BF31-A95351C1CB7C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{C76753D0-F564-45E9-AA60-A846EFE0A414}" @@ -121,10 +119,6 @@ Global {21CD6C35-65E2-414A-B9A1-22A0DD57977A}.Debug|Any CPU.Build.0 = Debug|Any CPU {21CD6C35-65E2-414A-B9A1-22A0DD57977A}.Release|Any CPU.ActiveCfg = Release|Any CPU {21CD6C35-65E2-414A-B9A1-22A0DD57977A}.Release|Any CPU.Build.0 = Release|Any CPU - {727A5FD3-0146-4E1E-81B6-E71D0C1A055E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {727A5FD3-0146-4E1E-81B6-E71D0C1A055E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {727A5FD3-0146-4E1E-81B6-E71D0C1A055E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {727A5FD3-0146-4E1E-81B6-E71D0C1A055E}.Release|Any CPU.Build.0 = Release|Any CPU {B6D30918-C1B7-4225-A809-E13A5817DE22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6D30918-C1B7-4225-A809-E13A5817DE22}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6D30918-C1B7-4225-A809-E13A5817DE22}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -161,7 +155,6 @@ Global {DA43AA92-35BA-4B84-BAA2-C3BB56C8BB3B} = {67719AA1-52DC-4E35-B6F7-2F53A50B913A} {78971B06-2519-45B7-B761-C8A30C168EBE} = {67719AA1-52DC-4E35-B6F7-2F53A50B913A} {21CD6C35-65E2-414A-B9A1-22A0DD57977A} = {67719AA1-52DC-4E35-B6F7-2F53A50B913A} - {727A5FD3-0146-4E1E-81B6-E71D0C1A055E} = {67719AA1-52DC-4E35-B6F7-2F53A50B913A} {B6D30918-C1B7-4225-A809-E13A5817DE22} = {67719AA1-52DC-4E35-B6F7-2F53A50B913A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs index 35121fc86ebc34..d9fa37e8cf8343 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs @@ -395,9 +395,10 @@ public void Compact(double percentage) private void Compact(long removalSizeTarget, Func computeEntrySize) { var entriesToRemove = new List(); - var lowPriEntries = new List(); - var normalPriEntries = new List(); - var highPriEntries = new List(); + // cache LastAccessed outside of the CacheEntry so it is stable during compaction + var lowPriEntries = new List(); + var normalPriEntries = new List(); + var highPriEntries = new List(); long removedSize = 0; // Sort items by expired & priority status @@ -415,13 +416,13 @@ private void Compact(long removalSizeTarget, Func computeEntry switch (entry.Priority) { case CacheItemPriority.Low: - lowPriEntries.Add(entry); + lowPriEntries.Add(new CompactPriorityEntry(entry, entry.LastAccessed)); break; case CacheItemPriority.Normal: - normalPriEntries.Add(entry); + normalPriEntries.Add(new CompactPriorityEntry(entry, entry.LastAccessed)); break; case CacheItemPriority.High: - highPriEntries.Add(entry); + highPriEntries.Add(new CompactPriorityEntry(entry, entry.LastAccessed)); break; case CacheItemPriority.NeverRemove: break; @@ -445,7 +446,7 @@ private void Compact(long removalSizeTarget, Func computeEntry // ?. Items with the soonest absolute expiration. // ?. Items with the soonest sliding expiration. // ?. Larger objects - estimated by object graph size, inaccurate. - static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, Func computeEntrySize, List entriesToRemove, List priorityEntries) + static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, Func computeEntrySize, List entriesToRemove, List priorityEntries) { // Do we meet our quota by just removing expired entries? if (removalSizeTarget <= removedSize) @@ -458,9 +459,10 @@ static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, F // TODO: Refine policy // LRU - priorityEntries.Sort((e1, e2) => e1.LastAccessed.CompareTo(e2.LastAccessed)); - foreach (CacheEntry entry in priorityEntries) + priorityEntries.Sort(static (e1, e2) => e1.LastAccessed.CompareTo(e2.LastAccessed)); + foreach (CompactPriorityEntry priorityEntry in priorityEntries) { + CacheEntry entry = priorityEntry.Entry; entry.SetExpired(EvictionReason.Capacity); entriesToRemove.Add(entry); removedSize += computeEntrySize(entry); @@ -473,6 +475,20 @@ static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, F } } + // use a struct instead of a ValueTuple to avoid adding a new dependency + // on System.ValueTuple on .NET Framework in a servicing release + private readonly struct CompactPriorityEntry + { + public readonly CacheEntry Entry; + public readonly DateTimeOffset LastAccessed; + + public CompactPriorityEntry(CacheEntry entry, DateTimeOffset lastAccessed) + { + Entry = entry; + LastAccessed = lastAccessed; + } + } + public void Dispose() { Dispose(true); diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/Microsoft.Extensions.Caching.Memory.csproj b/src/libraries/Microsoft.Extensions.Caching.Memory/src/Microsoft.Extensions.Caching.Memory.csproj index 495c645ba993ad..a65eda71abed6a 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/Microsoft.Extensions.Caching.Memory.csproj +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/Microsoft.Extensions.Caching.Memory.csproj @@ -4,6 +4,7 @@ netstandard2.0;net461 true In-memory cache implementation of Microsoft.Extensions.Caching.Memory.IMemoryCache. + 1 diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/CompactTests.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/CompactTests.cs index 3d9c2625b19ed9..10b9cce7c4d459 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/tests/CompactTests.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/tests/CompactTests.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Internal; using Xunit; @@ -83,4 +85,60 @@ public void CompactPrioritizesLRU() Assert.Equal("value4", cache.Get("key4")); } } + + [CollectionDefinition(nameof(DisableParallelization), DisableParallelization = true)] + public class DisableParallelization { } + + [Collection(nameof(DisableParallelization))] + public class CompactTestsDisableParallelization + { + /// + /// Tests a race condition in Compact where CacheEntry.LastAccessed is getting updated + /// by a different thread than what is doing the Compact, leading to sorting failing. + /// + /// See https://github.com/dotnet/runtime/issues/61032. + /// + [Fact] + public void CompactLastAccessedRaceCondition() + { + const int numEntries = 100; + MemoryCache cache = new MemoryCache(new MemoryCacheOptions()); + Random random = new Random(); + + void FillCache() + { + for (int i = 0; i < numEntries; i++) + { + cache.Set($"key{i}", $"value{i}"); + } + } + + // start a few tasks to access entries in the background + Task[] backgroundAccessTasks = new Task[Environment.ProcessorCount]; + bool done = false; + + for (int i = 0; i < backgroundAccessTasks.Length; i++) + { + backgroundAccessTasks[i] = Task.Run(async () => + { + while (!done) + { + cache.TryGetValue($"key{random.Next(numEntries)}", out _); + await Task.Yield(); + } + }); + } + + for (int i = 0; i < 1000; i++) + { + FillCache(); + + cache.Compact(1); + } + + done = true; + + Task.WaitAll(backgroundAccessTasks); + } + } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs index 5ea29116ca2d9b..55f5290cd13da9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/EnvironmentVariablesConfigurationProvider.cs @@ -78,17 +78,9 @@ internal void Load(IDictionary envVariables) { prefix = CustomPrefix; } - else if (key.StartsWith(_prefix, StringComparison.OrdinalIgnoreCase)) - { - // This prevents the prefix from being normalized. - // We can also do a fast path branch, I guess? No point in reallocating if the prefix is empty. - key = NormalizeKey(key.Substring(_prefix.Length)); - data[key] = entry.Value as string; - - continue; - } else { + AddIfPrefixed(data, NormalizeKey(key), (string?)entry.Value); continue; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/Microsoft.Extensions.Configuration.EnvironmentVariables.csproj b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/Microsoft.Extensions.Configuration.EnvironmentVariables.csproj index c12fa852d9b768..8983f7795cb97f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/Microsoft.Extensions.Configuration.EnvironmentVariables.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/src/Microsoft.Extensions.Configuration.EnvironmentVariables.csproj @@ -4,6 +4,7 @@ netstandard2.0;net461 true Environment variables configuration provider implementation for Microsoft.Extensions.Configuration. + 1 diff --git a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs index c5b1030ee74a0b..1e98a5767096a0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.EnvironmentVariables/tests/EnvironmentVariablesTest.cs @@ -166,7 +166,7 @@ public void ReplaceDoubleUnderscoreInEnvironmentVariablesButNotPrefix() envConfigSrc.Load(dict); - Assert.Equal("connection", envConfigSrc.Get("data:ConnectionString")); + Assert.Throws(() => envConfigSrc.Get("data:ConnectionString")); } [Fact] @@ -176,7 +176,7 @@ public void ReplaceDoubleUnderscoreInEnvironmentVariablesButNotInAnomalousPrefix { {"_____EXPERIMENTAL__data__ConnectionString", "connection"} }; - var envConfigSrc = new EnvironmentVariablesConfigurationProvider("_____EXPERIMENTAL__"); + var envConfigSrc = new EnvironmentVariablesConfigurationProvider("::_EXPERIMENTAL:"); envConfigSrc.Load(dict); @@ -194,7 +194,7 @@ public void ReplaceDoubleUnderscoreInEnvironmentVariablesWithDuplicatedPrefix() envConfigSrc.Load(dict); - Assert.Equal("connection", envConfigSrc.Get("test:ConnectionString")); + Assert.Throws(() => envConfigSrc.Get("test:ConnectionString")); } [Fact] @@ -205,7 +205,7 @@ public void PrefixPreventsLoadingSqlConnectionStrings() {"test__test__ConnectionString", "connection"}, {"SQLCONNSTR_db1", "connStr"} }; - var envConfigSrc = new EnvironmentVariablesConfigurationProvider("test__"); + var envConfigSrc = new EnvironmentVariablesConfigurationProvider("test:"); envConfigSrc.Load(dict); @@ -213,6 +213,54 @@ public void PrefixPreventsLoadingSqlConnectionStrings() Assert.Throws(() => envConfigSrc.Get("ConnectionStrings:db1_ProviderName")); } + public const string EnvironmentVariable = "Microsoft__Extensions__Configuration__EnvironmentVariables__Test__Foo"; + public class SettingsWithFoo + { + public string? Foo { get; set; } + } + + [Fact] + public void AddEnvironmentVariables_Bind_PrefixShouldNormalize() + { + try + { + Environment.SetEnvironmentVariable(EnvironmentVariable, "myFooValue"); + var configuration = new ConfigurationBuilder() + .AddEnvironmentVariables("Microsoft:Extensions:Configuration:EnvironmentVariables:Test:") + .Build(); + + var settingsWithFoo = new SettingsWithFoo(); + configuration.Bind(settingsWithFoo); + + Assert.Equal("myFooValue", settingsWithFoo.Foo); + } + finally + { + Environment.SetEnvironmentVariable(EnvironmentVariable, null); + } + } + + [Fact] + public void AddEnvironmentVariables_UsingDoubleUnderscores_Bind_PrefixWontNormalize() + { + try + { + Environment.SetEnvironmentVariable(EnvironmentVariable, "myFooValue"); + var configuration = new ConfigurationBuilder() + .AddEnvironmentVariables("Microsoft__Extensions__Configuration__EnvironmentVariables__Test__") + .Build(); + + var settingsWithFoo = new SettingsWithFoo(); + configuration.Bind(settingsWithFoo); + + Assert.Null(settingsWithFoo.Foo); + } + finally + { + Environment.SetEnvironmentVariable(EnvironmentVariable, null); + } + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void BindingDoesNotThrowIfReloadedDuringBinding() { diff --git a/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.sln b/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.sln index 648fd67ef942e7..e7d5ca9c205118 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.sln +++ b/src/libraries/Microsoft.Extensions.Configuration.Json/Microsoft.Extensions.Configuration.Json.sln @@ -49,8 +49,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{BD19B1E7-CAFF-4009-874A-760D5A466E28}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{160C3D6B-D90A-40B1-A695-81DB79EB24C4}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{A49023C8-173A-4B8F-84B3-2FF37FE8344A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{1F57E720-CBFF-4648-A507-EFCBCECB5FD3}" @@ -141,10 +139,6 @@ Global {BD19B1E7-CAFF-4009-874A-760D5A466E28}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD19B1E7-CAFF-4009-874A-760D5A466E28}.Release|Any CPU.ActiveCfg = Release|Any CPU {BD19B1E7-CAFF-4009-874A-760D5A466E28}.Release|Any CPU.Build.0 = Release|Any CPU - {160C3D6B-D90A-40B1-A695-81DB79EB24C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {160C3D6B-D90A-40B1-A695-81DB79EB24C4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {160C3D6B-D90A-40B1-A695-81DB79EB24C4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {160C3D6B-D90A-40B1-A695-81DB79EB24C4}.Release|Any CPU.Build.0 = Release|Any CPU {7517D0A0-5596-48B7-96EF-CB24DAD72675}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7517D0A0-5596-48B7-96EF-CB24DAD72675}.Debug|Any CPU.Build.0 = Debug|Any CPU {7517D0A0-5596-48B7-96EF-CB24DAD72675}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -201,7 +195,6 @@ Global {6A80D098-69EC-45FE-A064-4CBDFA44BA43} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} {B1723D4C-15E3-4A39-8976-C3E1740E5F00} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} {BD19B1E7-CAFF-4009-874A-760D5A466E28} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} - {160C3D6B-D90A-40B1-A695-81DB79EB24C4} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} {7517D0A0-5596-48B7-96EF-CB24DAD72675} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} {68210977-E10C-4BC3-B235-31B6E2AF9830} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} {FE50757B-7862-49D2-812E-1646F6FE0070} = {1789A282-9C08-40AB-9FD0-0FB1FAB99621} diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.sln b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.sln index e13f9f1bb81357..6e0e8ac58fc456 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.sln +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/Microsoft.Extensions.Configuration.UserSecrets.sln @@ -49,8 +49,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{1555B38A-E9CB-4734-AAB1-59CFB833A06D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{30EBBE93-80FC-442D-ADC6-D0BB0A8CFA76}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{82700778-D9AD-4B9D-8A1C-CDC1A19E4D54}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2434A707-1012-4104-81A0-1A1B25D9FEEA}" @@ -161,10 +159,6 @@ Global {1555B38A-E9CB-4734-AAB1-59CFB833A06D}.Debug|Any CPU.Build.0 = Debug|Any CPU {1555B38A-E9CB-4734-AAB1-59CFB833A06D}.Release|Any CPU.ActiveCfg = Release|Any CPU {1555B38A-E9CB-4734-AAB1-59CFB833A06D}.Release|Any CPU.Build.0 = Release|Any CPU - {30EBBE93-80FC-442D-ADC6-D0BB0A8CFA76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {30EBBE93-80FC-442D-ADC6-D0BB0A8CFA76}.Debug|Any CPU.Build.0 = Debug|Any CPU - {30EBBE93-80FC-442D-ADC6-D0BB0A8CFA76}.Release|Any CPU.ActiveCfg = Release|Any CPU - {30EBBE93-80FC-442D-ADC6-D0BB0A8CFA76}.Release|Any CPU.Build.0 = Release|Any CPU {96003091-9E9D-42D5-85A6-C2DFBD9DD847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {96003091-9E9D-42D5-85A6-C2DFBD9DD847}.Debug|Any CPU.Build.0 = Debug|Any CPU {96003091-9E9D-42D5-85A6-C2DFBD9DD847}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -203,7 +197,6 @@ Global {82700778-D9AD-4B9D-8A1C-CDC1A19E4D54} = {B5EF5DDD-EB92-414C-B9D2-826BA6CECCBF} {1EF04395-4D84-43F1-BD99-7F6D6C3D70BB} = {B5EF5DDD-EB92-414C-B9D2-826BA6CECCBF} {1555B38A-E9CB-4734-AAB1-59CFB833A06D} = {B5EF5DDD-EB92-414C-B9D2-826BA6CECCBF} - {30EBBE93-80FC-442D-ADC6-D0BB0A8CFA76} = {B5EF5DDD-EB92-414C-B9D2-826BA6CECCBF} {54B89407-FCD9-4B1A-8F83-04585D437443} = {B5EF5DDD-EB92-414C-B9D2-826BA6CECCBF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj index d488eecf483e74..a029a8c863902f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/Microsoft.Extensions.Configuration.UserSecrets.csproj @@ -4,6 +4,7 @@ netstandard2.0;net461 true User secrets configuration provider implementation for Microsoft.Extensions.Configuration. + 1 @@ -14,8 +15,8 @@ - - + + diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs index 86139faf9b021d..963ac77a30eea6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/UserSecretsConfigurationExtensions.cs @@ -29,7 +29,7 @@ public static class UserSecretsConfigurationExtensions /// The configuration builder. public static IConfigurationBuilder AddUserSecrets(this IConfigurationBuilder configuration) where T : class - => configuration.AddUserSecrets(typeof(T).Assembly, optional: false, reloadOnChange: false); + => configuration.AddUserSecrets(typeof(T).Assembly, optional: true, reloadOnChange: false); /// /// @@ -82,7 +82,7 @@ public static IConfigurationBuilder AddUserSecrets(this IConfigurationBuilder /// Thrown when does not have a valid /// The configuration builder. public static IConfigurationBuilder AddUserSecrets(this IConfigurationBuilder configuration, Assembly assembly) - => configuration.AddUserSecrets(assembly, optional: false, reloadOnChange: false); + => configuration.AddUserSecrets(assembly, optional: true, reloadOnChange: false); /// /// diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props rename to src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets rename to src/libraries/Microsoft.Extensions.Configuration.UserSecrets/src/buildTransitive/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets diff --git a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/ConfigurationExtensionTest.cs b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/ConfigurationExtensionTest.cs index 03667ab17b33c5..53dde10c61df4a 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/ConfigurationExtensionTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.UserSecrets/tests/ConfigurationExtensionTest.cs @@ -85,23 +85,23 @@ public void AddUserSecrets_FindsAssemblyAttributeFromType() public void AddUserSecrets_ThrowsIfAssemblyAttributeFromType() { var ex = Assert.Throws(() => - new ConfigurationBuilder().AddUserSecrets()); + new ConfigurationBuilder().AddUserSecrets(optional: false)); Assert.Equal(SR.Format(SR.Error_Missing_UserSecretsIdAttribute, typeof(string).Assembly.GetName().Name), ex.Message); ex = Assert.Throws(() => - new ConfigurationBuilder().AddUserSecrets(typeof(JObject).Assembly)); + new ConfigurationBuilder().AddUserSecrets(typeof(JObject).Assembly, optional: false)); Assert.Equal(SR.Format(SR.Error_Missing_UserSecretsIdAttribute, typeof(JObject).Assembly.GetName().Name), ex.Message); } [Fact] - public void AddUserSecrets_DoesNotThrowsIfOptional() + public void AddUserSecrets_DoesNotThrowsIfOptionalByDefault() { var config = new ConfigurationBuilder() - .AddUserSecrets(optional: true) - .AddUserSecrets(typeof(List<>).Assembly, optional: true) + .AddUserSecrets() + .AddUserSecrets(typeof(List<>).Assembly) .Build(); Assert.Empty(config.AsEnumerable()); diff --git a/src/libraries/Microsoft.Extensions.Configuration.Xml/src/Microsoft.Extensions.Configuration.Xml.csproj b/src/libraries/Microsoft.Extensions.Configuration.Xml/src/Microsoft.Extensions.Configuration.Xml.csproj index c9c66f5c8c67f2..9a06f8e7ad52b3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Xml/src/Microsoft.Extensions.Configuration.Xml.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Xml/src/Microsoft.Extensions.Configuration.Xml.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net461 + netstandard2.0;net461-windows true XML configuration provider implementation for Microsoft.Extensions.Configuration. diff --git a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj index 85e8e1de25876a..35ceadc08eed45 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Xml/tests/Microsoft.Extensions.Configuration.Xml.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);net461 + $(NetCoreAppCurrent);net461-windows true diff --git a/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.sln b/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.sln index a2ec3b0599f575..57cf3b372163b0 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.sln +++ b/src/libraries/Microsoft.Extensions.Configuration/Microsoft.Extensions.Configuration.sln @@ -95,8 +95,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Security.Permissions EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{23F4102D-67BD-4865-BB19-195C47945733}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{634542E9-CF9A-4BD2-BC36-71D12BEF2B36}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{41234DB5-1F3A-4E4A-8BD9-4A277C249666}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Windows.Extensions", "..\System.Windows.Extensions\ref\System.Windows.Extensions.csproj", "{6CDFD705-28EC-4D58-A2F9-715A3B06661B}" @@ -251,10 +249,6 @@ Global {23F4102D-67BD-4865-BB19-195C47945733}.Debug|Any CPU.Build.0 = Debug|Any CPU {23F4102D-67BD-4865-BB19-195C47945733}.Release|Any CPU.ActiveCfg = Release|Any CPU {23F4102D-67BD-4865-BB19-195C47945733}.Release|Any CPU.Build.0 = Release|Any CPU - {634542E9-CF9A-4BD2-BC36-71D12BEF2B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {634542E9-CF9A-4BD2-BC36-71D12BEF2B36}.Debug|Any CPU.Build.0 = Debug|Any CPU - {634542E9-CF9A-4BD2-BC36-71D12BEF2B36}.Release|Any CPU.ActiveCfg = Release|Any CPU - {634542E9-CF9A-4BD2-BC36-71D12BEF2B36}.Release|Any CPU.Build.0 = Release|Any CPU {CDC60461-56B7-4941-AD08-90228BD450CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CDC60461-56B7-4941-AD08-90228BD450CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {CDC60461-56B7-4941-AD08-90228BD450CE}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -303,7 +297,7 @@ Global {7CFEB13D-63D5-42A7-868C-CE1D0049EAF0}.Debug|Any CPU.Build.0 = Debug|Any CPU {7CFEB13D-63D5-42A7-868C-CE1D0049EAF0}.Release|Any CPU.ActiveCfg = Release|Any CPU {7CFEB13D-63D5-42A7-868C-CE1D0049EAF0}.Release|Any CPU.Build.0 = Release|Any CPU - {6CDFD705-28EC-4D58-A2F9-715A3B06661B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CDFD705-28EC-4D58-A2F9-715A3B06661B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6CDFD705-28EC-4D58-A2F9-715A3B06661B}.Debug|Any CPU.Build.0 = Debug|Any CPU {6CDFD705-28EC-4D58-A2F9-715A3B06661B}.Release|Any CPU.ActiveCfg = Release|Any CPU {6CDFD705-28EC-4D58-A2F9-715A3B06661B}.Release|Any CPU.Build.0 = Release|Any CPU @@ -370,7 +364,6 @@ Global {BAA953EF-6529-4F2C-8F89-C76A05258677} = {76107BEB-02C0-4A83-9631-B226340752A7} {42C10152-F747-443F-9AC1-5738CB62EA6C} = {76107BEB-02C0-4A83-9631-B226340752A7} {23F4102D-67BD-4865-BB19-195C47945733} = {76107BEB-02C0-4A83-9631-B226340752A7} - {634542E9-CF9A-4BD2-BC36-71D12BEF2B36} = {76107BEB-02C0-4A83-9631-B226340752A7} {CDC60461-56B7-4941-AD08-90228BD450CE} = {76107BEB-02C0-4A83-9631-B226340752A7} {6CCBE9AB-E620-4616-9B80-1F9D3E722B87} = {76107BEB-02C0-4A83-9631-B226340752A7} {8F65DFBB-9196-4E69-879A-C99C641B3E49} = {76107BEB-02C0-4A83-9631-B226340752A7} diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs index 9578f3c334ac3f..84cceb06218d74 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationManager.cs @@ -12,15 +12,20 @@ namespace Microsoft.Extensions.Configuration { /// /// Configuration is mutable configuration object. It is both an and an . - /// As sources are added, it updates its current view of configuration. Once Build is called, configuration is frozen. + /// As sources are added, it updates its current view of configuration. /// public sealed class ConfigurationManager : IConfigurationBuilder, IConfigurationRoot, IDisposable { + // Concurrently modifying config sources or properties is not thread-safe. However, it is thread-safe to read config while modifying sources or properties. private readonly ConfigurationSources _sources; private readonly ConfigurationBuilderProperties _properties; - private readonly object _providerLock = new(); - private readonly List _providers = new(); + // ReferenceCountedProviderManager manages copy-on-write references to support concurrently reading config while modifying sources. + // It waits for readers to unreference the providers before disposing them without blocking on any concurrent operations. + private readonly ReferenceCountedProviderManager _providerManager = new(); + + // _changeTokenRegistrations is only modified when config sources are modified. It is not referenced by any read operations. + // Because modify config sources is not thread-safe, modifying _changeTokenRegistrations does not need to be thread-safe either. private readonly List _changeTokenRegistrations = new(); private ConfigurationReloadToken _changeToken = new(); @@ -43,17 +48,13 @@ public string this[string key] { get { - lock (_providerLock) - { - return ConfigurationRoot.GetConfiguration(_providers, key); - } + using ReferenceCountedProviders reference = _providerManager.GetReference(); + return ConfigurationRoot.GetConfiguration(reference.Providers, key); } set { - lock (_providerLock) - { - ConfigurationRoot.SetConfiguration(_providers, key, value); - } + using ReferenceCountedProviders reference = _providerManager.GetReference(); + ConfigurationRoot.SetConfiguration(reference.Providers, key, value); } } @@ -61,37 +62,22 @@ public string this[string key] public IConfigurationSection GetSection(string key) => new ConfigurationSection(this, key); /// - public IEnumerable GetChildren() - { - lock (_providerLock) - { - // ToList() to eagerly evaluate inside lock. - return this.GetChildrenImplementation(null).ToList(); - } - } + public IEnumerable GetChildren() => this.GetChildrenImplementation(null); IDictionary IConfigurationBuilder.Properties => _properties; IList IConfigurationBuilder.Sources => _sources; - IEnumerable IConfigurationRoot.Providers - { - get - { - lock (_providerLock) - { - return new List(_providers); - } - } - } + // We cannot track the duration of the reference to the providers if this property is used. + // If a configuration source is removed after this is accessed but before it's completely enumerated, + // this may allow access to a disposed provider. + IEnumerable IConfigurationRoot.Providers => _providerManager.NonReferenceCountedProviders; /// public void Dispose() { - lock (_providerLock) - { - DisposeRegistrationsAndProvidersUnsynchronized(); - } + DisposeRegistrations(); + _providerManager.Dispose(); } IConfigurationBuilder IConfigurationBuilder.Add(IConfigurationSource source) @@ -106,9 +92,9 @@ IConfigurationBuilder IConfigurationBuilder.Add(IConfigurationSource source) void IConfigurationRoot.Reload() { - lock (_providerLock) + using (ReferenceCountedProviders reference = _providerManager.GetReference()) { - foreach (var provider in _providers) + foreach (IConfigurationProvider provider in reference.Providers) { provider.Load(); } @@ -117,6 +103,8 @@ void IConfigurationRoot.Reload() RaiseChanged(); } + internal ReferenceCountedProviders GetProvidersReference() => _providerManager.GetReference(); + private void RaiseChanged() { var previousToken = Interlocked.Exchange(ref _changeToken, new ConfigurationReloadToken()); @@ -126,59 +114,49 @@ private void RaiseChanged() // Don't rebuild and reload all providers in the common case when a source is simply added to the IList. private void AddSource(IConfigurationSource source) { - lock (_providerLock) - { - var provider = source.Build(this); - _providers.Add(provider); + IConfigurationProvider provider = source.Build(this); - provider.Load(); - _changeTokenRegistrations.Add(ChangeToken.OnChange(() => provider.GetReloadToken(), () => RaiseChanged())); - } + provider.Load(); + _changeTokenRegistrations.Add(ChangeToken.OnChange(() => provider.GetReloadToken(), () => RaiseChanged())); + _providerManager.AddProvider(provider); RaiseChanged(); } // Something other than Add was called on IConfigurationBuilder.Sources or IConfigurationBuilder.Properties has changed. private void ReloadSources() { - lock (_providerLock) - { - DisposeRegistrationsAndProvidersUnsynchronized(); + DisposeRegistrations(); - _changeTokenRegistrations.Clear(); - _providers.Clear(); + _changeTokenRegistrations.Clear(); - foreach (var source in _sources) - { - _providers.Add(source.Build(this)); - } + var newProvidersList = new List(); - foreach (var p in _providers) - { - p.Load(); - _changeTokenRegistrations.Add(ChangeToken.OnChange(() => p.GetReloadToken(), () => RaiseChanged())); - } + foreach (IConfigurationSource source in _sources) + { + newProvidersList.Add(source.Build(this)); + } + + foreach (IConfigurationProvider p in newProvidersList) + { + p.Load(); + _changeTokenRegistrations.Add(ChangeToken.OnChange(() => p.GetReloadToken(), () => RaiseChanged())); } + _providerManager.ReplaceProviders(newProvidersList); RaiseChanged(); } - private void DisposeRegistrationsAndProvidersUnsynchronized() + private void DisposeRegistrations() { // dispose change token registrations - foreach (var registration in _changeTokenRegistrations) + foreach (IDisposable registration in _changeTokenRegistrations) { registration.Dispose(); } - - // dispose providers - foreach (var provider in _providers) - { - (provider as IDisposable)?.Dispose(); - } } - private class ConfigurationSources : IList + private sealed class ConfigurationSources : IList { private readonly List _sources = new(); private readonly ConfigurationManager _config; @@ -259,7 +237,7 @@ IEnumerator IEnumerable.GetEnumerator() } } - private class ConfigurationBuilderProperties : IDictionary + private sealed class ConfigurationBuilderProperties : IDictionary { private readonly Dictionary _properties = new(); private readonly ConfigurationManager _config; diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs b/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs index bff5c527104008..de86a8473d9812 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/InternalConfigurationRootExtensions.cs @@ -20,11 +20,24 @@ internal static class InternalConfigurationRootExtensions /// Immediate children sub-sections of section specified by key. internal static IEnumerable GetChildrenImplementation(this IConfigurationRoot root, string path) { - return root.Providers + using ReferenceCountedProviders? reference = (root as ConfigurationManager)?.GetProvidersReference(); + IEnumerable providers = reference?.Providers ?? root.Providers; + + IEnumerable children = providers .Aggregate(Enumerable.Empty(), (seed, source) => source.GetChildKeys(seed, path)) .Distinct(StringComparer.OrdinalIgnoreCase) .Select(key => root.GetSection(path == null ? key : ConfigurationPath.Combine(path, key))); + + if (reference is null) + { + return children; + } + else + { + // Eagerly evaluate the IEnumerable before releasing the reference so we don't allow iteration over disposed providers. + return children.ToList(); + } } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj b/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj index 62243f8db8537a..89d1b42bcfaa91 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration/src/Microsoft.Extensions.Configuration.csproj @@ -4,6 +4,8 @@ netstandard2.0;net461 true Implementation of key-value pair based configuration for Microsoft.Extensions.Configuration. Includes the memory configuration provider. + 1 + true diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ReferenceCountedProviders.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ReferenceCountedProviders.cs new file mode 100644 index 00000000000000..2c2e32fc7e47d0 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ReferenceCountedProviders.cs @@ -0,0 +1,93 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.Threading; + +namespace Microsoft.Extensions.Configuration +{ + // ReferenceCountedProviders is used by ConfigurationManager to wait until all readers unreference it before disposing any providers. + internal abstract class ReferenceCountedProviders : IDisposable + { + public static ReferenceCountedProviders Create(List providers) => new ActiveReferenceCountedProviders(providers); + + // If anything references DisposedReferenceCountedProviders, it indicates something is using the ConfigurationManager after it's been disposed. + // We could preemptively throw an ODE from ReferenceCountedProviderManager.GetReference() instead of returning this type, but this might + // break existing apps that are previously able to continue to read configuration after disposing an ConfigurationManager. + public static ReferenceCountedProviders CreateDisposed(List providers) => new DisposedReferenceCountedProviders(providers); + + public abstract List Providers { get; set; } + + // NonReferenceCountedProviders is only used to: + // 1. Support IConfigurationRoot.Providers because we cannot track the lifetime of that reference. + // 2. Construct DisposedReferenceCountedProviders because the providers are disposed anyway and no longer reference counted. + public abstract List NonReferenceCountedProviders { get; } + + public abstract void AddReference(); + // This is Dispose() rather than RemoveReference() so we can conveniently release a reference at the end of a using block. + public abstract void Dispose(); + + private sealed class ActiveReferenceCountedProviders : ReferenceCountedProviders + { + private long _refCount = 1; + // volatile is not strictly necessary because the runtime adds a barrier either way, but volatile indicates that this field has + // unsynchronized readers meaning the all writes initializing the list must be published before updating the _providers reference. + private volatile List _providers; + + public ActiveReferenceCountedProviders(List providers) + { + _providers = providers; + } + + public override List Providers + { + get + { + Debug.Assert(_refCount > 0); + return _providers; + } + set + { + Debug.Assert(_refCount > 0); + _providers = value; + } + } + + public override List NonReferenceCountedProviders => _providers; + + public override void AddReference() + { + // AddReference() is always called with a lock to ensure _refCount hasn't already decremented to zero. + Debug.Assert(_refCount > 0); + Interlocked.Increment(ref _refCount); + } + + public override void Dispose() + { + if (Interlocked.Decrement(ref _refCount) == 0) + { + foreach (IConfigurationProvider provider in _providers) + { + (provider as IDisposable)?.Dispose(); + } + } + } + } + + private sealed class DisposedReferenceCountedProviders : ReferenceCountedProviders + { + public DisposedReferenceCountedProviders(List providers) + { + Providers = providers; + } + + public override List Providers { get; set; } + public override List NonReferenceCountedProviders => Providers; + + public override void AddReference() { } + public override void Dispose() { } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ReferenceCountedProvidersManager.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ReferenceCountedProvidersManager.cs new file mode 100644 index 00000000000000..210e41f665a47a --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ReferenceCountedProvidersManager.cs @@ -0,0 +1,93 @@ +// 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.Collections.Generic; + +namespace Microsoft.Extensions.Configuration +{ + // ReferenceCountedProviderManager is used by ConfigurationManager to provide copy-on-write references that support concurrently + // reading config while modifying sources. It waits for readers to unreference the providers before disposing them + // without blocking on any concurrent operations. + internal sealed class ReferenceCountedProviderManager : IDisposable + { + private readonly object _replaceProvidersLock = new object(); + private ReferenceCountedProviders _refCountedProviders = ReferenceCountedProviders.Create(new List()); + private bool _disposed; + + // This is only used to support IConfigurationRoot.Providers because we cannot track the lifetime of that reference. + public IEnumerable NonReferenceCountedProviders => _refCountedProviders.NonReferenceCountedProviders; + + public ReferenceCountedProviders GetReference() + { + // Lock to ensure oldRefCountedProviders.Dispose() in ReplaceProviders() or Dispose() doesn't decrement ref count to zero + // before calling _refCountedProviders.AddReference(). + lock (_replaceProvidersLock) + { + if (_disposed) + { + // Return a non-reference-counting ReferenceCountedProviders instance now that the ConfigurationManager is disposed. + // We could preemptively throw an ODE instead, but this might break existing apps that were previously able to + // continue to read configuration after disposing an ConfigurationManager. + return ReferenceCountedProviders.CreateDisposed(_refCountedProviders.NonReferenceCountedProviders); + } + + _refCountedProviders.AddReference(); + return _refCountedProviders; + } + } + + // Providers should never be concurrently modified. Reading during modification is allowed. + public void ReplaceProviders(List providers) + { + ReferenceCountedProviders oldRefCountedProviders = _refCountedProviders; + + lock (_replaceProvidersLock) + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(ConfigurationManager)); + } + + _refCountedProviders = ReferenceCountedProviders.Create(providers); + } + + // Decrement the reference count to the old providers. If they are being concurrently read from + // the actual disposal of the old providers will be delayed until the final reference is released. + // Never dispose ReferenceCountedProviders with a lock because this may call into user code. + oldRefCountedProviders.Dispose(); + } + + public void AddProvider(IConfigurationProvider provider) + { + lock (_replaceProvidersLock) + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(ConfigurationManager)); + } + + // Maintain existing references, but replace list with copy containing new item. + _refCountedProviders.Providers = new List(_refCountedProviders.Providers) + { + provider + }; + } + } + + public void Dispose() + { + ReferenceCountedProviders oldRefCountedProviders = _refCountedProviders; + + // This lock ensures that we cannot reduce the ref count to zero before GetReference() calls AddReference(). + // Once _disposed is set, GetReference() stops reference counting. + lock (_replaceProvidersLock) + { + _disposed = true; + } + + // Never dispose ReferenceCountedProviders with a lock because this may call into user code. + oldRefCountedProviders.Dispose(); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/ConfigurationManagerTest.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/ConfigurationManagerTest.cs index 89da7883517544..aa36cceb424e5d 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/ConfigurationManagerTest.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/ConfigurationManagerTest.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Microsoft.Extensions.Configuration.Memory; using Microsoft.Extensions.Primitives; using Moq; @@ -171,6 +173,91 @@ public void DisposesProvidersOnRemoval() Assert.True(provider5.IsDisposed); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public async Task ProviderCanBlockLoadWaitingOnConcurrentRead() + { + using var mre = new ManualResetEventSlim(false); + var provider = new BlockLoadOnMREProvider(mre, timeout: TimeSpan.FromSeconds(30)); + + var config = new ConfigurationManager(); + IConfigurationBuilder builder = config; + + // builder.Add(source) will block on provider.Load(). + var loadTask = Task.Run(() => builder.Add(new TestConfigurationSource(provider))); + await provider.LoadStartedTask; + + // Read configuration while provider.Load() is blocked waiting on us. + _ = config["key"]; + + // Unblock provider.Load() + mre.Set(); + + // This will throw if provider.Load() timed out instead of unblocking gracefully after the read. + await loadTask; + } + + public static TheoryData ConcurrentReadActions + { + get + { + return new TheoryData> + { + config => _ = config["key"], + config => config.GetChildren(), + config => config.GetSection("key").GetChildren(), + }; + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [MemberData(nameof(ConcurrentReadActions))] + public async Task ProviderDisposeDelayedWaitingOnConcurrentRead(Action concurrentReadAction) + { + using var mre = new ManualResetEventSlim(false); + var provider = new BlockReadOnMREProvider(mre, timeout: TimeSpan.FromSeconds(30)); + + var config = new ConfigurationManager(); + IConfigurationBuilder builder = config; + + builder.Add(new TestConfigurationSource(provider)); + + // Reading configuration will block on provider.TryRead() or profvider.GetChildKeys(). + var readTask = Task.Run(() => concurrentReadAction(config)); + await provider.ReadStartedTask; + + // Removing the source normally disposes the provider except when there provider is in use as is the case here. + builder.Sources.Clear(); + + Assert.False(provider.IsDisposed); + + // Unblock TryRead() or GetChildKeys() + mre.Set(); + + // This will throw if TryRead() or GetChildKeys() timed out instead of unblocking gracefully after setting the MRE. + await readTask; + + // The provider should be disposed when the concurrentReadAction releases the last reference to the provider. + Assert.True(provider.IsDisposed); + } + + [Fact] + public void DisposingConfigurationManagerCausesOnlySourceChangesToThrow() + { + var config = new ConfigurationManager + { + ["TestKey"] = "TestValue", + }; + + config.Dispose(); + + Assert.Equal("TestValue", config["TestKey"]); + config["TestKey"] = "TestValue2"; + Assert.Equal("TestValue2", config["TestKey"]); + + Assert.Throws(() => config.AddInMemoryCollection()); + Assert.Throws(() => ((IConfigurationBuilder)config).Sources.Clear()); + } + [Fact] public void DisposesChangeTokenRegistrationsOnDispose() { @@ -1128,6 +1215,62 @@ public TestConfigurationProvider(string key, string value) => Data.Add(key, value); } + private class BlockLoadOnMREProvider : ConfigurationProvider + { + private readonly ManualResetEventSlim _mre; + private readonly TimeSpan _timeout; + + private readonly TaskCompletionSource _loadStartedTcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + + public BlockLoadOnMREProvider(ManualResetEventSlim mre, TimeSpan timeout) + { + _mre = mre; + _timeout = timeout; + } + + public Task LoadStartedTask => _loadStartedTcs.Task; + + public override void Load() + { + _loadStartedTcs.SetResult(null); + Assert.True(_mre.Wait(_timeout), "BlockLoadOnMREProvider.Load() timed out."); + } + } + + private class BlockReadOnMREProvider : ConfigurationProvider, IDisposable + { + private readonly ManualResetEventSlim _mre; + private readonly TimeSpan _timeout; + + private readonly TaskCompletionSource _readStartedTcs = new(TaskCreationOptions.RunContinuationsAsynchronously); + + public BlockReadOnMREProvider(ManualResetEventSlim mre, TimeSpan timeout) + { + _mre = mre; + _timeout = timeout; + } + + public Task ReadStartedTask => _readStartedTcs.Task; + + public bool IsDisposed { get; set; } + + public override bool TryGet(string key, out string? value) + { + _readStartedTcs.SetResult(null); + Assert.True(_mre.Wait(_timeout), "BlockReadOnMREProvider.TryGet() timed out."); + return base.TryGet(key, out value); + } + + public override IEnumerable GetChildKeys(IEnumerable earlierKeys, string? parentPath) + { + _readStartedTcs.SetResult(null); + Assert.True(_mre.Wait(_timeout), "BlockReadOnMREProvider.GetChildKeys() timed out."); + return base.GetChildKeys(earlierKeys, parentPath); + } + + public void Dispose() => IsDisposed = true; + } + private class DisposableTestConfigurationProvider : ConfigurationProvider, IDisposable { public bool IsDisposed { get; set; } diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs index 50ffa927af1177..fc26cf88b653a2 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/ConfigurationTests.cs @@ -903,7 +903,7 @@ public void GetDefaultBasePathForSources() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void CanEnumerateProviders() { var config = CreateBuilder() diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj index e28690dc03d718..e2ca66c3ff7cce 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/FunctionalTests/Microsoft.Extensions.Configuration.Functional.Tests.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);net461 + $(NetCoreAppCurrent);net461-windows true diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj index 4c1f40cce828db..915591133734e3 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs index 338325edb830f6..03b245224d8bb6 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/DependencyInjectionEventSource.cs @@ -79,9 +79,9 @@ public void ServiceRealizationFailed(string? exceptionMessage, int serviceProvid [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Parameters to this method are primitive and are trimmer safe.")] [Event(7, Level = EventLevel.Informational, Keywords = Keywords.ServiceProviderInitialized)] - private void ServiceProviderBuilt(int serviceProviderHashCode, int singletonServices, int scopedServices, int transientServices) + private void ServiceProviderBuilt(int serviceProviderHashCode, int singletonServices, int scopedServices, int transientServices, int closedGenericsServices, int openGenericsServices) { - WriteEvent(7, serviceProviderHashCode, singletonServices, scopedServices, transientServices); + WriteEvent(7, serviceProviderHashCode, singletonServices, scopedServices, transientServices, closedGenericsServices, openGenericsServices); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", @@ -174,6 +174,8 @@ private void WriteServiceProviderBuilt(ServiceProvider provider) int singletonServices = 0; int scopedServices = 0; int transientServices = 0; + int closedGenericsServices = 0; + int openGenericsServices = 0; StringBuilder descriptorBuilder = new StringBuilder("{ \"descriptors\":[ "); bool firstDescriptor = true; @@ -202,11 +204,23 @@ private void WriteServiceProviderBuilt(ServiceProvider provider) transientServices++; break; } + + if (descriptor.ServiceType.IsGenericType) + { + if (descriptor.ServiceType.IsConstructedGenericType) + { + closedGenericsServices++; + } + else + { + openGenericsServices++; + } + } } descriptorBuilder.Append(" ] }"); int providerHashCode = provider.GetHashCode(); - ServiceProviderBuilt(providerHashCode, singletonServices, scopedServices, transientServices); + ServiceProviderBuilt(providerHashCode, singletonServices, scopedServices, transientServices, closedGenericsServices, openGenericsServices); string descriptorString = descriptorBuilder.ToString(); int chunkCount = descriptorString.Length / MaxChunkSize + (descriptorString.Length % MaxChunkSize > 0 ? 1 : 0); diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/DependencyInjectionEventSourceTests.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/DependencyInjectionEventSourceTests.cs index 11d8ae91570ecc..deaaba56b47fd2 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/DependencyInjectionEventSourceTests.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/tests/DI.Tests/DependencyInjectionEventSourceTests.cs @@ -241,14 +241,18 @@ public void EmitsServiceProviderBuilt() serviceCollection.AddScoped(); serviceCollection.AddTransient(); serviceCollection.AddSingleton(); + serviceCollection.AddScoped(typeof(IFakeOpenGenericService<>), typeof(FakeOpenGenericService<>)); + serviceCollection.AddTransient, FakeOpenGenericService>(); using ServiceProvider provider = serviceCollection.BuildServiceProvider(); EventWrittenEventArgs serviceProviderBuiltEvent = _listener.EventData.Single(e => e.EventName == "ServiceProviderBuilt"); GetProperty(serviceProviderBuiltEvent, "serviceProviderHashCode"); // assert hashcode exists as an int Assert.Equal(4, GetProperty(serviceProviderBuiltEvent, "singletonServices")); - Assert.Equal(1, GetProperty(serviceProviderBuiltEvent, "scopedServices")); - Assert.Equal(2, GetProperty(serviceProviderBuiltEvent, "transientServices")); + Assert.Equal(2, GetProperty(serviceProviderBuiltEvent, "scopedServices")); + Assert.Equal(3, GetProperty(serviceProviderBuiltEvent, "transientServices")); + Assert.Equal(1, GetProperty(serviceProviderBuiltEvent, "closedGenericsServices")); + Assert.Equal(1, GetProperty(serviceProviderBuiltEvent, "openGenericsServices")); Assert.Equal(7, serviceProviderBuiltEvent.EventId); EventWrittenEventArgs serviceProviderDescriptorsEvent = _listener.EventData.Single(e => e.EventName == "ServiceProviderDescriptors"); @@ -290,6 +294,16 @@ public void EmitsServiceProviderBuilt() " \"serviceType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeService\",", " \"lifetime\": \"Singleton\",", " \"implementationType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.FakeDisposableCallbackInnerService\"", + " },", + " {", + " \"serviceType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1[TValue]\",", + " \"lifetime\": \"Scoped\",", + " \"implementationType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.FakeOpenGenericService`1[TVal]\"", + " },", + " {", + " \"serviceType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.IFakeOpenGenericService`1[Microsoft.Extensions.DependencyInjection.Specification.Fakes.PocoClass]\",", + " \"lifetime\": \"Transient\",", + " \"implementationType\": \"Microsoft.Extensions.DependencyInjection.Specification.Fakes.FakeOpenGenericService`1[Microsoft.Extensions.DependencyInjection.Specification.Fakes.PocoClass]\"", " }", " ]", "}"), diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.sln b/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.sln index 6510d1b3940139..b59269c9e27155 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.sln +++ b/src/libraries/Microsoft.Extensions.DependencyModel/Microsoft.Extensions.DependencyModel.sln @@ -19,8 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{7902A0CA-E94D-4C96-A112-455A1E5E2390}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{6699E51A-8DC5-4DBA-A06B-B4A04144E4FA}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{FA7201FE-097D-4197-BDEC-329986814D8D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{50BA55F5-BD05-4C05-910F-2BFD20BD3465}" @@ -67,10 +65,6 @@ Global {4A28B457-D950-486B-B59B-A4C977A733B1}.Debug|Any CPU.Build.0 = Debug|Any CPU {4A28B457-D950-486B-B59B-A4C977A733B1}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A28B457-D950-486B-B59B-A4C977A733B1}.Release|Any CPU.Build.0 = Release|Any CPU - {6699E51A-8DC5-4DBA-A06B-B4A04144E4FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6699E51A-8DC5-4DBA-A06B-B4A04144E4FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6699E51A-8DC5-4DBA-A06B-B4A04144E4FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6699E51A-8DC5-4DBA-A06B-B4A04144E4FA}.Release|Any CPU.Build.0 = Release|Any CPU {F38E2965-8DBB-4795-89AF-C0109EB23574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F38E2965-8DBB-4795-89AF-C0109EB23574}.Debug|Any CPU.Build.0 = Debug|Any CPU {F38E2965-8DBB-4795-89AF-C0109EB23574}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -98,7 +92,6 @@ Global {FA7201FE-097D-4197-BDEC-329986814D8D} = {5725D7DF-DC33-47D2-90C9-D8736C579E77} {7902A0CA-E94D-4C96-A112-455A1E5E2390} = {5725D7DF-DC33-47D2-90C9-D8736C579E77} {4A28B457-D950-486B-B59B-A4C977A733B1} = {5725D7DF-DC33-47D2-90C9-D8736C579E77} - {6699E51A-8DC5-4DBA-A06B-B4A04144E4FA} = {5725D7DF-DC33-47D2-90C9-D8736C579E77} {2AED2951-7724-4EFC-8E16-6DF877C6B4A6} = {5725D7DF-DC33-47D2-90C9-D8736C579E77} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs index de58daa3906d4e..63855745dbffe6 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFileProvider.cs @@ -162,8 +162,8 @@ internal PhysicalFilesWatcher CreateFileWatcher() FileSystemWatcher watcher; #if NETCOREAPP - // For browser we will proactively fallback to polling since FileSystemWatcher is not supported. - if (OperatingSystem.IsBrowser()) + // For browser/iOS/tvOS we will proactively fallback to polling since FileSystemWatcher is not supported. + if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { UsePollingFileWatcher = true; UseActivePolling = true; diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs index 81df7c51532bf3..21d1ed8deedc11 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/src/PhysicalFilesWatcher.cs @@ -90,7 +90,7 @@ public PhysicalFilesWatcher( if (fileSystemWatcher != null) { #if NETCOREAPP - if (OperatingSystem.IsBrowser()) + if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { throw new PlatformNotSupportedException(SR.Format(SR.FileSystemWatcher_PlatformNotSupported, typeof(FileSystemWatcher))); } @@ -148,7 +148,7 @@ public IChangeToken CreateFileChangeToken(string filter) } IChangeToken changeToken = GetOrAddChangeToken(filter); -// We made sure that browser never uses FileSystemWatcher. +// We made sure that browser/iOS/tvOS never uses FileSystemWatcher. #pragma warning disable CA1416 // Validate platform compatibility TryEnableFileSystemWatcher(); #pragma warning restore CA1416 // Validate platform compatibility @@ -276,6 +276,9 @@ protected virtual void Dispose(bool disposing) } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void OnRenamed(object sender, RenamedEventArgs e) { // For a file name change or a directory's name change notify registered tokens. @@ -309,12 +312,18 @@ ex is DirectoryNotFoundException || } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void OnChanged(object sender, FileSystemEventArgs e) { OnFileSystemEntryChange(e.FullPath); } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void OnError(object sender, ErrorEventArgs e) { // Notify all cache entries on error. @@ -325,6 +334,9 @@ private void OnError(object sender, ErrorEventArgs e) } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void OnFileSystemEntryChange(string fullPath) { try @@ -348,6 +360,9 @@ ex is SecurityException || } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void ReportChangeForMatchedEntries(string path) { if (string.IsNullOrEmpty(path)) @@ -385,6 +400,9 @@ private void ReportChangeForMatchedEntries(string path) } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void TryDisableFileSystemWatcher() { if (_fileWatcher != null) @@ -403,6 +421,9 @@ private void TryDisableFileSystemWatcher() } [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] private void TryEnableFileSystemWatcher() { if (_fileWatcher != null) diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs index e1480ab8686b4d..4aa57114fcdc69 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFileProviderTests.cs @@ -137,7 +137,7 @@ public void PollingFileProviderShouldntConsumeINotifyInstances() } } } - + private void GetFileInfoReturnsNotFoundFileInfoForIllegalPathWithLeadingSlashes(string path) { using (var provider = new PhysicalFileProvider(Path.GetTempPath())) @@ -325,7 +325,7 @@ public void GetFileInfoReturnsFileInfoWhenExclusionDisabled() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "Browser always uses Active Polling which doesn't return the same instance between multiple calls to Watch(string)")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "Browser/iOS/tvOS always uses Active Polling which doesn't return the same instance between multiple calls to Watch(string)")] public void TokenIsSameForSamePath() { using (var root = new DisposableFileSystem()) @@ -349,7 +349,7 @@ public void TokenIsSameForSamePath() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokensFiredOnFileChange() { using (var root = new DisposableFileSystem()) @@ -380,7 +380,7 @@ public async Task TokensFiredOnFileChange() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenCallbackInvokedOnFileChange() { using (var root = new DisposableFileSystem()) @@ -417,7 +417,7 @@ public async Task TokenCallbackInvokedOnFileChange() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task WatcherWithPolling_ReturnsTrueForFileChangedWhenFileSystemWatcherDoesNotRaiseEvents() { using (var root = new DisposableFileSystem()) @@ -448,7 +448,7 @@ public async Task WatcherWithPolling_ReturnsTrueForFileChangedWhenFileSystemWatc [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task WatcherWithPolling_ReturnsTrueForFileRemovedWhenFileSystemWatcherDoesNotRaiseEvents() { using (var root = new DisposableFileSystem()) @@ -481,7 +481,7 @@ public async Task WatcherWithPolling_ReturnsTrueForFileRemovedWhenFileSystemWatc [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokensFiredOnFileDeleted() { using (var root = new DisposableFileSystem()) @@ -793,7 +793,7 @@ public void GetDirectoryContentsReturnsFilesWhenExclusionDisabled() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task FileChangeTokenNotNotifiedAfterExpiry() { using (var root = new DisposableFileSystem()) @@ -826,7 +826,7 @@ public async Task FileChangeTokenNotNotifiedAfterExpiry() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "Browser always uses Active Polling which doesn't return the same instance between multiple calls to Watch(string)")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "Browser/iOS/tvOS always uses Active Polling which doesn't return the same instance between multiple calls to Watch(string)")] public void TokenIsSameForSamePathCaseInsensitive() { using (var root = new DisposableFileSystem()) @@ -843,7 +843,7 @@ public void TokenIsSameForSamePathCaseInsensitive() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task CorrectTokensFiredForMultipleFiles() { using (var root = new DisposableFileSystem()) @@ -877,7 +877,7 @@ public async Task CorrectTokensFiredForMultipleFiles() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenNotAffectedByExceptions() { using (var root = new DisposableFileSystem()) @@ -936,6 +936,7 @@ public void NoopChangeTokenForFilterThatNavigatesAboveRoot() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/58584", TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS)] public void TokenForEmptyFilter() { using (var root = new DisposableFileSystem()) @@ -985,7 +986,7 @@ public void NoopChangeTokenForAbsolutePathFilters() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenFiredOnCreation() { using (var root = new DisposableFileSystem()) @@ -1011,7 +1012,7 @@ public async Task TokenFiredOnCreation() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenFiredOnDeletion() { using (var root = new DisposableFileSystem()) @@ -1037,7 +1038,7 @@ public async Task TokenFiredOnDeletion() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenFiredForFilesUnderPathEndingWithSlash() { using (var root = new DisposableFileSystem()) @@ -1092,7 +1093,7 @@ public async Task TokenFiredForRelativePathStartingWithSlash_Windows(string slas [InlineData("///")] // Testing Unix specific behaviour on leading slashes. [PlatformSpecific(TestPlatforms.AnyUnix)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenFiredForRelativePathStartingWithSlash_Unix(string slashes) { await TokenFiredForRelativePathStartingWithSlash(slashes); @@ -1135,7 +1136,7 @@ public async Task TokenNotFiredForInvalidPathStartingWithSlash_Windows(string sl [InlineData("/\0/")] // Testing Unix specific behaviour on leading slashes. [PlatformSpecific(TestPlatforms.AnyUnix)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenNotFiredForInvalidPathStartingWithSlash_Unix(string slashes) { await TokenNotFiredForInvalidPathStartingWithSlash(slashes); @@ -1167,7 +1168,7 @@ private async Task TokenNotFiredForInvalidPathStartingWithSlash(string slashes) [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenFiredForGlobbingPatternsPointingToSubDirectory() { using (var root = new DisposableFileSystem()) @@ -1201,7 +1202,7 @@ public async Task TokenFiredForGlobbingPatternsPointingToSubDirectory() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "Browser always uses Active Polling which doesn't return the same instance between multiple calls to Watch(string)")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "Browser/iOS/tvOS always uses Active Polling which doesn't return the same instance between multiple calls to Watch(string)")] public void TokensWithForwardAndBackwardSlashesAreSame() { using (var root = new DisposableFileSystem()) @@ -1218,7 +1219,7 @@ public void TokensWithForwardAndBackwardSlashesAreSame() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokensFiredForOldAndNewNamesOnRename() { using (var root = new DisposableFileSystem()) @@ -1248,7 +1249,7 @@ public async Task TokensFiredForOldAndNewNamesOnRename() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokensFiredForNewDirectoryContentsOnRename() { var tcsShouldNotFire = new TaskCompletionSource(); @@ -1322,7 +1323,7 @@ void Fail(object state) [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokenNotFiredForFileNameStartingWithPeriod() { using (var root = new DisposableFileSystem()) @@ -1390,7 +1391,7 @@ public async Task TokensNotFiredForHiddenAndSystemFiles() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task TokensFiredForAllEntriesOnError() { using (var root = new DisposableFileSystem()) @@ -1419,7 +1420,7 @@ public async Task TokensFiredForAllEntriesOnError() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task WildCardToken_RaisesEventsForNewFilesAdded() { // Arrange @@ -1446,7 +1447,7 @@ public async Task WildCardToken_RaisesEventsForNewFilesAdded() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task WildCardToken_RaisesEventsWhenFileSystemWatcherDoesNotFire() { // Arrange @@ -1496,7 +1497,7 @@ public void UsePollingFileWatcher_FileWatcherNull_SetsSuccessfully() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void UsePollingFileWatcher_FileWatcherNotNull_SetterThrows() { // Arrange @@ -1517,7 +1518,7 @@ public void UsePollingFileWatcher_FileWatcherNotNull_SetterThrows() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void UsePollingFileWatcher_FileWatcherNotNull_ReturnsFalse() { // Arrange @@ -1618,7 +1619,7 @@ public void CreateFileWatcher_CreatesWatcherWithPollingAndActiveFlags() [InlineData(false)] [InlineData(true)] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task CanDeleteWatchedDirectory(bool useActivePolling) { using (var root = new DisposableFileSystem()) diff --git a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs index 2e48a7cb0c0f70..fed678475f8e8d 100644 --- a/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs +++ b/src/libraries/Microsoft.Extensions.FileProviders.Physical/tests/PhysicalFilesWatcherTests.cs @@ -18,7 +18,7 @@ public class PhysicalFilesWatcherTests private const int WaitTimeForTokenToFire = 500; [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void CreateFileChangeToken_DoesNotAllowPathsAboveRoot() { using (var root = new DisposableFileSystem()) @@ -38,7 +38,7 @@ public void CreateFileChangeToken_DoesNotAllowPathsAboveRoot() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public async Task HandlesOnRenamedEventsThatMatchRootPath() { using (var root = new DisposableFileSystem()) @@ -131,7 +131,7 @@ public void RaiseChangeEvents_CancelsAndRemovesMultipleChangedTokens() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void GetOrAddFilePathChangeToken_AddsPollingChangeTokenWithCancellationToken_WhenActiveCallbackIsTrue() { using (var root = new DisposableFileSystem()) @@ -158,7 +158,7 @@ public void GetOrAddFilePathChangeToken_AddsPollingChangeTokenWithCancellationTo } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void GetOrAddFilePathChangeToken_AddsPollingChangeTokenWhenPollingIsEnabled() { using (var root = new DisposableFileSystem()) @@ -183,7 +183,7 @@ public void GetOrAddFilePathChangeToken_AddsPollingChangeTokenWhenPollingIsEnabl } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void GetOrAddFilePathChangeToken_DoesNotAddsPollingChangeTokenWhenCallbackIsDisabled() { using (var root = new DisposableFileSystem()) @@ -198,7 +198,7 @@ public void GetOrAddFilePathChangeToken_DoesNotAddsPollingChangeTokenWhenCallbac } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] public void GetOrAddWildcardChangeToken_AddsPollingChangeTokenWithCancellationToken_WhenActiveCallbackIsTrue() { using (var root = new DisposableFileSystem()) diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/HostFactoryResolver.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/HostFactoryResolver.cs index 49ef8b69517309..ec4335d5f5343b 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/HostFactoryResolver.cs +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/HostFactoryResolver.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -19,9 +20,25 @@ internal sealed class HostFactoryResolver public const string BuildWebHost = nameof(BuildWebHost); public const string CreateWebHostBuilder = nameof(CreateWebHostBuilder); public const string CreateHostBuilder = nameof(CreateHostBuilder); + private const string TimeoutEnvironmentKey = "DOTNET_HOST_FACTORY_RESOLVER_DEFAULT_TIMEOUT_IN_SECONDS"; // The amount of time we wait for the diagnostic source events to fire - private static readonly TimeSpan s_defaultWaitTimeout = Debugger.IsAttached ? Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(5); + private static readonly TimeSpan s_defaultWaitTimeout = SetupDefaultTimout(); + + private static TimeSpan SetupDefaultTimout() + { + if (Debugger.IsAttached) + { + return Timeout.InfiniteTimeSpan; + } + + if (uint.TryParse(Environment.GetEnvironmentVariable(TimeoutEnvironmentKey), out uint timeoutInSeconds)) + { + return TimeSpan.FromSeconds((int)timeoutInSeconds); + } + + return TimeSpan.FromMinutes(5); + } public static Func? ResolveWebHostFactory(Assembly assembly) { @@ -144,6 +161,14 @@ private static bool IsFactory(MethodInfo? factory) { return args => { + static bool IsApplicationNameArg(string arg) + => arg.Equals("--applicationName", StringComparison.OrdinalIgnoreCase) || + arg.Equals("/applicationName", StringComparison.OrdinalIgnoreCase); + + args = args.Any(arg => IsApplicationNameArg(arg)) || assembly.FullName is null + ? args + : args.Concat(new[] { "--applicationName", assembly.FullName }).ToArray(); + var host = hostFactory(args); return GetServiceProvider(host); }; @@ -220,7 +245,7 @@ public object CreateHost() // Try to set an exception if the entry point returns gracefully, this will force // build to throw - _hostTcs.TrySetException(new InvalidOperationException("Unable to build IHost")); + _hostTcs.TrySetException(new InvalidOperationException("The entry point exited without ever building an IHost.")); } catch (TargetInvocationException tie) when (tie.InnerException is StopTheHostException) { @@ -259,7 +284,7 @@ public object CreateHost() // Wait before throwing an exception if (!_hostTcs.Task.Wait(_waitTimeout)) { - throw new InvalidOperationException("Unable to build IHost"); + throw new InvalidOperationException($"Timed out waiting for the entry point to build the IHost after {s_defaultWaitTimeout}. This timeout can be modified using the '{TimeoutEnvironmentKey}' environment variable."); } } catch (AggregateException) when (_hostTcs.Task.IsCompleted) diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj index 31cd86025ee019..9d328fb100d1ad 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/src/Microsoft.Extensions.HostFactoryResolver.Sources.csproj @@ -9,6 +9,7 @@ true true + 1 Internal package for sharing Microsoft.Extensions.Hosting.HostFactoryResolver type. diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromAgrument/ApplicationNameSetFromAgrument.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromAgrument/ApplicationNameSetFromAgrument.csproj new file mode 100644 index 00000000000000..716b25a87281da --- /dev/null +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromAgrument/ApplicationNameSetFromAgrument.csproj @@ -0,0 +1,13 @@ + + + + $(NetCoreAppCurrent);net461 + true + Exe + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromAgrument/Program.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromAgrument/Program.cs new file mode 100644 index 00000000000000..f83f5c12af7966 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/ApplicationNameSetFromAgrument/Program.cs @@ -0,0 +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; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + +var host = new HostBuilder().ConfigureAppConfiguration(builder => builder.AddCommandLine(args)).Build(); \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs index 8f6cf79de0bf3e..d6cf530c94e93a 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.cs +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/HostFactoryResolverTests.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 Microsoft.Extensions.Configuration; using MockHostTypes; using System; using System.Diagnostics.CodeAnalysis; @@ -252,6 +253,27 @@ public void TopLevelStatements() Assert.IsAssignableFrom(factory(Array.Empty())); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public void TopLevelStatementsTestsTimeout() + { + var assembly = Assembly.Load("TopLevelStatementsTestsTimeout"); + var factory = HostFactoryResolver.ResolveServiceProviderFactory(assembly, s_WaitTimeout); + + Assert.NotNull(factory); + Assert.Throws(() => factory(Array.Empty())); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public void ApplicationNameSetFromAgrument() + { + Assembly assembly = Assembly.Load("ApplicationNameSetFromAgrument"); + var factory = HostFactoryResolver.ResolveServiceProviderFactory(assembly, s_WaitTimeout); + IServiceProvider? serviceProvider = factory(Array.Empty()); + + var configuration = (IConfiguration)serviceProvider.GetService(typeof(IConfiguration)); + Assert.Contains("ApplicationNameSetFromAgrument", configuration["applicationName"]); + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(NoSpecialEntryPointPattern.Program))] public void NoSpecialEntryPointPatternCanRunInParallel() diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj index dc808c40b7cc99..fe811f1fe1b5df 100644 --- a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/Microsoft.Extensions.HostFactoryResolver.Tests.csproj @@ -14,6 +14,7 @@ + @@ -27,6 +28,7 @@ + diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/Program.cs b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/Program.cs new file mode 100644 index 00000000000000..f4c01882987e12 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/Program.cs @@ -0,0 +1,10 @@ +// 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.Threading; +using Microsoft.Extensions.Hosting; + +var hostBuilder = new HostBuilder(); +Thread.Sleep(TimeSpan.FromSeconds(30)); +hostBuilder.Build(); \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj new file mode 100644 index 00000000000000..716b25a87281da --- /dev/null +++ b/src/libraries/Microsoft.Extensions.HostFactoryResolver/tests/TopLevelStatementsTestsTimeout/TopLevelStatementsTestsTimeout.csproj @@ -0,0 +1,13 @@ + + + + $(NetCoreAppCurrent);net461 + true + Exe + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.sln b/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.sln index 4d180d0e8e5926..fad399ab4ffd49 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.sln +++ b/src/libraries/Microsoft.Extensions.Hosting.Systemd/Microsoft.Extensions.Hosting.Systemd.sln @@ -71,8 +71,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hostin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hosting", "..\Microsoft.Extensions.Hosting\src\Microsoft.Extensions.Hosting.csproj", "{AFC1BDAA-7E40-4118-BB80-F8057752A600}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{21A8F1A2-DB8F-40BB-8B41-34FFBFF678BE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{860B845B-929F-4442-AED1-1F4186DBF497}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{A0AF82AE-ED18-4EEB-AD9A-B44017510F0C}" @@ -131,8 +129,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Security.Permissions EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{47A3CDB0-8252-4536-B61F-C2E10F6EC2B9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{CA49BE02-D809-4F18-8E0B-54FA365429E3}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{25474DE2-4D3D-4950-BDA7-CF6FE3CCD940}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.AccessControl", "..\System.Threading.AccessControl\ref\System.Threading.AccessControl.csproj", "{6061433D-2A71-47B3-B34B-3EDF523ABB78}" @@ -397,10 +393,6 @@ Global {1A3EF133-CC86-4CC9-BBB8-333D41563AC3}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A3EF133-CC86-4CC9-BBB8-333D41563AC3}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A3EF133-CC86-4CC9-BBB8-333D41563AC3}.Release|Any CPU.Build.0 = Release|Any CPU - {CA49BE02-D809-4F18-8E0B-54FA365429E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CA49BE02-D809-4F18-8E0B-54FA365429E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA49BE02-D809-4F18-8E0B-54FA365429E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CA49BE02-D809-4F18-8E0B-54FA365429E3}.Release|Any CPU.Build.0 = Release|Any CPU {47A3CDB0-8252-4536-B61F-C2E10F6EC2B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {47A3CDB0-8252-4536-B61F-C2E10F6EC2B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {47A3CDB0-8252-4536-B61F-C2E10F6EC2B9}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -509,7 +501,6 @@ Global {3488D63C-0C29-442C-8145-407DE19C7480} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} {2E027B76-275A-4FCE-9774-A2F8C3CD0C7E} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} {578661A4-C136-4533-819E-AF3352F79953} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} - {CA49BE02-D809-4F18-8E0B-54FA365429E3} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} {47A3CDB0-8252-4536-B61F-C2E10F6EC2B9} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} {C1ACBD81-9577-483B-8E33-819F1313114A} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} {01DB5E6D-40C5-42F7-8F9D-6F8DBC591129} = {192FD259-E55F-40C5-82EE-9E924EA6C3CB} diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Directory.Build.props b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Directory.Build.props index 899ad9d38a52d6..3d31843054e721 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Directory.Build.props +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Directory.Build.props @@ -2,6 +2,5 @@ hosting - windows diff --git a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.sln b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.sln index d044381432e722..b07fcf11887c4b 100644 --- a/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.sln +++ b/src/libraries/Microsoft.Extensions.Hosting.WindowsServices/Microsoft.Extensions.Hosting.WindowsServices.sln @@ -67,8 +67,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hostin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hosting", "..\Microsoft.Extensions.Hosting\src\Microsoft.Extensions.Hosting.csproj", "{36FAE390-EAAE-4193-98E7-34F10D3FA8E1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{9CECED3B-385A-4C54-9E07-74E8341EB52D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{723957C4-C433-4B6D-BF0C-28AE36AEDDBD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{E5F61C36-FB9B-4DA7-96C0-056FBEADBB53}" @@ -131,8 +129,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ServiceProcess.Servi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{2D8B86CE-7A3A-45F0-9127-AE6CDCEC6EA5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{CC36DF9A-6602-47D9-B44B-C2D2C33A80D0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{C50BBD27-2445-4DF4-9A1D-C7919D016BBC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.AccessControl", "..\System.Threading.AccessControl\ref\System.Threading.AccessControl.csproj", "{B7ACDBBE-C64B-482B-B80D-3DC002AD450B}" @@ -419,10 +415,6 @@ Global {B7ACDBBE-C64B-482B-B80D-3DC002AD450B}.Debug|Any CPU.Build.0 = Debug|Any CPU {B7ACDBBE-C64B-482B-B80D-3DC002AD450B}.Release|Any CPU.ActiveCfg = Release|Any CPU {B7ACDBBE-C64B-482B-B80D-3DC002AD450B}.Release|Any CPU.Build.0 = Release|Any CPU - {CC36DF9A-6602-47D9-B44B-C2D2C33A80D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CC36DF9A-6602-47D9-B44B-C2D2C33A80D0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CC36DF9A-6602-47D9-B44B-C2D2C33A80D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CC36DF9A-6602-47D9-B44B-C2D2C33A80D0}.Release|Any CPU.Build.0 = Release|Any CPU {2D8B86CE-7A3A-45F0-9127-AE6CDCEC6EA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2D8B86CE-7A3A-45F0-9127-AE6CDCEC6EA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {2D8B86CE-7A3A-45F0-9127-AE6CDCEC6EA5}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -509,7 +501,6 @@ Global {C50BBD27-2445-4DF4-9A1D-C7919D016BBC} = {76933DF1-12AA-4B5B-8863-EF38F10B1EC9} {83D8F9FB-0A8D-4E48-A7CF-D169432A41AD} = {76933DF1-12AA-4B5B-8863-EF38F10B1EC9} {BAE78100-3020-4AAE-BDBF-ACF9D1D1BA2F} = {76933DF1-12AA-4B5B-8863-EF38F10B1EC9} - {CC36DF9A-6602-47D9-B44B-C2D2C33A80D0} = {76933DF1-12AA-4B5B-8863-EF38F10B1EC9} {2D8B86CE-7A3A-45F0-9127-AE6CDCEC6EA5} = {76933DF1-12AA-4B5B-8863-EF38F10B1EC9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/Microsoft.Extensions.Hosting/Directory.Build.props b/src/libraries/Microsoft.Extensions.Hosting/Directory.Build.props index 43dc3a2640bbae..207017db91b3d1 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/Directory.Build.props +++ b/src/libraries/Microsoft.Extensions.Hosting/Directory.Build.props @@ -2,5 +2,6 @@ true + 1 diff --git a/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.sln b/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.sln index a9809bec457afd..529c17516ab669 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.sln +++ b/src/libraries/Microsoft.Extensions.Hosting/Microsoft.Extensions.Hosting.sln @@ -71,8 +71,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hostin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hosting.Unit.Tests", "tests\UnitTests\Microsoft.Extensions.Hosting.Unit.Tests.csproj", "{33C3D8F0-297F-4471-92B0-F4E8717F10E3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{FBF0B5C9-CD20-4B8A-83B4-6281A2EEBC45}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{42E1BF94-6FE0-4017-9702-55913BD95EDE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{8845E6FF-94B2-4994-A8F4-DF30844A2168}" @@ -131,8 +129,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Security.Permissions EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{B41AA17B-5129-41CC-8EA4-250B80BABF87}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{631AE96F-2615-4D38-B3BB-0D98777C4667}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{0813853E-8C78-429A-B01A-3FB2EF1898F8}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.AccessControl", "..\System.Threading.AccessControl\ref\System.Threading.AccessControl.csproj", "{6F69FD88-7BD1-41DF-BF5D-F0E5F12BE766}" @@ -401,10 +397,6 @@ Global {014EE6B4-BE08-4E50-9EBD-0D7A0CB7A76E}.Debug|Any CPU.Build.0 = Debug|Any CPU {014EE6B4-BE08-4E50-9EBD-0D7A0CB7A76E}.Release|Any CPU.ActiveCfg = Release|Any CPU {014EE6B4-BE08-4E50-9EBD-0D7A0CB7A76E}.Release|Any CPU.Build.0 = Release|Any CPU - {631AE96F-2615-4D38-B3BB-0D98777C4667}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {631AE96F-2615-4D38-B3BB-0D98777C4667}.Debug|Any CPU.Build.0 = Debug|Any CPU - {631AE96F-2615-4D38-B3BB-0D98777C4667}.Release|Any CPU.ActiveCfg = Release|Any CPU - {631AE96F-2615-4D38-B3BB-0D98777C4667}.Release|Any CPU.Build.0 = Release|Any CPU {B41AA17B-5129-41CC-8EA4-250B80BABF87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B41AA17B-5129-41CC-8EA4-250B80BABF87}.Debug|Any CPU.Build.0 = Debug|Any CPU {B41AA17B-5129-41CC-8EA4-250B80BABF87}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -509,7 +501,6 @@ Global {0AEAD15B-CD38-4462-A36C-655ED8D0CBD1} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} {0BC9E4F4-5C34-4B90-80AB-2933992D99A6} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} {4ED9C0A9-C1EF-47ED-99F8-74B7411C971B} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} - {631AE96F-2615-4D38-B3BB-0D98777C4667} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} {B41AA17B-5129-41CC-8EA4-250B80BABF87} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} {C58E2CF3-F8AA-47C1-8A49-65B91252F2AA} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} {A5DD36AF-F0AD-4616-AB91-BC63E89B2744} = {59A29BF0-B76B-41F8-A733-E2A0847AB992} diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs b/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs index 4041133a0a9f25..2f73146e695ef2 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs @@ -79,15 +79,22 @@ public async Task StartAsync(CancellationToken cancellationToken = default) private async Task TryExecuteBackgroundServiceAsync(BackgroundService backgroundService) { + // backgroundService.ExecuteTask may not be set (e.g. if the derived class doesn't call base.StartAsync) + Task backgroundTask = backgroundService.ExecuteTask; + if (backgroundTask == null) + { + return; + } + try { - await backgroundService.ExecuteTask.ConfigureAwait(false); + await backgroundTask.ConfigureAwait(false); } catch (Exception ex) { // When the host is being stopped, it cancels the background services. // This isn't an error condition, so don't log it as an error. - if (_stopCalled && backgroundService.ExecuteTask.IsCanceled && ex is OperationCanceledException) + if (_stopCalled && backgroundTask.IsCanceled && ex is OperationCanceledException) { return; } diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj index b868be57845e0c..5962169ce1aea5 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/src/Microsoft.Extensions.Hosting.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent);netstandard2.0;netstandard2.1;net461 @@ -6,6 +6,7 @@ Hosting and startup infrastructures for applications. false + diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs index d07c2bc57eaa71..b3133dba3be886 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs @@ -1394,6 +1394,36 @@ public async Task HostNoErrorWhenServiceIsCanceledAsPartOfStop() } } + /// + /// Tests that when a BackgroundService does not call base, the Host still starts and stops successfully. + /// + [Fact] + public async Task StartOnBackgroundServiceThatDoesNotCallBase() + { + TestLoggerProvider logger = new TestLoggerProvider(); + + using IHost host = CreateBuilder() + .ConfigureLogging(logging => + { + logging.AddProvider(logger); + }) + .ConfigureServices(services => + { + services.AddHostedService(); + }) + .Build(); + + host.Start(); + await host.StopAsync(); + + foreach (LogEvent logEvent in logger.GetEvents()) + { + Assert.True(logEvent.LogLevel <= LogLevel.Information, "All logged events should be less than or equal to Information. No Warnings or Errors."); + + Assert.NotEqual("BackgroundServiceFaulted", logEvent.EventId.Name); + } + } + private IHostBuilder CreateBuilder(IConfiguration config = null) { return new HostBuilder().ConfigureHostConfiguration(builder => builder.AddConfiguration(config ?? new ConfigurationBuilder().Build())); @@ -1562,5 +1592,14 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } } } + + private class BackgroundServiceDoesNotCallBase : BackgroundService + { + public override Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; + + protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.CompletedTask; + + public override Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; + } } } diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj index ee0c814c41b3f0..babb650155cbfb 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Microsoft.Extensions.Hosting.Unit.Tests.csproj @@ -18,4 +18,10 @@ + + + + + diff --git a/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.sln b/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.sln index bbb76ebd7a1ab7..1f763e573612b6 100644 --- a/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.sln +++ b/src/libraries/Microsoft.Extensions.Http/Microsoft.Extensions.Http.sln @@ -19,8 +19,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Http", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Http.Tests", "tests\Microsoft.Extensions.Http.Tests\Microsoft.Extensions.Http.Tests.csproj", "{58A1E42E-5DA1-452A-B39C-A1819171970A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{3DD4EF0E-36D5-48BD-8F8A-1D7DAF74EC25}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{85615392-9242-4CAF-A0FE-A439FF615462}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{BAFF07C7-1F5F-4706-B7D7-9D5D309CBFE2}" diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln index 869ed2e72f0dd8..147339db0e9240 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/Microsoft.Extensions.Logging.Abstractions.sln @@ -1,13 +1,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{79CE8C7E-A4AF-413C-A54D-86F17073559C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "gen\Microsoft.Extensions.Logging.Generators.csproj", "{1CB925AD-09DA-4734-BA05-619A00E5B448}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{7F536552-0E2A-4642-B7CF-863727C2F9CD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "src\Microsoft.Extensions.Logging.Abstractions.csproj", "{75C579F7-F20B-41F1-8CAF-641DE7ADA4EE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Tests", "tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Tests.csproj", "{1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests", "tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests.csproj", "{1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\ref\System.Runtime.CompilerServices.Unsafe.csproj", "{DAA1349E-960E-49EB-81F3-FF4F99D8A325}" EndProject @@ -19,6 +17,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4DE63935 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{548DF5F7-790C-4A1C-89EB-BD904CA1BA86}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn4.0", "gen\Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj", "{A5439E79-96D6-4F02-8DD0-23DFF979851D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn3.11", "gen\Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj", "{1491B9C9-955D-4DB0-B1D5-70137A78EAAE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators.Roslyn3.11.Tests", "tests\Microsoft.Extensions.Logging.Generators.Tests\Microsoft.Extensions.Logging.Generators.Roslyn3.11.Tests.csproj", "{C333EC5A-F386-4A01-AE20-12D499551304}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,18 +45,38 @@ Global {79CE8C7E-A4AF-413C-A54D-86F17073559C}.Debug|Any CPU.Build.0 = Debug|Any CPU {79CE8C7E-A4AF-413C-A54D-86F17073559C}.Release|Any CPU.ActiveCfg = Release|Any CPU {79CE8C7E-A4AF-413C-A54D-86F17073559C}.Release|Any CPU.Build.0 = Release|Any CPU - {1CB925AD-09DA-4734-BA05-619A00E5B448}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1CB925AD-09DA-4734-BA05-619A00E5B448}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1CB925AD-09DA-4734-BA05-619A00E5B448}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1CB925AD-09DA-4734-BA05-619A00E5B448}.Release|Any CPU.Build.0 = Release|Any CPU - {F8CF3192-B902-4631-972A-C405FDECC48D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F8CF3192-B902-4631-972A-C405FDECC48D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F8CF3192-B902-4631-972A-C405FDECC48D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F8CF3192-B902-4631-972A-C405FDECC48D}.Release|Any CPU.Build.0 = Release|Any CPU + {7F536552-0E2A-4642-B7CF-863727C2F9CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F536552-0E2A-4642-B7CF-863727C2F9CD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F536552-0E2A-4642-B7CF-863727C2F9CD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F536552-0E2A-4642-B7CF-863727C2F9CD}.Release|Any CPU.Build.0 = Release|Any CPU + {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE}.Release|Any CPU.Build.0 = Release|Any CPU + {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B}.Release|Any CPU.Build.0 = Release|Any CPU {DAA1349E-960E-49EB-81F3-FF4F99D8A325}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DAA1349E-960E-49EB-81F3-FF4F99D8A325}.Debug|Any CPU.Build.0 = Debug|Any CPU {DAA1349E-960E-49EB-81F3-FF4F99D8A325}.Release|Any CPU.ActiveCfg = Release|Any CPU {DAA1349E-960E-49EB-81F3-FF4F99D8A325}.Release|Any CPU.Build.0 = Release|Any CPU + {F8CF3192-B902-4631-972A-C405FDECC48D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8CF3192-B902-4631-972A-C405FDECC48D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8CF3192-B902-4631-972A-C405FDECC48D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8CF3192-B902-4631-972A-C405FDECC48D}.Release|Any CPU.Build.0 = Release|Any CPU + {A5439E79-96D6-4F02-8DD0-23DFF979851D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5439E79-96D6-4F02-8DD0-23DFF979851D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5439E79-96D6-4F02-8DD0-23DFF979851D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5439E79-96D6-4F02-8DD0-23DFF979851D}.Release|Any CPU.Build.0 = Release|Any CPU + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE}.Release|Any CPU.Build.0 = Release|Any CPU + {C333EC5A-F386-4A01-AE20-12D499551304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C333EC5A-F386-4A01-AE20-12D499551304}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C333EC5A-F386-4A01-AE20-12D499551304}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C333EC5A-F386-4A01-AE20-12D499551304}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -62,9 +86,14 @@ Global {DAA1349E-960E-49EB-81F3-FF4F99D8A325} = {7631380A-FB73-4241-9987-0891A21E9769} {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} {79CE8C7E-A4AF-413C-A54D-86F17073559C} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} + {7F536552-0E2A-4642-B7CF-863727C2F9CD} = {7631380A-FB73-4241-9987-0891A21E9769} {75C579F7-F20B-41F1-8CAF-641DE7ADA4EE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} - {1CB925AD-09DA-4734-BA05-619A00E5B448} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} + {1CB869A7-2EEC-4A53-9C33-DF9E0C75825B} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} + {DAA1349E-960E-49EB-81F3-FF4F99D8A325} = {7631380A-FB73-4241-9987-0891A21E9769} {F8CF3192-B902-4631-972A-C405FDECC48D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} + {A5439E79-96D6-4F02-8DD0-23DFF979851D} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} + {1491B9C9-955D-4DB0-B1D5-70137A78EAAE} = {548DF5F7-790C-4A1C-89EB-BD904CA1BA86} + {C333EC5A-F386-4A01-AE20-12D499551304} = {4DE63935-DCA9-4D63-9C1F-AAE79C89CA8B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {450DA749-CBDC-4BDC-950F-8A491CF59D49} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs index 53dd062b5d4b4c..249672b37058b1 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Emitter.cs @@ -78,7 +78,7 @@ namespace {lc.Namespace} // loop until you find top level nested class while (parent != null) { - parentClasses.Add($"partial {parent.Keyword} {parent.Name} {parent.Constraints}"); + parentClasses.Add($"partial {parent.Keyword} {parent.Name} "); parent = parent.ParentClass; } @@ -92,7 +92,7 @@ namespace {lc.Namespace} } _builder.Append($@" - {nestedIndentation}partial {lc.Keyword} {lc.Name} {lc.Constraints} + {nestedIndentation}partial {lc.Keyword} {lc.Name} {nestedIndentation}{{"); foreach (LoggerMethod lm in lc.Methods) @@ -196,7 +196,7 @@ private void GenFieldAssignments(LoggerMethod lm, string nestedIndentation) { foreach (LoggerParameter p in lm.TemplateParameters) { - _builder.AppendLine($" {nestedIndentation}this._{p.Name} = {p.Name};"); + _builder.AppendLine($" {nestedIndentation}this._{p.Name} = {p.CodeName};"); } } @@ -255,7 +255,7 @@ private void GenCallbackArguments(LoggerMethod lm) { foreach (LoggerParameter p in lm.TemplateParameters) { - _builder.Append($"{p.Name}, "); + _builder.Append($"{p.CodeName}, "); } } @@ -309,7 +309,11 @@ private void GenParameters(LoggerMethod lm) _builder.Append(", "); } - _builder.Append($"{p.Type} {p.Name}"); + if (p.Qualifier != null) + { + _builder.Append($"{p.Qualifier} "); + } + _builder.Append($"{p.Type} {p.CodeName}"); } } @@ -327,7 +331,7 @@ private void GenArguments(LoggerMethod lm) _builder.Append(", "); } - _builder.Append($"{p.Type} {p.Name}"); + _builder.Append($"{p.Type} {p.CodeName}"); } } @@ -343,7 +347,7 @@ private void GenHolder(LoggerMethod lm) _builder.Append(", "); } - _builder.Append(p.Name); + _builder.Append(p.CodeName); } _builder.Append(')'); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs index 4a995039104b9d..592ee84655139e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs @@ -10,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.Collections.Immutable; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Microsoft.Extensions.Logging.Generators { @@ -17,6 +18,8 @@ public partial class LoggerMessageGenerator { internal class Parser { + private const string LoggerMessageAttribute = "Microsoft.Extensions.Logging.LoggerMessageAttribute"; + private readonly CancellationToken _cancellationToken; private readonly Compilation _compilation; private readonly Action _reportDiagnostic; @@ -28,35 +31,63 @@ public Parser(Compilation compilation, Action reportDiagnostic, Canc _reportDiagnostic = reportDiagnostic; } + internal static bool IsSyntaxTargetForGeneration(SyntaxNode node) => + node is MethodDeclarationSyntax m && m.AttributeLists.Count > 0; + + internal static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context) + { + var methodDeclarationSyntax = (MethodDeclarationSyntax)context.Node; + + foreach (AttributeListSyntax attributeListSyntax in methodDeclarationSyntax.AttributeLists) + { + foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + { + IMethodSymbol attributeSymbol = context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol as IMethodSymbol; + if (attributeSymbol == null) + { + continue; + } + + INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType; + string fullName = attributeContainingTypeSymbol.ToDisplayString(); + + if (fullName == LoggerMessageAttribute) + { + return methodDeclarationSyntax.Parent as ClassDeclarationSyntax; + } + } + } + + return null; + } + /// /// Gets the set of logging classes containing methods to output. /// public IReadOnlyList GetLogClasses(IEnumerable classes) { - const string LoggerMessageAttribute = "Microsoft.Extensions.Logging.LoggerMessageAttribute"; - - INamedTypeSymbol loggerMessageAttribute = _compilation.GetTypeByMetadataName(LoggerMessageAttribute); + INamedTypeSymbol loggerMessageAttribute = _compilation.GetBestTypeByMetadataName(LoggerMessageAttribute); if (loggerMessageAttribute == null) { // nothing to do if this type isn't available return Array.Empty(); } - INamedTypeSymbol loggerSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.ILogger"); + INamedTypeSymbol loggerSymbol = _compilation.GetBestTypeByMetadataName("Microsoft.Extensions.Logging.ILogger"); if (loggerSymbol == null) { // nothing to do if this type isn't available return Array.Empty(); } - INamedTypeSymbol logLevelSymbol = _compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.LogLevel"); + INamedTypeSymbol logLevelSymbol = _compilation.GetBestTypeByMetadataName("Microsoft.Extensions.Logging.LogLevel"); if (logLevelSymbol == null) { // nothing to do if this type isn't available return Array.Empty(); } - INamedTypeSymbol exceptionSymbol = _compilation.GetTypeByMetadataName("System.Exception"); + INamedTypeSymbol exceptionSymbol = _compilation.GetBestTypeByMetadataName("System.Exception"); if (exceptionSymbol == null) { Diag(DiagnosticDescriptors.MissingRequiredType, null, "System.Exception"); @@ -277,6 +308,15 @@ public IReadOnlyList GetLogClasses(IEnumerable 0) + { + ParameterSyntax paramSyntax = paramSymbol.DeclaringSyntaxReferences[0].GetSyntax(_cancellationToken) as ParameterSyntax; + if (paramSyntax != null && !string.IsNullOrEmpty(paramSyntax.Identifier.Text)) + { + needsAtSign = paramSyntax.Identifier.Text[0] == '@'; + } + } if (string.IsNullOrWhiteSpace(paramName)) { // semantic problem, just bail quietly @@ -292,6 +332,15 @@ public IReadOnlyList GetLogClasses(IEnumerable GetLogClasses(IEnumerable GetLogClasses(IEnumerable GetLogClasses(IEnumerable + bool IsAllowedKind(SyntaxKind kind) => kind == SyntaxKind.ClassDeclaration || kind == SyntaxKind.StructDeclaration || kind == SyntaxKind.RecordDeclaration; - + while (parentLoggerClass != null && IsAllowedKind(parentLoggerClass.Kind())) { currentLoggerClass.ParentClass = new LoggerClass @@ -454,7 +514,6 @@ bool IsAllowedKind(SyntaxKind kind) => Keyword = parentLoggerClass.Keyword.ValueText, Namespace = nspace, Name = parentLoggerClass.Identifier.ToString() + parentLoggerClass.TypeParameterList, - Constraints = parentLoggerClass.ConstraintClauses.ToString(), ParentClass = null, }; @@ -640,7 +699,6 @@ internal class LoggerClass public string Keyword = string.Empty; public string Namespace = string.Empty; public string Name = string.Empty; - public string Constraints = string.Empty; public LoggerClass? ParentClass; } @@ -671,6 +729,8 @@ internal class LoggerParameter { public string Name = string.Empty; public string Type = string.Empty; + public string CodeName = string.Empty; + public string? Qualifier; public bool IsLogger; public bool IsException; public bool IsLogLevel; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn3.11.cs similarity index 61% rename from src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.cs rename to src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn3.11.cs index 92105d515e328c..52a42cec41d08c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn3.11.cs @@ -1,10 +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; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -17,16 +14,14 @@ namespace Microsoft.Extensions.Logging.Generators [Generator] public partial class LoggerMessageGenerator : ISourceGenerator { - [ExcludeFromCodeCoverage] public void Initialize(GeneratorInitializationContext context) { - context.RegisterForSyntaxNotifications(SyntaxReceiver.Create); + context.RegisterForSyntaxNotifications(SyntaxContextReceiver.Create); } - [ExcludeFromCodeCoverage] public void Execute(GeneratorExecutionContext context) { - if (context.SyntaxReceiver is not SyntaxReceiver receiver || receiver.ClassDeclarations.Count == 0) + if (context.SyntaxContextReceiver is not SyntaxContextReceiver receiver || receiver.ClassDeclarations.Count == 0) { // nothing to do yet return; @@ -38,26 +33,29 @@ public void Execute(GeneratorExecutionContext context) { var e = new Emitter(); string result = e.Emit(logClasses, context.CancellationToken); - + context.AddSource("LoggerMessage.g.cs", SourceText.From(result, Encoding.UTF8)); } } - [ExcludeFromCodeCoverage] - private sealed class SyntaxReceiver : ISyntaxReceiver + private sealed class SyntaxContextReceiver : ISyntaxContextReceiver { - internal static ISyntaxReceiver Create() + internal static ISyntaxContextReceiver Create() { - return new SyntaxReceiver(); + return new SyntaxContextReceiver(); } - public List ClassDeclarations { get; } = new (); + public HashSet ClassDeclarations { get; } = new(); - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + public void OnVisitSyntaxNode(GeneratorSyntaxContext context) { - if (syntaxNode is ClassDeclarationSyntax classSyntax) + if (Parser.IsSyntaxTargetForGeneration(context.Node)) { - ClassDeclarations.Add(classSyntax); + ClassDeclarationSyntax classSyntax = Parser.GetSemanticTargetForGeneration(context); + if (classSyntax != null) + { + ClassDeclarations.Add(classSyntax); + } } } } diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs new file mode 100644 index 00000000000000..3b7817cebeeba4 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Roslyn4.0.cs @@ -0,0 +1,52 @@ +// 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.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +[assembly: System.Resources.NeutralResourcesLanguage("en-us")] + +namespace Microsoft.Extensions.Logging.Generators +{ + [Generator] + public partial class LoggerMessageGenerator : IIncrementalGenerator + { + public void Initialize(IncrementalGeneratorInitializationContext context) + { + IncrementalValuesProvider classDeclarations = context.SyntaxProvider + .CreateSyntaxProvider(static (s, _) => Parser.IsSyntaxTargetForGeneration(s), static (ctx, _) => Parser.GetSemanticTargetForGeneration(ctx)) + .Where(static m => m is not null); + + IncrementalValueProvider<(Compilation, ImmutableArray)> compilationAndClasses = + context.CompilationProvider.Combine(classDeclarations.Collect()); + + context.RegisterSourceOutput(compilationAndClasses, static (spc, source) => Execute(source.Item1, source.Item2, spc)); + } + + private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext context) + { + if (classes.IsDefaultOrEmpty) + { + // nothing to do yet + return; + } + + IEnumerable distinctClasses = classes.Distinct(); + + var p = new Parser(compilation, context.ReportDiagnostic, context.CancellationToken); + IReadOnlyList logClasses = p.GetLogClasses(distinctClasses); + if (logClasses.Count > 0) + { + var e = new Emitter(); + string result = e.Emit(logClasses, context.CancellationToken); + + context.AddSource("LoggerMessage.g.cs", SourceText.From(result, Encoding.UTF8)); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj new file mode 100644 index 00000000000000..4a0f7955215914 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn3.11.csproj @@ -0,0 +1,14 @@ + + + + 3.11 + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion_3_11) + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj new file mode 100644 index 00000000000000..50e939c50b1985 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.Roslyn4.0.csproj @@ -0,0 +1,15 @@ + + + + 4.0 + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion) + $(DefineConstants);ROSLYN4_0_OR_GREATER + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.targets similarity index 57% rename from src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.csproj rename to src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.targets index 1531036a02e811..77a182fa4649aa 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/Microsoft.Extensions.Logging.Generators.targets @@ -1,7 +1,11 @@ - + netstandard2.0 + $(MSBuildThisFileName) + $(MSBuildThisFileName) + SR + FxResources.$(RootNamespace).$(StringResourcesClassName) enable true false @@ -12,8 +16,12 @@ - + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj index 71e35b67179fa7..77092726df74cb 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/Microsoft.Extensions.Logging.Abstractions.csproj @@ -17,6 +17,8 @@ Microsoft.Extensions.Logging.LogLevel Microsoft.Extensions.Logging.Logger<T> Microsoft.Extensions.Logging.LoggerMessage Microsoft.Extensions.Logging.Abstractions.NullLogger + true + 1 @@ -30,13 +32,15 @@ Microsoft.Extensions.Logging.Abstractions.NullLogger Link="Common\System\Text\ValueStringBuilder.cs" /> - + - - + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt index c61da37d27bba4..f4747ef679f83c 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDefaultValues.generated.txt @@ -5,7 +5,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithDefaultValues { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] private readonly struct __M0Struct : global::System.Collections.Generic.IReadOnlyList> { @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, global::Microsoft.Extensions.Logging.LogLevel level) { if (logger.IsEnabled(level)) @@ -54,4 +54,4 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses } } } -} +} \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt index 7a2026361b561b..1d1af4719fe40d 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithDynamicLogLevel.generated.txt @@ -5,7 +5,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithDynamicLogLevel { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] private readonly struct __M9Struct : global::System.Collections.Generic.IReadOnlyList> { @@ -40,7 +40,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] public static partial void M9(global::Microsoft.Extensions.Logging.LogLevel level, global::Microsoft.Extensions.Logging.ILogger logger) { if (logger.IsEnabled(level)) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt index 90455e122c1d42..3387ec2da1a327 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithMoreThan6Params.generated.txt @@ -5,7 +5,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithMoreThan6Params { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] private readonly struct __Method9Struct : global::System.Collections.Generic.IReadOnlyList> { private readonly global::System.Int32 _p1; @@ -73,7 +73,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses global::System.Collections.IEnumerator global::System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); } - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] public static partial void Method9(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Int32 p1, global::System.Int32 p2, global::System.Int32 p3, global::System.Int32 p4, global::System.Int32 p5, global::System.Int32 p6, global::System.Collections.Generic.IEnumerable p7) { if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Error)) @@ -88,7 +88,7 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses } } } -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] +[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] internal static class __LoggerMessageGenerator { public static string Enumerate(global::System.Collections.IEnumerable? enumerable) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt index e10a678aef24cf..07cd2a3aff4211 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithNestedClass.generated.txt @@ -9,17 +9,17 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses.NestedNamesp { partial record NestedRecord { - partial class NestedClassTestsExtensions where T1 : Class1 + partial class NestedClassTestsExtensions { partial class NestedMiddleParentClass { - partial class Nested where T2 : Class2 + partial class Nested { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] private static readonly global::System.Action __M9Callback = global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Debug, new global::Microsoft.Extensions.Logging.EventId(9, nameof(M9)), "M9", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] public static partial void M9(global::Microsoft.Extensions.Logging.ILogger logger) { if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Debug)) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt index 6576bb4b394f1b..24575eb81bf458 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithSkipEnabledCheck.generated.txt @@ -5,11 +5,11 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithSkipEnabledCheck { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] private static readonly global::System.Action __M0Callback = global::Microsoft.Extensions.Logging.LoggerMessage.Define(global::Microsoft.Extensions.Logging.LogLevel.Information, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "Message: When using SkipEnabledCheck, the generated code skips logger.IsEnabled(logLevel) check before calling log. To be used when consumer has already guarded logger method in an IsEnabled check.", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger) { __M0Callback(logger, null); diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt index 5daee3ddd43a1e..d7c2482cdd9216 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Baselines/TestWithTwoParams.generated.txt @@ -5,11 +5,11 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { partial class TestWithTwoParams { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] private static readonly global::System.Action, global::System.Exception?> __M0Callback = global::Microsoft.Extensions.Logging.LoggerMessage.Define>(global::Microsoft.Extensions.Logging.LogLevel.Error, new global::Microsoft.Extensions.Logging.EventId(0, nameof(M0)), "M0 {a1} {a2}", new global::Microsoft.Extensions.Logging.LogDefineOptions() { SkipEnabledCheck = true }); - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "6.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Extensions.Logging.Generators", "%VERSION%")] public static partial void M0(global::Microsoft.Extensions.Logging.ILogger logger, global::System.Int32 a1, global::System.Collections.Generic.IEnumerable a2) { if (logger.IsEnabled(global::Microsoft.Extensions.Logging.LogLevel.Error)) diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/CompilationHelper.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/CompilationHelper.cs new file mode 100644 index 00000000000000..59c82a5437147f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/CompilationHelper.cs @@ -0,0 +1,64 @@ +// 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.Collections.Generic; +using System.IO; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace Microsoft.Extensions.Logging.Generators.Tests +{ + public class CompilationHelper + { + public static Compilation CreateCompilation( + string source, + MetadataReference[]? additionalReferences = null, + string assemblyName = "TestAssembly") + { + string corelib = Assembly.GetAssembly(typeof(object))!.Location; + string runtimeDir = Path.GetDirectoryName(corelib)!; + + var refs = new List(); + refs.Add(MetadataReference.CreateFromFile(corelib)); + refs.Add(MetadataReference.CreateFromFile(Path.Combine(runtimeDir, "netstandard.dll"))); + refs.Add(MetadataReference.CreateFromFile(Path.Combine(runtimeDir, "System.Runtime.dll"))); + refs.Add(MetadataReference.CreateFromFile(typeof(ILogger).Assembly.Location)); + refs.Add(MetadataReference.CreateFromFile(typeof(LoggerMessageAttribute).Assembly.Location)); + + if (additionalReferences != null) + { + foreach (MetadataReference reference in additionalReferences) + { + refs.Add(reference); + } + } + + CSharpParseOptions options = CSharpParseOptions.Default; + +#if ROSLYN4_0_OR_GREATER + // workaround https://github.com/dotnet/roslyn/pull/55866. We can remove "LangVersion=Preview" when we get a Roslyn build with that change. + options = options.WithLanguageVersion(LanguageVersion.Preview); +#endif + + return CSharpCompilation.Create( + assemblyName, + syntaxTrees: new[] { CSharpSyntaxTree.ParseText(source, options) }, + references: refs.ToArray(), + options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) + ); + } + + public static byte[] CreateAssemblyImage(Compilation compilation) + { + MemoryStream ms = new MemoryStream(); + var emitResult = compilation.Emit(ms); + if (!emitResult.Success) + { + throw new InvalidOperationException(); + } + return ms.ToArray(); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs index d55bf4a8028d52..3b0650309a0179 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratedCodeTests.cs @@ -3,8 +3,12 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Generators.Tests.TestClasses; +using Microsoft.Extensions.Logging.Generators.Tests.TestClasses.UsesConstraintInAnotherNamespace; using Xunit; +using NamespaceForABC; +using ConstraintInAnotherNamespace; namespace Microsoft.Extensions.Logging.Generators.Tests { @@ -410,6 +414,71 @@ public void SkipEnabledCheckTests() Assert.Equal(1, logger.CallCount); Assert.Equal("LoggerMethodWithTrueSkipEnabledCheck", logger.LastEventId.Name); } + private struct MyStruct { } + + [Fact] + public void ConstraintsTests() + { + var logger = new MockLogger(); + + var printer = new MessagePrinter(); + logger.Reset(); + printer.Print(logger, new Message() { Text = "Hello" }); + Assert.Equal(LogLevel.Information, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("The message is Hello.", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + var printer2 = new MessagePrinterHasConstraintOnLogClassAndLogMethod(); + logger.Reset(); + printer2.Print(logger, new Message() { Text = "Hello" }); + Assert.Equal(LogLevel.Information, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("The message is `Hello`.", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ConstraintsTestExtensions.M0(logger, 12); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("M012", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ConstraintsTestExtensions1.M0(logger, 12); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("M012", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ConstraintsTestExtensions2.M0(logger, 12); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("M012", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ConstraintsTestExtensions3.M0(logger, 12); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("M012", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ConstraintsTestExtensions4.M0(logger, 12); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("M012", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + + logger.Reset(); + ConstraintsTestExtensions5.M0(logger, 12); + Assert.Equal(LogLevel.Debug, logger.LastLogLevel); + Assert.Null(logger.LastException); + Assert.Equal("M012", logger.LastFormattedString); + Assert.Equal(1, logger.CallCount); + } [Fact] public void NestedClassTests() diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs index 917d87cd127f1e..097dcc722d4007 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorEmitterTests.cs @@ -3,9 +3,7 @@ using System; using System.IO; -using System.Reflection; using System.Threading.Tasks; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Text; using SourceGenerators.Tests; using Xunit; @@ -149,9 +147,25 @@ internal class Class2 { } await VerifyAgainstBaselineUsingFile("TestWithNestedClass.generated.txt", testSourceCode); } + [Fact] + public async Task TestBaseline_TestWithFileScopedNamespace_Success() + { + string testSourceCode = @" +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses; + +internal static partial class TestWithDefaultValues +{ + [LoggerMessage] + public static partial void M0(ILogger logger, LogLevel level); +}"; + await VerifyAgainstBaselineUsingFile("TestWithDefaultValues.generated.txt", testSourceCode); + } + private async Task VerifyAgainstBaselineUsingFile(string filename, string testSourceCode) { - string[] expectedLines = await File.ReadAllLinesAsync(Path.Combine("Baselines", filename)).ConfigureAwait(false); + string baseline = await File.ReadAllTextAsync(Path.Combine("Baselines", filename)).ConfigureAwait(false); + string[] expectedLines = baseline.Replace("%VERSION%", typeof(LoggerMessageGenerator).Assembly.GetName().Version?.ToString()) + .Split(Environment.NewLine); var (d, r) = await RoslynTestUtils.RunGenerator( new LoggerMessageGenerator(), diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs index b2fe61084c52ea..3cbcc2e539e02d 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/LoggerMessageGeneratorParserTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -350,6 +351,24 @@ public partial class Nested Assert.Empty(diagnostics); } + [Fact] + public async Task FileScopedNamespaceOK() + { + IReadOnlyList diagnostics = await RunGenerator(@" + using Microsoft.Extensions.Logging; + + namespace MyLibrary; + + internal partial class Logger + { + [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = ""Hello {Name}!"")] + public static partial void Greeting(ILogger logger, string name); + } + "); + + Assert.Empty(diagnostics); + } + [Theory] [InlineData("false")] [InlineData("true")] @@ -380,6 +399,7 @@ public class Object {} public class Void {} public class String {} public struct DateTime {} + public abstract class Attribute {} } namespace System.Collections { @@ -392,10 +412,12 @@ public interface ILogger {} } namespace Microsoft.Extensions.Logging { - public class LoggerMessageAttribute {} + public class LoggerMessageAttribute : System.Attribute {} } partial class C { + [Microsoft.Extensions.Logging.LoggerMessage] + public static partial void Log(ILogger logger); } ", false, includeBaseReferences: false, includeLoggingReferences: false); @@ -584,6 +606,21 @@ partial class C Assert.Equal(DiagnosticDescriptors.LoggingMethodIsGeneric.Id, diagnostics[0].Id); } + [Theory] + [InlineData("ref")] + [InlineData("in")] + public async Task SupportsRefKindsInAndRef(string modifier) + { + IReadOnlyList diagnostics = await RunGenerator(@$" + partial class C + {{ + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = ""Parameter {{P1}}"")] + static partial void M(ILogger logger, {modifier} int p1); + }}"); + + Assert.Empty(diagnostics); + } + [Fact] public async Task Templates() { @@ -656,6 +693,55 @@ static partial class C Assert.Empty(diagnostics); // should fail quietly on broken code } + [Fact] + internal void MultipleTypeDefinitions() + { + // Adding a dependency to an assembly that has internal definitions of public types + // should not result in a collision and break generation. + // Verify usage of the extension GetBestTypeByMetadataName(this Compilation) instead of Compilation.GetTypeByMetadataName(). + var referencedSource = @" + namespace Microsoft.Extensions.Logging + { + internal class LoggerMessageAttribute { } + } + namespace Microsoft.Extensions.Logging + { + internal interface ILogger { } + internal enum LogLevel { } + }"; + + // Compile the referenced assembly first. + Compilation referencedCompilation = CompilationHelper.CreateCompilation(referencedSource); + + // Obtain the image of the referenced assembly. + byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation); + + // Generate the code + string source = @" + namespace Test + { + using Microsoft.Extensions.Logging; + + partial class C + { + [LoggerMessage(EventId = 1, Level = LogLevel.Debug, Message = ""M1"")] + static partial void M1(ILogger logger); + } + }"; + + MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) }; + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + LoggerMessageGenerator generator = new LoggerMessageGenerator(); + + (ImmutableArray diagnostics, ImmutableArray generatedSources) = + RoslynTestUtils.RunGenerator(compilation, generator); + + // Make sure compilation was successful. + Assert.Empty(diagnostics); + Assert.Equal(1, generatedSources.Length); + Assert.Equal(21, generatedSources[0].SourceText.Lines.Count); + } + private static async Task> RunGenerator( string code, bool wrap = true, diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn3.11.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn3.11.Tests.csproj new file mode 100644 index 00000000000000..bb4f032a25357c --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn3.11.Tests.csproj @@ -0,0 +1,13 @@ + + + + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion_3_11) + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests.csproj new file mode 100644 index 00000000000000..1c826c0b30a3f2 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Roslyn4.0.Tests.csproj @@ -0,0 +1,14 @@ + + + + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion) + $(DefineConstants);ROSLYN4_0_OR_GREATER + + + + + + + + + diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Tests.csproj b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.targets similarity index 83% rename from src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Tests.csproj rename to src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.targets index 1e837898edb969..50df6bb7cc044f 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/Microsoft.Extensions.Logging.Generators.targets @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent) @@ -14,9 +14,8 @@ - + - diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/AtSymbolTestExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/AtSymbolTestExtensions.cs new file mode 100644 index 00000000000000..be41f22e5a73a5 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/AtSymbolTestExtensions.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal static partial class AtSymbolTestExtensions + { + [LoggerMessage(EventId = 0, Level = LogLevel.Information, Message = "M0 {event}")] + internal static partial void M0(ILogger logger, string @event); + } +} \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ConstaintsTestExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ConstaintsTestExtensions.cs new file mode 100644 index 00000000000000..7e6f87271b535f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ConstaintsTestExtensions.cs @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + using ConstraintInAnotherNamespace; + namespace UsesConstraintInAnotherNamespace + { + public partial class MessagePrinter + where T : Message + { + public void Print(ILogger logger, T message) + { + Log.Message(logger, message.Text); + } + + internal static partial class Log + { + [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "The message is {Text}.")] + internal static partial void Message(ILogger logger, string? text); + } + } + + public partial class MessagePrinterHasConstraintOnLogClassAndLogMethod + where T : Message + { + public void Print(ILogger logger, T message) + { + Log.Message(logger, message); + } + + internal static partial class Log where U : Message + { + [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "The message is {Text}.")] + internal static partial void Message(ILogger logger, U text); + } + } + } + + internal static partial class ConstraintsTestExtensions + where T : class + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "M0{p0}")] + public static partial void M0(ILogger logger, int p0); + + public static void Foo(T dummy) + { + } + } + + internal static partial class ConstraintsTestExtensions1 + where T : struct + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "M0{p0}")] + public static partial void M0(ILogger logger, int p0); + + public static void Foo(T dummy) + { + } + } + + internal static partial class ConstraintsTestExtensions2 + where T : unmanaged + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "M0{p0}")] + public static partial void M0(ILogger logger, int p0); + + public static void Foo(T dummy) + { + } + } + + internal static partial class ConstraintsTestExtensions3 + where T : new() + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "M0{p0}")] + public static partial void M0(ILogger logger, int p0); + + public static void Foo(T dummy) + { + } + } + + internal static partial class ConstraintsTestExtensions4 + where T : System.Attribute + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "M0{p0}")] + public static partial void M0(ILogger logger, int p0); + + public static void Foo(T dummy) + { + } + } + + internal static partial class ConstraintsTestExtensions5 + where T : notnull + { + [LoggerMessage(EventId = 0, Level = LogLevel.Debug, Message = "M0{p0}")] + public static partial void M0(ILogger logger, int p0); + + public static void Foo(T dummy) + { + } + } +} + +namespace ConstraintInAnotherNamespace +{ + public class Message + { + public string? Text { get; set; } + + public override string ToString() + { + return $"`{Text}`"; + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs index 4b5b6cdbf90a26..ba6b87f6d5308a 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/NestedClassTestsExtensions.cs @@ -3,6 +3,8 @@ namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses { + using NamespaceForABC; + internal static partial class NestedClassTestsExtensions where T : ABC { internal static partial class NestedMiddleParentClass @@ -26,7 +28,6 @@ internal static partial class NestedClass } } } - public class ABC {} public partial struct NestedStruct { @@ -61,3 +62,8 @@ internal static partial class Logger } } } + +namespace NamespaceForABC +{ + public class ABC {} +} \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ParameterTestExtensions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ParameterTestExtensions.cs new file mode 100644 index 00000000000000..f51fc2e62f6a96 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/tests/Microsoft.Extensions.Logging.Generators.Tests/TestClasses/ParameterTestExtensions.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Extensions.Logging.Generators.Tests.TestClasses +{ + internal static partial class ParameterTestExtensions + { + internal struct S + { + public override string ToString() => "Hello from S"; + } + + [LoggerMessage(EventId = 0, Level = LogLevel.Information, Message = "UseInParameter {s}")] + internal static partial void UseInParameter(ILogger logger, in S s); + + [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = "UseRefParameter {s}")] + internal static partial void UseRefParameter(ILogger logger, ref S s); + } +} diff --git a/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.sln b/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.sln index 970154049e48ad..f9d674fdba5679 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Configuration/Microsoft.Extensions.Logging.Configuration.sln @@ -23,8 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{788150B7-B822-4466-A1DC-C875449DE449}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{6D6D8484-D8D0-4FCA-B6FA-B665C629D78F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{C4F75024-EA9D-46C5-B2D9-CAE8FC5EFF38}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{E7035B72-0180-437E-A696-1F0CD8921279}" diff --git a/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.sln b/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.sln index 992cbc4d3929ef..f8e2622773b41e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Console/Microsoft.Extensions.Logging.Console.sln @@ -25,8 +25,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{2E4D0EB0-E34B-4D47-A7F1-E35C696066E8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{D902BAF8-7431-4017-BD56-F4EABE38D7F9}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{9BCECFDA-BF6E-4BD8-BFE2-A25C61F57874}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{6A02D298-6899-4DD0-BFF4-40702BC30BCD}" @@ -65,8 +63,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{BF5E5B5A-AC50-4FF1-AADB-0DFC1AA8E429}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{AD117F41-062A-4158-A17D-3375820A53FA}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{C9F3D8F9-8646-432E-82FC-2E4E8411CFFE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{AB19DE2B-6A14-4CDA-94EF-845BAF293051}" @@ -189,10 +185,6 @@ Global {1B33EC41-F711-4111-8818-FEEBC9A0BD8D}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B33EC41-F711-4111-8818-FEEBC9A0BD8D}.Release|Any CPU.ActiveCfg = Release|Any CPU {1B33EC41-F711-4111-8818-FEEBC9A0BD8D}.Release|Any CPU.Build.0 = Release|Any CPU - {AD117F41-062A-4158-A17D-3375820A53FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AD117F41-062A-4158-A17D-3375820A53FA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AD117F41-062A-4158-A17D-3375820A53FA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AD117F41-062A-4158-A17D-3375820A53FA}.Release|Any CPU.Build.0 = Release|Any CPU {BF5E5B5A-AC50-4FF1-AADB-0DFC1AA8E429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BF5E5B5A-AC50-4FF1-AADB-0DFC1AA8E429}.Debug|Any CPU.Build.0 = Debug|Any CPU {BF5E5B5A-AC50-4FF1-AADB-0DFC1AA8E429}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -259,7 +251,6 @@ Global {F3F1AF4B-963B-4DCC-80AF-11DFEB652D8D} = {F3BAE0A3-1AF5-4F38-ADBE-6FEC99664322} {ED51A791-65BB-4F8B-B76C-769D0663D4A7} = {F3BAE0A3-1AF5-4F38-ADBE-6FEC99664322} {D3E483FC-DF73-4CD8-AFAA-1DA752F49304} = {F3BAE0A3-1AF5-4F38-ADBE-6FEC99664322} - {AD117F41-062A-4158-A17D-3375820A53FA} = {F3BAE0A3-1AF5-4F38-ADBE-6FEC99664322} {BF5E5B5A-AC50-4FF1-AADB-0DFC1AA8E429} = {F3BAE0A3-1AF5-4F38-ADBE-6FEC99664322} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.sln b/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.sln index 255b413c6450bc..99d30d9127f861 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.sln +++ b/src/libraries/Microsoft.Extensions.Logging.Debug/Microsoft.Extensions.Logging.Debug.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{850FBE78-DE29-480D-B4EE-6D260B0341B4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{3FB47333-590F-417A-832D-83CD81BAA4E1}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{16E075F3-372C-4A98-BDAF-FF615B8A9855}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{3DDCFBB7-A438-46BB-9094-A1A39060DD2A}" diff --git a/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.sln b/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.sln index f902c80971692d..15164504862054 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.sln +++ b/src/libraries/Microsoft.Extensions.Logging.EventLog/Microsoft.Extensions.Logging.EventLog.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{62D0B220-DABD-4C56-A0E2-640D74465328}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{AF5C6565-09EE-4E1F-A146-72785C0FF66F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{B1BE2665-7E3F-46FB-BCE1-774D5984F76C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{6C2850C7-56F0-4DCF-BFBF-4365DE2FC439}" diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.sln b/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.sln index 5a6064ddaabe48..a35664f1b47212 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.sln +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/Microsoft.Extensions.Logging.EventSource.sln @@ -13,8 +13,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{7834A5FC-A39B-4435-9D8C-2EEABFFA7A84}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{0C1BD2DA-FA39-458E-8BCB-0D73231C43D3}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{F5B4A3CF-03B5-40A2-BE78-DA6230270113}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{F4A703F8-3D69-4113-A86F-9AD908086092}" @@ -45,8 +43,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{50CC33E5-CB2C-4CFB-9CDE-BBD41B30FB86}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{4BF31DFE-A930-499C-B696-BB1958C08089}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{5A956452-F322-4C4F-8689-D2B425764293}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{5A06587C-82E8-4B40-9C0A-DD06CB986625}" @@ -153,10 +149,6 @@ Global {50CC33E5-CB2C-4CFB-9CDE-BBD41B30FB86}.Debug|Any CPU.Build.0 = Debug|Any CPU {50CC33E5-CB2C-4CFB-9CDE-BBD41B30FB86}.Release|Any CPU.ActiveCfg = Release|Any CPU {50CC33E5-CB2C-4CFB-9CDE-BBD41B30FB86}.Release|Any CPU.Build.0 = Release|Any CPU - {4BF31DFE-A930-499C-B696-BB1958C08089}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4BF31DFE-A930-499C-B696-BB1958C08089}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4BF31DFE-A930-499C-B696-BB1958C08089}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4BF31DFE-A930-499C-B696-BB1958C08089}.Release|Any CPU.Build.0 = Release|Any CPU {EF689C53-9B62-4E17-B412-92FAD527FA59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EF689C53-9B62-4E17-B412-92FAD527FA59}.Debug|Any CPU.Build.0 = Debug|Any CPU {EF689C53-9B62-4E17-B412-92FAD527FA59}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -190,7 +182,6 @@ Global {0C1BD2DA-FA39-458E-8BCB-0D73231C43D3} = {887BF6A4-CB22-4DF4-8E24-A1B267161ECB} {23F45D4C-4E33-4334-A5BF-D34E24165E0B} = {887BF6A4-CB22-4DF4-8E24-A1B267161ECB} {50CC33E5-CB2C-4CFB-9CDE-BBD41B30FB86} = {887BF6A4-CB22-4DF4-8E24-A1B267161ECB} - {4BF31DFE-A930-499C-B696-BB1958C08089} = {887BF6A4-CB22-4DF4-8E24-A1B267161ECB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {67B715CE-2E67-4605-BFB0-CA65F345C3A5} diff --git a/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.sln b/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.sln index bcfcc830a1c42d..0520a0c4137b8b 100644 --- a/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.sln +++ b/src/libraries/Microsoft.Extensions.Logging.TraceSource/Microsoft.Extensions.Logging.TraceSource.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Depend EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.DependencyInjection", "..\Microsoft.Extensions.DependencyInjection\src\Microsoft.Extensions.DependencyInjection.csproj", "{A64CC82B-B781-4469-B009-49A43A0A2A96}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{F4DE0466-D21E-4CAF-9307-999478A64D5B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{367922CE-A24E-4977-89BE-D1F2F678F8B2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{F63AB9DB-6E62-4FEC-BA06-E146615C08AC}" diff --git a/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.sln b/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.sln index 056d8c4141fcaa..99cbfceba7692c 100644 --- a/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.sln +++ b/src/libraries/Microsoft.Extensions.Logging/Microsoft.Extensions.Logging.sln @@ -49,8 +49,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.FileSy EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.FileSystemGlobbing", "..\Microsoft.Extensions.FileSystemGlobbing\src\Microsoft.Extensions.FileSystemGlobbing.csproj", "{7C562B37-19E5-44BE-85D5-15FFA9FAEF5A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{56A5DED2-47C2-4938-931E-B896A6BDDA0D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{5CC86773-7762-4FB7-9B6E-F4002F286AD4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{4BEF5648-8DBF-4E16-B6E6-6F80694E140D}" @@ -113,8 +111,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Security.Permissions EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{B5B30447-25D0-42C0-920A-092247C95664}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{B4313086-0B16-4A80-BA04-964F64745DC2}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{34C22E86-B0A3-457D-B8D9-7CF47AAF2570}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.AccessControl", "..\System.Threading.AccessControl\ref\System.Threading.AccessControl.csproj", "{5FF1A443-F491-428F-9121-51523AA65052}" @@ -229,10 +225,6 @@ Global {7C562B37-19E5-44BE-85D5-15FFA9FAEF5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C562B37-19E5-44BE-85D5-15FFA9FAEF5A}.Release|Any CPU.ActiveCfg = Release|Any CPU {7C562B37-19E5-44BE-85D5-15FFA9FAEF5A}.Release|Any CPU.Build.0 = Release|Any CPU - {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {56A5DED2-47C2-4938-931E-B896A6BDDA0D}.Release|Any CPU.Build.0 = Release|Any CPU {5CC86773-7762-4FB7-9B6E-F4002F286AD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5CC86773-7762-4FB7-9B6E-F4002F286AD4}.Debug|Any CPU.Build.0 = Debug|Any CPU {5CC86773-7762-4FB7-9B6E-F4002F286AD4}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -357,10 +349,6 @@ Global {B5B30447-25D0-42C0-920A-092247C95664}.Debug|Any CPU.Build.0 = Debug|Any CPU {B5B30447-25D0-42C0-920A-092247C95664}.Release|Any CPU.ActiveCfg = Release|Any CPU {B5B30447-25D0-42C0-920A-092247C95664}.Release|Any CPU.Build.0 = Release|Any CPU - {B4313086-0B16-4A80-BA04-964F64745DC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B4313086-0B16-4A80-BA04-964F64745DC2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B4313086-0B16-4A80-BA04-964F64745DC2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B4313086-0B16-4A80-BA04-964F64745DC2}.Release|Any CPU.Build.0 = Release|Any CPU {34C22E86-B0A3-457D-B8D9-7CF47AAF2570}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {34C22E86-B0A3-457D-B8D9-7CF47AAF2570}.Debug|Any CPU.Build.0 = Debug|Any CPU {34C22E86-B0A3-457D-B8D9-7CF47AAF2570}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -409,7 +397,6 @@ Global {5F0CF40F-D54D-4101-94EA-8FE7F9C843CB} = {D8928AB2-2939-4421-90C5-56B789BF93E5} {F61AC077-D30A-4F65-9831-5F9DC23B3561} = {E70034C8-3FE8-4A9E-9D2C-569FB4AE2AD7} {7C562B37-19E5-44BE-85D5-15FFA9FAEF5A} = {D8928AB2-2939-4421-90C5-56B789BF93E5} - {56A5DED2-47C2-4938-931E-B896A6BDDA0D} = {D8928AB2-2939-4421-90C5-56B789BF93E5} {5CC86773-7762-4FB7-9B6E-F4002F286AD4} = {E70034C8-3FE8-4A9E-9D2C-569FB4AE2AD7} {4BEF5648-8DBF-4E16-B6E6-6F80694E140D} = {D8928AB2-2939-4421-90C5-56B789BF93E5} {E68B2719-B7A0-46F4-A5F0-72BB03BF8167} = {E70034C8-3FE8-4A9E-9D2C-569FB4AE2AD7} @@ -441,7 +428,6 @@ Global {04BA3E3C-6979-4792-B19E-C797AD607F42} = {D8928AB2-2939-4421-90C5-56B789BF93E5} {DDE4AAB2-E249-4A1A-A0CB-4C1AF440B620} = {E70034C8-3FE8-4A9E-9D2C-569FB4AE2AD7} {B5B30447-25D0-42C0-920A-092247C95664} = {D8928AB2-2939-4421-90C5-56B789BF93E5} - {B4313086-0B16-4A80-BA04-964F64745DC2} = {D8928AB2-2939-4421-90C5-56B789BF93E5} {34C22E86-B0A3-457D-B8D9-7CF47AAF2570} = {D8928AB2-2939-4421-90C5-56B789BF93E5} {5FF1A443-F491-428F-9121-51523AA65052} = {E70034C8-3FE8-4A9E-9D2C-569FB4AE2AD7} {504464B5-B163-4D6B-A113-52DDC78A401D} = {D8928AB2-2939-4421-90C5-56B789BF93E5} diff --git a/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.sln b/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.sln index 20100a69c0f5a0..8271c101f02c72 100644 --- a/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.sln +++ b/src/libraries/Microsoft.Extensions.Options/Microsoft.Extensions.Options.sln @@ -65,8 +65,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hostin EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Hosting", "..\Microsoft.Extensions.Hosting\src\Microsoft.Extensions.Hosting.csproj", "{6AD51705-102E-4E9D-B62E-6BF19025F3A7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Generators", "..\Microsoft.Extensions.Logging.Abstractions\gen\Microsoft.Extensions.Logging.Generators.csproj", "{0641221C-4409-4805-8CA4-4023809D5AD1}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\ref\Microsoft.Extensions.Logging.Abstractions.csproj", "{EFFB59C1-CAF4-4347-B996-4C773E1AFAA8}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Logging.Abstractions", "..\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj", "{56D37CB2-68A3-42D3-AA0E-416813ABAD8B}" @@ -131,8 +129,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Security.Permissions EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{59D31D62-3BF9-4F4A-9FF7-3A61F297F714}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{850A0E3B-1C09-40EF-8F3E-D61D93663C4E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{D7CEC738-5D2D-4FCB-9268-9650EB01BF31}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Threading.AccessControl", "..\System.Threading.AccessControl\ref\System.Threading.AccessControl.csproj", "{39D50C3D-609B-4B4E-955F-252E469A55C9}" @@ -401,10 +397,6 @@ Global {6F7512BA-9B15-4395-AE05-C546F0770344}.Debug|Any CPU.Build.0 = Debug|Any CPU {6F7512BA-9B15-4395-AE05-C546F0770344}.Release|Any CPU.ActiveCfg = Release|Any CPU {6F7512BA-9B15-4395-AE05-C546F0770344}.Release|Any CPU.Build.0 = Release|Any CPU - {850A0E3B-1C09-40EF-8F3E-D61D93663C4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {850A0E3B-1C09-40EF-8F3E-D61D93663C4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {850A0E3B-1C09-40EF-8F3E-D61D93663C4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {850A0E3B-1C09-40EF-8F3E-D61D93663C4E}.Release|Any CPU.Build.0 = Release|Any CPU {59D31D62-3BF9-4F4A-9FF7-3A61F297F714}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59D31D62-3BF9-4F4A-9FF7-3A61F297F714}.Debug|Any CPU.Build.0 = Debug|Any CPU {59D31D62-3BF9-4F4A-9FF7-3A61F297F714}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -509,7 +501,6 @@ Global {429C9D71-4BBD-489D-9C86-EC240F652008} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} {0641221C-4409-4805-8CA4-4023809D5AD1} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} {9175023F-6982-45CD-B360-C4FC1E145B25} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} - {850A0E3B-1C09-40EF-8F3E-D61D93663C4E} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} {59D31D62-3BF9-4F4A-9FF7-3A61F297F714} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} {B82AF93C-33D7-4B48-B36E-A9873D74601C} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} {99007CDD-4840-4B94-8A8A-FECF72BCEE3F} = {7028EE0A-D314-4F48-91CA-51A1633BC3F4} diff --git a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj index ab3ec6f159302c..57d39f71d4dd60 100644 --- a/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj +++ b/src/libraries/Microsoft.Internal.Runtime.AspNetCore.Transport/src/Microsoft.Internal.Runtime.AspNetCore.Transport.proj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent) false @@ -13,6 +13,8 @@ Internal transport package to provide aspnetcore with the assemblies from dotnet/runtime that make up the Microsoft.AspNetCore.App shared framework. $(NoWarn);NU5131 + true + $(PatchVersion) @@ -20,6 +22,7 @@ - + + diff --git a/src/libraries/Microsoft.Internal.Runtime.WindowsDesktop.Transport/src/Microsoft.Internal.Runtime.WindowsDesktop.Transport.proj b/src/libraries/Microsoft.Internal.Runtime.WindowsDesktop.Transport/src/Microsoft.Internal.Runtime.WindowsDesktop.Transport.proj index fa9dc31e8edfa7..70c1cad7311994 100644 --- a/src/libraries/Microsoft.Internal.Runtime.WindowsDesktop.Transport/src/Microsoft.Internal.Runtime.WindowsDesktop.Transport.proj +++ b/src/libraries/Microsoft.Internal.Runtime.WindowsDesktop.Transport/src/Microsoft.Internal.Runtime.WindowsDesktop.Transport.proj @@ -13,10 +13,13 @@ Internal transport package to provide windowsdesktop with the assemblies from dotnet/runtime that make up the Microsoft.WindowsDesktop.App shared framework. $(NoWarn);NU5131 + true + $(PatchVersion) - - + + diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj index 71cf1e98a1c5c0..da09df45abba5b 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/src/Microsoft.NETCore.Platforms.csproj @@ -1,6 +1,6 @@ - + - $(NetCoreAppToolCurrent);net472 + $(NetCoreAppToolCurrent);$(NetFrameworkToolCurrent) false $(MSBuildProjectName) @@ -19,9 +19,11 @@ $(AdditionalRuntimeIdentifiers);$(OutputRID) + true + 2 - + @@ -44,9 +46,8 @@ - - - + + diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json index 1617ecf4dab272..bf6dfc3c1a1d75 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.compatibility.json @@ -508,6 +508,120 @@ "any", "base" ], + "alpine.3.15": [ + "alpine.3.15", + "alpine.3.14", + "alpine.3.13", + "alpine.3.12", + "alpine.3.11", + "alpine.3.10", + "alpine.3.9", + "alpine.3.8", + "alpine.3.7", + "alpine.3.6", + "alpine", + "linux-musl", + "linux", + "unix", + "any", + "base" + ], + "alpine.3.15-arm": [ + "alpine.3.15-arm", + "alpine.3.15", + "alpine.3.14-arm", + "alpine.3.14", + "alpine.3.13-arm", + "alpine.3.13", + "alpine.3.12-arm", + "alpine.3.12", + "alpine.3.11-arm", + "alpine.3.11", + "alpine.3.10-arm", + "alpine.3.10", + "alpine.3.9-arm", + "alpine.3.9", + "alpine.3.8-arm", + "alpine.3.8", + "alpine.3.7-arm", + "alpine.3.7", + "alpine.3.6-arm", + "alpine.3.6", + "alpine-arm", + "alpine", + "linux-musl-arm", + "linux-musl", + "linux-arm", + "linux", + "unix-arm", + "unix", + "any", + "base" + ], + "alpine.3.15-arm64": [ + "alpine.3.15-arm64", + "alpine.3.15", + "alpine.3.14-arm64", + "alpine.3.14", + "alpine.3.13-arm64", + "alpine.3.13", + "alpine.3.12-arm64", + "alpine.3.12", + "alpine.3.11-arm64", + "alpine.3.11", + "alpine.3.10-arm64", + "alpine.3.10", + "alpine.3.9-arm64", + "alpine.3.9", + "alpine.3.8-arm64", + "alpine.3.8", + "alpine.3.7-arm64", + "alpine.3.7", + "alpine.3.6-arm64", + "alpine.3.6", + "alpine-arm64", + "alpine", + "linux-musl-arm64", + "linux-musl", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "alpine.3.15-x64": [ + "alpine.3.15-x64", + "alpine.3.15", + "alpine.3.14-x64", + "alpine.3.14", + "alpine.3.13-x64", + "alpine.3.13", + "alpine.3.12-x64", + "alpine.3.12", + "alpine.3.11-x64", + "alpine.3.11", + "alpine.3.10-x64", + "alpine.3.10", + "alpine.3.9-x64", + "alpine.3.9", + "alpine.3.8-x64", + "alpine.3.8", + "alpine.3.7-x64", + "alpine.3.7", + "alpine.3.6-x64", + "alpine.3.6", + "alpine-x64", + "alpine", + "linux-musl-x64", + "linux-musl", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "alpine.3.6": [ "alpine.3.6", "alpine", @@ -2883,6 +2997,38 @@ "any", "base" ], + "fedora.36": [ + "fedora.36", + "fedora", + "linux", + "unix", + "any", + "base" + ], + "fedora.36-arm64": [ + "fedora.36-arm64", + "fedora.36", + "fedora-arm64", + "fedora", + "linux-arm64", + "linux", + "unix-arm64", + "unix", + "any", + "base" + ], + "fedora.36-x64": [ + "fedora.36-x64", + "fedora.36", + "fedora-x64", + "fedora", + "linux-x64", + "linux", + "unix-x64", + "unix", + "any", + "base" + ], "freebsd": [ "freebsd", "unix", @@ -5220,6 +5366,73 @@ "any", "base" ], + "osx.12": [ + "osx.12", + "osx.11.0", + "osx.10.16", + "osx.10.15", + "osx.10.14", + "osx.10.13", + "osx.10.12", + "osx.10.11", + "osx.10.10", + "osx", + "unix", + "any", + "base" + ], + "osx.12-arm64": [ + "osx.12-arm64", + "osx.12", + "osx.11.0-arm64", + "osx.11.0", + "osx.10.16-arm64", + "osx.10.16", + "osx.10.15-arm64", + "osx.10.15", + "osx.10.14-arm64", + "osx.10.14", + "osx.10.13-arm64", + "osx.10.13", + "osx.10.12-arm64", + "osx.10.12", + "osx.10.11-arm64", + "osx.10.11", + "osx.10.10-arm64", + "osx.10.10", + "osx-arm64", + "osx", + "unix-arm64", + "unix", + "any", + "base" + ], + "osx.12-x64": [ + "osx.12-x64", + "osx.12", + "osx.11.0-x64", + "osx.11.0", + "osx.10.16-x64", + "osx.10.16", + "osx.10.15-x64", + "osx.10.15", + "osx.10.14-x64", + "osx.10.14", + "osx.10.13-x64", + "osx.10.13", + "osx.10.12-x64", + "osx.10.12", + "osx.10.11-x64", + "osx.10.11", + "osx.10.10-x64", + "osx.10.10", + "osx-x64", + "osx", + "unix-x64", + "unix", + "any", + "base" + ], "rhel": [ "rhel", "linux", diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json index 04e41069e0a6d5..2e6ec616b74201 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtime.json @@ -138,6 +138,29 @@ "alpine.3.13-x64" ] }, + "alpine.3.15": { + "#import": [ + "alpine.3.14" + ] + }, + "alpine.3.15-arm": { + "#import": [ + "alpine.3.15", + "alpine.3.14-arm" + ] + }, + "alpine.3.15-arm64": { + "#import": [ + "alpine.3.15", + "alpine.3.14-arm64" + ] + }, + "alpine.3.15-x64": { + "#import": [ + "alpine.3.15", + "alpine.3.14-x64" + ] + }, "alpine.3.6": { "#import": [ "alpine" @@ -1106,6 +1129,23 @@ "fedora-x64" ] }, + "fedora.36": { + "#import": [ + "fedora" + ] + }, + "fedora.36-arm64": { + "#import": [ + "fedora.36", + "fedora-arm64" + ] + }, + "fedora.36-x64": { + "#import": [ + "fedora.36", + "fedora-x64" + ] + }, "freebsd": { "#import": [ "unix" @@ -2127,6 +2167,23 @@ "osx.10.16-x64" ] }, + "osx.12": { + "#import": [ + "osx.11.0" + ] + }, + "osx.12-arm64": { + "#import": [ + "osx.12", + "osx.11.0-arm64" + ] + }, + "osx.12-x64": { + "#import": [ + "osx.12", + "osx.11.0-x64" + ] + }, "rhel": { "#import": [ "linux" diff --git a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props index 63e342106d82d7..1945bb9af0e5af 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props +++ b/src/libraries/Microsoft.NETCore.Platforms/src/runtimeGroups.props @@ -16,7 +16,7 @@ linux-musl x64;arm;arm64 - 3.6;3.7;3.8;3.9;3.10;3.11;3.12;3.13;3.14 + 3.6;3.7;3.8;3.9;3.10;3.11;3.12;3.13;3.14;3.15 @@ -71,7 +71,7 @@ linux x64;arm64 - 23;24;25;26;27;28;29;30;31;32;33;34;35 + 23;24;25;26;27;28;29;30;31;32;33;34;35;36 false @@ -155,7 +155,7 @@ unix x64;arm64 - 10.10;10.11;10.12;10.13;10.14;10.15;10.16;11.0 + 10.10;10.11;10.12;10.13;10.14;10.15;10.16;11.0;12 diff --git a/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj b/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj index a2a273ed6e042f..00e2f561d82625 100644 --- a/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj +++ b/src/libraries/Microsoft.NETCore.Platforms/tests/Microsoft.NETCore.Platforms.Tests.csproj @@ -4,14 +4,6 @@ true - - - - - - - - @@ -25,4 +17,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/libraries/Microsoft.VisualBasic.Core/Directory.Build.props b/src/libraries/Microsoft.VisualBasic.Core/Directory.Build.props index fac4b55f49cd7d..74f97da58b5daf 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/Directory.Build.props +++ b/src/libraries/Microsoft.VisualBasic.Core/Directory.Build.props @@ -1,7 +1,13 @@  - $([MSBuild]::Add($(MajorVersion), 5)).$(MinorVersion).0.0 + + $([MSBuild]::Add($(MajorVersion), 5)) + $(MajorVersion).$(MinorVersion).0.0 + + 1 Microsoft true diff --git a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb index 9f9140eb846231..3ffcac0d716232 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb +++ b/src/libraries/Microsoft.VisualBasic.Core/src/Microsoft/VisualBasic/FileIO/TextFieldParser.vb @@ -690,16 +690,14 @@ Namespace Microsoft.VisualBasic.FileIO ' No need to slide if we're already at the beginning If m_Position > 0 Then - Dim BufferLength As Integer = m_Buffer.Length - Dim TempArray(BufferLength - 1) As Char - Array.Copy(m_Buffer, m_Position, TempArray, 0, BufferLength - m_Position) + Dim ContentLength As Integer = m_CharsRead - m_Position - ' Fill the rest of the buffer - Dim CharsRead As Integer = m_Reader.Read(TempArray, BufferLength - m_Position, m_Position) - m_CharsRead = m_CharsRead - m_Position + CharsRead + Array.Copy(m_Buffer, m_Position, m_Buffer, 0, ContentLength) + ' Try to fill the rest of the buffer + Dim CharsRead As Integer = m_Reader.Read(m_Buffer, ContentLength, m_Buffer.Length - ContentLength) + m_CharsRead = ContentLength + CharsRead m_Position = 0 - m_Buffer = TempArray Return CharsRead End If @@ -717,27 +715,30 @@ Namespace Microsoft.VisualBasic.FileIO Debug.Assert(m_Buffer IsNot Nothing, "There's no buffer") Debug.Assert(m_Reader IsNot Nothing, "There's no StreamReader") + Debug.Assert(m_Position = 0, "Non-zero position") ' Set cursor m_PeekPosition = m_CharsRead - ' Create a larger buffer and copy our data into it - Dim BufferSize As Integer = m_Buffer.Length + DEFAULT_BUFFER_LENGTH + If m_CharsRead = m_Buffer.Length Then + ' Create a larger buffer and copy our data into it + Dim BufferSize As Integer = m_Buffer.Length + DEFAULT_BUFFER_LENGTH + + ' Make sure the buffer hasn't grown too large + If BufferSize > m_MaxBufferSize Then + Throw GetInvalidOperationException(SR.TextFieldParser_BufferExceededMaxSize) + End If - ' Make sure the buffer hasn't grown too large - If BufferSize > m_MaxBufferSize Then - Throw GetInvalidOperationException(SR.TextFieldParser_BufferExceededMaxSize) + Dim TempArray(BufferSize - 1) As Char + Array.Copy(m_Buffer, TempArray, m_Buffer.Length) + m_Buffer = TempArray End If - Dim TempArray(BufferSize - 1) As Char + Dim CharsRead As Integer = m_Reader.Read(m_Buffer, m_CharsRead, m_Buffer.Length - m_CharsRead) + Debug.Assert(CharsRead <= m_Buffer.Length - m_CharsRead, "We've read more chars than we have space for") - Array.Copy(m_Buffer, TempArray, m_Buffer.Length) - Dim CharsRead As Integer = m_Reader.Read(TempArray, m_Buffer.Length, DEFAULT_BUFFER_LENGTH) - m_Buffer = TempArray m_CharsRead += CharsRead - Debug.Assert(m_CharsRead <= BufferSize, "We've read more chars than we have space for") - Return CharsRead End Function diff --git a/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj b/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj index 3900dc68845302..821cd0397ac1c6 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj +++ b/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft.VisualBasic.Core.Tests.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent);net461 + $(NetCoreAppCurrent);net48-windows @@ -52,7 +52,7 @@ - + diff --git a/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft/VisualBasic/FileIO/TextFieldParserTests.cs b/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft/VisualBasic/FileIO/TextFieldParserTests.cs index a9f0553e54236a..925741dbcc06ee 100644 --- a/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft/VisualBasic/FileIO/TextFieldParserTests.cs +++ b/src/libraries/Microsoft.VisualBasic.Core/tests/Microsoft/VisualBasic/FileIO/TextFieldParserTests.cs @@ -2,7 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Text; using Xunit; namespace Microsoft.VisualBasic.FileIO.Tests @@ -372,5 +375,73 @@ public void UnmatchedQuote_MalformedLineException() Assert.Throws(() => parser.ReadFields()); } } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ReadFields_PartialReadsFromStream_Large(bool fieldsInQuotes) => + ReadFields_PartialReadsFromStream(fieldsInQuotes, 1023); + + [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Framework doesn't properly handle streams frequently returning much less than requested")] + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ReadFields_PartialReadsFromStream_Small(bool fieldsInQuotes) => + ReadFields_PartialReadsFromStream(fieldsInQuotes, 10); + + private void ReadFields_PartialReadsFromStream(bool fieldsInQuotes, int maxCount) + { + // Generate some data + var rand = new Random(42); + string[][] expected = Enumerable + .Range(0, 10_000) + .Select(_ => Enumerable.Range(0, 4).Select(_ => new string('s', rand.Next(0, 10))).ToArray()) + .ToArray(); + + // Write it out + Stream s = new DribbleStream() { MaxCount = maxCount }; + using (var writer = new StreamWriter(s, Encoding.UTF8, 1024, leaveOpen: true)) + { + foreach (string[] line in expected) + { + string separator = ""; + foreach (string part in line) + { + writer.Write(separator); + separator = ","; + if (fieldsInQuotes) writer.Write('"'); + writer.Write(part); + if (fieldsInQuotes) writer.Write('"'); + } + writer.WriteLine(); + } + } + + // Read/parse it back in + s.Position = 0; + using (var parser = new TextFieldParser(s)) + { + parser.TextFieldType = FieldType.Delimited; + parser.SetDelimiters(new[] { "," }); + parser.HasFieldsEnclosedInQuotes = fieldsInQuotes; + + int i = 0; + while (!parser.EndOfData) + { + string[]? actual = parser.ReadFields(); + Assert.Equal(expected[i], actual); + i++; + } + Assert.Equal(expected.Length, i); + } + } + + private sealed class DribbleStream : MemoryStream + { + public int MaxCount { get; set; } = 1; + + public override int Read(byte[] buffer, int offset, int count) => + base.Read(buffer, offset, Math.Min(count, MaxCount)); + } } } diff --git a/src/libraries/Microsoft.Win32.Registry.AccessControl/ref/Microsoft.Win32.Registry.AccessControl.csproj b/src/libraries/Microsoft.Win32.Registry.AccessControl/ref/Microsoft.Win32.Registry.AccessControl.csproj index a0b77d033ab7ec..ab664dfa2e23ee 100644 --- a/src/libraries/Microsoft.Win32.Registry.AccessControl/ref/Microsoft.Win32.Registry.AccessControl.csproj +++ b/src/libraries/Microsoft.Win32.Registry.AccessControl/ref/Microsoft.Win32.Registry.AccessControl.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj b/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj index 881805e1df0ef0..e4466db1d35c82 100644 --- a/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj +++ b/src/libraries/Microsoft.Win32.Registry.AccessControl/src/Microsoft.Win32.Registry.AccessControl.csproj @@ -23,14 +23,18 @@ System.Security.AccessControl.RegistrySecurity + + + + - - + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Win32.SystemEvents/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Win32.SystemEvents/src/CompatibilitySuppressions.xml deleted file mode 100644 index 7a8b03634badf8..00000000000000 --- a/src/libraries/Microsoft.Win32.SystemEvents/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - CP0001 - lib/netstandard2.0/Microsoft.Win32.SystemEvents.dll - lib/net461/Microsoft.Win32.SystemEvents.dll - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj index 4ccc4b8d8845d4..83d774de464216 100644 --- a/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj +++ b/src/libraries/Microsoft.Win32.SystemEvents/tests/Microsoft.Win32.SystemEvents.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent)-windows;net461-windows + $(NetCoreAppCurrent)-windows;net461 true diff --git a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj index ee16f0c79eba8d..0bb569984fb040 100644 --- a/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj +++ b/src/libraries/Microsoft.Windows.Compatibility/src/Microsoft.Windows.Compatibility.csproj @@ -29,6 +29,7 @@ + @@ -50,8 +51,9 @@ System.ServiceModel.Duplex; System.ServiceModel.Http; System.ServiceModel.NetTcp; - System.ServiceModel.Security" - Version="$(ServiceModelVersion)" /> + System.ServiceModel.Security; + System.Web.Services.Description" + Version="$(SystemServiceModelPrimitivesVersion)" /> @@ -63,7 +65,6 @@ - diff --git a/src/libraries/Native/AnyOS/zlib/pal_zlib.c b/src/libraries/Native/AnyOS/zlib/pal_zlib.c index aa4dcdca8a29e8..4d0b05c6629fa5 100644 --- a/src/libraries/Native/AnyOS/zlib/pal_zlib.c +++ b/src/libraries/Native/AnyOS/zlib/pal_zlib.c @@ -7,6 +7,9 @@ #ifdef _WIN32 #define c_static_assert(e) static_assert((e),"") +#endif + +#if defined(_WIN32) || defined(__EMSCRIPTEN__) #include "../../Windows/System.IO.Compression.Native/zlib/zlib.h" #else #include "pal_utilities.h" diff --git a/src/libraries/Native/Unix/CMakeLists.txt b/src/libraries/Native/Unix/CMakeLists.txt index 31cea57a629380..6fae902369c0e8 100644 --- a/src/libraries/Native/Unix/CMakeLists.txt +++ b/src/libraries/Native/Unix/CMakeLists.txt @@ -36,6 +36,8 @@ add_compile_options(-Wno-cast-align) add_compile_options(-Wno-typedef-redefinition) add_compile_options(-Wno-c11-extensions) add_compile_options(-Wno-unknown-pragmas) +add_compile_options(-Wno-unknown-warning-option) +add_compile_options(-Wno-unused-but-set-variable) check_c_compiler_flag(-Wimplicit-fallthrough COMPILER_SUPPORTS_W_IMPLICIT_FALLTHROUGH) if (COMPILER_SUPPORTS_W_IMPLICIT_FALLTHROUGH) @@ -48,6 +50,7 @@ add_compile_options(-g) if(CMAKE_C_COMPILER_ID STREQUAL Clang) add_compile_options(-Wthread-safety) add_compile_options(-Wno-thread-safety-analysis) + add_compile_options(-Wno-reserved-identifier) elseif(CMAKE_C_COMPILER_ID STREQUAL GNU) add_compile_options(-Wno-stringop-truncation) endif() diff --git a/src/libraries/Native/Unix/Common/pal_config.h.in b/src/libraries/Native/Unix/Common/pal_config.h.in index 9a02610534101b..8d0d191d1c73d6 100644 --- a/src/libraries/Native/Unix/Common/pal_config.h.in +++ b/src/libraries/Native/Unix/Common/pal_config.h.in @@ -12,6 +12,7 @@ #cmakedefine01 HAVE_F_FULLFSYNC #cmakedefine01 HAVE_O_CLOEXEC #cmakedefine01 HAVE_GETIFADDRS +#cmakedefine01 HAVE_IFADDRS #cmakedefine01 HAVE_UTSNAME_DOMAINNAME #cmakedefine01 HAVE_STAT64 #cmakedefine01 HAVE_FORK @@ -36,8 +37,7 @@ #cmakedefine01 HAVE_STRLCAT #cmakedefine01 HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP #cmakedefine01 HAVE_POSIX_ADVISE -#cmakedefine01 HAVE_POSIX_FALLOCATE -#cmakedefine01 HAVE_POSIX_FALLOCATE64 +#cmakedefine01 HAVE_FALLOCATE #cmakedefine01 HAVE_PREADV #cmakedefine01 HAVE_PWRITEV #cmakedefine01 PRIORITY_REQUIRES_INT_WHO @@ -78,6 +78,10 @@ #cmakedefine01 HAVE_NETINET_IP_VAR_H #cmakedefine01 HAVE_NETINET_ICMP_VAR_H #cmakedefine01 HAVE_IOS_NET_ROUTE_H +#cmakedefine01 HAVE_IOS_NETINET_IP_VAR_H +#cmakedefine01 HAVE_IOS_NETINET_ICMP_VAR_H +#cmakedefine01 HAVE_IOS_NETINET_TCPFSM_H +#cmakedefine01 HAVE_IOS_NETINET_UDP_VAR_H #cmakedefine01 HAVE_RT_MSGHDR #cmakedefine01 HAVE_RT_MSGHDR2 #cmakedefine01 HAVE_IF_MSGHDR2 @@ -88,6 +92,7 @@ #cmakedefine01 HAVE_NET_IF_ARP_H #cmakedefine01 HAVE_SYS_MNTENT_H #cmakedefine01 HAVE_NET_IFMEDIA_H +#cmakedefine01 HAVE_IOS_NET_IFMEDIA_H #cmakedefine01 HAVE_LINUX_RTNETLINK_H #cmakedefine01 HAVE_LINUX_CAN_H #cmakedefine01 HAVE_GETDOMAINNAME_SIZET diff --git a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h index 92ded52d687245..1ddaff5594aad3 100644 --- a/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h +++ b/src/libraries/Native/Unix/System.Globalization.Native/pal_icushim_internal.h @@ -73,8 +73,8 @@ U_CAPI int32_t U_EXPORT2 ucal_getWindowsTimeZoneID(const UChar* id, int32_t len, PER_FUNCTION_BLOCK(u_tolower, libicuuc, true) \ PER_FUNCTION_BLOCK(u_toupper, libicuuc, true) \ PER_FUNCTION_BLOCK(u_uastrncpy, libicuuc, true) \ - PER_FUNCTION_BLOCK(ubrk_close, libicui18n, true) \ - PER_FUNCTION_BLOCK(ubrk_openRules, libicui18n, true) \ + PER_FUNCTION_BLOCK(ubrk_close, libicuuc, true) \ + PER_FUNCTION_BLOCK(ubrk_openRules, libicuuc, true) \ PER_FUNCTION_BLOCK(ucal_add, libicui18n, true) \ PER_FUNCTION_BLOCK(ucal_close, libicui18n, true) \ PER_FUNCTION_BLOCK(ucal_get, libicui18n, true) \ diff --git a/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt index f68e1acef69b00..89c20051c895cd 100644 --- a/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.IO.Compression.Native/CMakeLists.txt @@ -1,9 +1,5 @@ project(System.IO.Compression.Native C) -if (CLR_CMAKE_TARGET_BROWSER) - add_definitions(-s USE_ZLIB) -endif() - include(${CMAKE_CURRENT_LIST_DIR}/extra_libs.cmake) set(NATIVE_LIBS_EXTRA) @@ -13,7 +9,21 @@ set(NATIVECOMPRESSION_SOURCES ../../AnyOS/zlib/pal_zlib.c ) -if (NOT CLR_CMAKE_TARGET_BROWSER) +if (CLR_CMAKE_TARGET_BROWSER) + set (NATIVECOMPRESSION_SOURCES + ${NATIVECOMPRESSION_SOURCES} + ../../Windows/System.IO.Compression.Native/zlib/adler32.c + ../../Windows/System.IO.Compression.Native/zlib/compress.c + ../../Windows/System.IO.Compression.Native/zlib/crc32.c + ../../Windows/System.IO.Compression.Native/zlib/deflate.c + ../../Windows/System.IO.Compression.Native/zlib/inffast.c + ../../Windows/System.IO.Compression.Native/zlib/inflate.c + ../../Windows/System.IO.Compression.Native/zlib/inftrees.c + ../../Windows/System.IO.Compression.Native/zlib/trees.c + ../../Windows/System.IO.Compression.Native/zlib/zutil.c + ) + set_source_files_properties(${NATIVECOMPRESSION_SOURCES} PROPERTIES COMPILE_FLAGS -Wno-implicit-fallthrough) +else() #Include Brotli include files include_directories("../../AnyOS/brotli/include") diff --git a/src/libraries/Native/Unix/System.Native/CMakeLists.txt b/src/libraries/Native/Unix/System.Native/CMakeLists.txt index a28952750b3ef9..188ca5fc6bde86 100644 --- a/src/libraries/Native/Unix/System.Native/CMakeLists.txt +++ b/src/libraries/Native/Unix/System.Native/CMakeLists.txt @@ -40,6 +40,12 @@ else() list (APPEND NATIVE_SOURCES pal_autoreleasepool.c) endif() +if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) + list (APPEND NATIVE_SOURCES pal_environment.m) +else() + list (APPEND NATIVE_SOURCES pal_environment.c) +endif() + if (CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) set(NATIVE_SOURCES ${NATIVE_SOURCES} pal_log.m diff --git a/src/libraries/Native/Unix/System.Native/entrypoints.c b/src/libraries/Native/Unix/System.Native/entrypoints.c index c8b678ec08340b..702ead88e6d7e2 100644 --- a/src/libraries/Native/Unix/System.Native/entrypoints.c +++ b/src/libraries/Native/Unix/System.Native/entrypoints.c @@ -7,6 +7,7 @@ #include "pal_autoreleasepool.h" #include "pal_console.h" #include "pal_datetime.h" +#include "pal_environment.h" #include "pal_errno.h" #include "pal_interfaceaddresses.h" #include "pal_io.h" @@ -91,7 +92,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_FTruncate) DllImportEntry(SystemNative_Poll) DllImportEntry(SystemNative_PosixFAdvise) - DllImportEntry(SystemNative_PosixFAllocate) + DllImportEntry(SystemNative_FAllocate) DllImportEntry(SystemNative_Read) DllImportEntry(SystemNative_ReadLink) DllImportEntry(SystemNative_Rename) @@ -218,6 +219,7 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_GetOSArchitecture) DllImportEntry(SystemNative_GetProcessArchitecture) DllImportEntry(SystemNative_SearchPath) + DllImportEntry(SystemNative_SearchPath_TempDirectory) DllImportEntry(SystemNative_RegisterForSigChld) DllImportEntry(SystemNative_SetDelayedSigChildConsoleConfigurationHandler) DllImportEntry(SystemNative_SetTerminalInvalidationHandler) @@ -257,6 +259,9 @@ static const Entry s_sysNative[] = DllImportEntry(SystemNative_SetPosixSignalHandler) DllImportEntry(SystemNative_GetPlatformSignalNumber) DllImportEntry(SystemNative_GetGroups) + DllImportEntry(SystemNative_GetEnv) + DllImportEntry(SystemNative_GetEnviron) + DllImportEntry(SystemNative_FreeEnviron) }; EXTERN_C const void* SystemResolveDllImport(const char* name); diff --git a/src/libraries/Native/Unix/System.Native/ios/net/if_media.h b/src/libraries/Native/Unix/System.Native/ios/net/if_media.h new file mode 100644 index 00000000000000..e7e1a838d420fc --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/ios/net/if_media.h @@ -0,0 +1,589 @@ +/* + * Copyright (c) 2000-2019 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* $NetBSD: if_media.h,v 1.3 1997/03/26 01:19:27 thorpej Exp $ */ +/* $FreeBSD: src/sys/net/if_media.h,v 1.9.2.1 2001/07/04 00:12:38 brooks Exp $ */ + +/* + * Copyright (c) 1997 + * Jonathan Stone and Jason R. Thorpe. All rights reserved. + * + * This software is derived from information provided by Matt Thomas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jonathan Stone + * and Jason R. Thorpe for the NetBSD Project. + * 4. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NET_IF_MEDIA_H_ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#define _NET_IF_MEDIA_H_ +#pragma clang diagnostic pop +#ifndef DRIVERKIT +#include +#endif /* DRIVERKIT */ + +/* + * Prototypes and definitions for BSD/OS-compatible network interface + * media selection. + * + * Where it is safe to do so, this code strays slightly from the BSD/OS + * design. Software which uses the API (device drivers, basically) + * shouldn't notice any difference. + * + * Many thanks to Matt Thomas for providing the information necessary + * to implement this interface. + */ + +#ifdef KERNEL_PRIVATE +/* sigh; some modules are lazy and thus rely on this */ +#include +#endif /* KERNEL_PRIVATE */ + +/* + * if_media Options word: + * Bits Use + * ---- ------- + * 0-4 Media variant + * 5-7 Media type + * 8-15 Type specific options + * 16-19 Extended media variant bits + * 20-27 Shared (global) options + * 28-31 Instance + */ + +/* + * Ethernet + * + * In order to use more than 31 subtypes, Ethernet uses the extended media + * variant bits + * + * The extended media variant bits are not backward compatible so they + * must not be used by kernel extensions like ifnet and drivers that + * are to be deployed on older system versions + */ +#define IFM_X(x) IFM_X_SUBTYPE(x) /* internal shorthand */ + +#define IFM_ETHER 0x00000020 +#define IFM_10_T 3 /* 10BaseT - RJ45 */ +#define IFM_10_2 4 /* 10Base2 - Thinnet */ +#define IFM_10_5 5 /* 10Base5 - AUI */ +#define IFM_100_TX 6 /* 100BaseTX - RJ45 */ +#define IFM_100_FX 7 /* 100BaseFX - Fiber */ +#define IFM_100_T4 8 /* 100BaseT4 - 4 pair cat 3 */ +#define IFM_100_VG 9 /* 100VG-AnyLAN */ +#define IFM_100_T2 10 /* 100BaseT2 */ +#define IFM_1000_SX 11 /* 1000BaseSX - multi-mode fiber */ +#define IFM_10_STP 12 /* 10BaseT over shielded TP */ +#define IFM_10_FL 13 /* 10baseFL - Fiber */ +#define IFM_1000_LX 14 /* 1000baseLX - single-mode fiber */ +#define IFM_1000_CX 15 /* 1000baseCX - 150ohm STP */ +#define IFM_1000_T 16 /* 1000baseT - 4 pair cat 5 */ +#ifdef PRIVATE +#define IFM_1000_TX IFM_1000_T /* For compatibility */ +#endif /* PRIVATE */ +#define IFM_HPNA_1 17 /* HomePNA 1.0 (1Mb/s) */ +#define IFM_10G_SR 18 /* 10GbaseSR - multi-mode fiber */ +#define IFM_10G_LR 19 /* 10GbaseLR - single-mode fiber */ +#define IFM_10G_CX4 20 /* 10GbaseCX4 - copper */ +#define IFM_10G_T 21 /* 10GbaseT - 4 pair cat 6 */ +#define IFM_2500_T 22 /* 2500baseT - 4 pair cat 5 */ +#define IFM_5000_T 23 /* 5000baseT - 4 pair cat 5 */ +#define IFM_1000_CX_SGMII 24 /* 1000Base-CX-SGMII */ +#define IFM_1000_KX 25 /* 1000Base-KX backplane */ +#define IFM_10G_KX4 26 /* 10GBase-KX4 backplane */ +#define IFM_10G_KR 27 /* 10GBase-KR backplane */ +#define IFM_10G_CR1 28 /* 10GBase-CR1 Twinax splitter */ +#define IFM_10G_ER 29 /* 10GBase-ER */ +#define IFM_20G_KR2 30 /* 20GBase-KR2 backplane */ +#define IFM_OTHER 31 /* Other: one of the following */ + +/* following types are not visible to old binaries using the low bits of IFM_TMASK */ +#define IFM_2500_SX IFM_X(32) /* 2500BaseSX - multi-mode fiber */ +#define IFM_10G_TWINAX IFM_X(33) /* 10GBase Twinax copper */ +#define IFM_10G_TWINAX_LONG IFM_X(34) /* 10GBase Twinax Long copper */ +#define IFM_10G_LRM IFM_X(35) /* 10GBase-LRM 850nm Multi-mode */ +#define IFM_2500_KX IFM_X(36) /* 2500Base-KX backplane */ +#define IFM_40G_CR4 IFM_X(37) /* 40GBase-CR4 */ +#define IFM_40G_SR4 IFM_X(38) /* 40GBase-SR4 */ +#define IFM_50G_PCIE IFM_X(39) /* 50G Ethernet over PCIE */ +#define IFM_25G_PCIE IFM_X(40) /* 25G Ethernet over PCIE */ +#define IFM_1000_SGMII IFM_X(41) /* 1G media interface */ +#define IFM_10G_SFI IFM_X(42) /* 10G media interface */ +#define IFM_40G_XLPPI IFM_X(43) /* 40G media interface */ +#define IFM_40G_LR4 IFM_X(44) /* 40GBase-LR4 */ +#define IFM_40G_KR4 IFM_X(45) /* 40GBase-KR4 */ +#define IFM_100G_CR4 IFM_X(47) /* 100GBase-CR4 */ +#define IFM_100G_SR4 IFM_X(48) /* 100GBase-SR4 */ +#define IFM_100G_KR4 IFM_X(49) /* 100GBase-KR4 */ +#define IFM_100G_LR4 IFM_X(50) /* 100GBase-LR4 */ +#define IFM_56G_R4 IFM_X(51) /* 56GBase-R4 */ +#define IFM_100_T IFM_X(52) /* 100BaseT - RJ45 */ +#define IFM_25G_CR IFM_X(53) /* 25GBase-CR */ +#define IFM_25G_KR IFM_X(54) /* 25GBase-KR */ +#define IFM_25G_SR IFM_X(55) /* 25GBase-SR */ +#define IFM_50G_CR2 IFM_X(56) /* 50GBase-CR2 */ +#define IFM_50G_KR2 IFM_X(57) /* 50GBase-KR2 */ +#define IFM_25G_LR IFM_X(58) /* 25GBase-LR */ +#define IFM_10G_AOC IFM_X(59) /* 10G active optical cable */ +#define IFM_25G_ACC IFM_X(60) /* 25G active copper cable */ +#define IFM_25G_AOC IFM_X(61) /* 25G active optical cable */ +#define IFM_100_SGMII IFM_X(62) /* 100M media interface */ +#define IFM_2500_X IFM_X(63) /* 2500BaseX */ +#define IFM_5000_KR IFM_X(64) /* 5GBase-KR backplane */ +#define IFM_25G_T IFM_X(65) /* 25GBase-T - RJ45 */ +#define IFM_25G_CR_S IFM_X(66) /* 25GBase-CR (short) */ +#define IFM_25G_CR1 IFM_X(67) /* 25GBase-CR1 DA cable */ +#define IFM_25G_KR_S IFM_X(68) /* 25GBase-KR (short) */ +#define IFM_5000_KR_S IFM_X(69) /* 5GBase-KR backplane (short) */ +#define IFM_5000_KR1 IFM_X(70) /* 5GBase-KR backplane */ +#define IFM_25G_AUI IFM_X(71) /* 25G-AUI-C2C (chip to chip) */ +#define IFM_40G_XLAUI IFM_X(72) /* 40G-XLAUI */ +#define IFM_40G_XLAUI_AC IFM_X(73) /* 40G active copper/optical */ +#define IFM_40G_ER4 IFM_X(74) /* 40GBase-ER4 */ +#define IFM_50G_SR2 IFM_X(75) /* 50GBase-SR2 */ +#define IFM_50G_LR2 IFM_X(76) /* 50GBase-LR2 */ +#define IFM_50G_LAUI2_AC IFM_X(77) /* 50G active copper/optical */ +#define IFM_50G_LAUI2 IFM_X(78) /* 50G-LAUI2 */ +#define IFM_50G_AUI2_AC IFM_X(79) /* 50G active copper/optical */ +#define IFM_50G_AUI2 IFM_X(80) /* 50G-AUI2 */ +#define IFM_50G_CP IFM_X(81) /* 50GBase-CP */ +#define IFM_50G_SR IFM_X(82) /* 50GBase-SR */ +#define IFM_50G_LR IFM_X(83) /* 50GBase-LR */ +#define IFM_50G_FR IFM_X(84) /* 50GBase-FR */ +#define IFM_50G_KR_PAM4 IFM_X(85) /* 50GBase-KR PAM4 */ +#define IFM_25G_KR1 IFM_X(86) /* 25GBase-KR1 */ +#define IFM_50G_AUI1_AC IFM_X(87) /* 50G active copper/optical */ +#define IFM_50G_AUI1 IFM_X(88) /* 50G-AUI1 */ +#define IFM_100G_CAUI4_AC IFM_X(89) /* 100G-CAUI4 active copper/optical */ +#define IFM_100G_CAUI4 IFM_X(90) /* 100G-CAUI4 */ +#define IFM_100G_AUI4_AC IFM_X(91) /* 100G-AUI4 active copper/optical */ +#define IFM_100G_AUI4 IFM_X(92) /* 100G-AUI4 */ +#define IFM_100G_CR_PAM4 IFM_X(93) /* 100GBase-CR PAM4 */ +#define IFM_100G_KR_PAM4 IFM_X(94) /* 100GBase-CR PAM4 */ +#define IFM_100G_CP2 IFM_X(95) /* 100GBase-CP2 */ +#define IFM_100G_SR2 IFM_X(96) /* 100GBase-SR2 */ +#define IFM_100G_DR IFM_X(97) /* 100GBase-DR */ +#define IFM_100G_KR2_PAM4 IFM_X(98) /* 100GBase-KR2 PAM4 */ +#define IFM_100G_CAUI2_AC IFM_X(99) /* 100G-CAUI2 active copper/optical */ +#define IFM_100G_CAUI2 IFM_X(100) /* 100G-CAUI2 */ +#define IFM_100G_AUI2_AC IFM_X(101) /* 100G-AUI2 active copper/optical */ +#define IFM_100G_AUI2 IFM_X(102) /* 100G-AUI2 */ +#define IFM_200G_CR4_PAM4 IFM_X(103) /* 200GBase-CR4 PAM4 */ +#define IFM_200G_SR4 IFM_X(104) /* 200GBase-SR4 */ +#define IFM_200G_FR4 IFM_X(105) /* 200GBase-FR4 */ +#define IFM_200G_LR4 IFM_X(106) /* 200GBase-LR4 */ +#define IFM_200G_DR4 IFM_X(107) /* 200GBase-DR4 */ +#define IFM_200G_KR4_PAM4 IFM_X(108) /* 200GBase-KR4 PAM4 */ +#define IFM_200G_AUI4_AC IFM_X(109) /* 200G-AUI4 active copper/optical */ +#define IFM_200G_AUI4 IFM_X(110) /* 200G-AUI4 */ +#define IFM_200G_AUI8_AC IFM_X(111) /* 200G-AUI8 active copper/optical */ +#define IFM_200G_AUI8 IFM_X(112) /* 200G-AUI8 */ +#define IFM_400G_FR8 IFM_X(113) /* 400GBase-FR8 */ +#define IFM_400G_LR8 IFM_X(114) /* 400GBase-LR8 */ +#define IFM_400G_DR4 IFM_X(115) /* 400GBase-DR4 */ +#define IFM_400G_AUI8_AC IFM_X(116) /* 400G-AUI8 active copper/optical */ +#define IFM_400G_AUI8 IFM_X(117) /* 400G-AUI8 */ + +/* + * Token ring + */ +#define IFM_TOKEN 0x00000040 +#define IFM_TOK_STP4 3 /* Shielded twisted pair 4m - DB9 */ +#define IFM_TOK_STP16 4 /* Shielded twisted pair 16m - DB9 */ +#define IFM_TOK_UTP4 5 /* Unshielded twisted pair 4m - RJ45 */ +#define IFM_TOK_UTP16 6 /* Unshielded twisted pair 16m - RJ45 */ +#define IFM_TOK_STP100 7 /* Shielded twisted pair 100m - DB9 */ +#define IFM_TOK_UTP100 8 /* Unshielded twisted pair 100m - RJ45 */ +#define IFM_TOK_ETR 0x00000200 /* Early token release */ +#define IFM_TOK_SRCRT 0x00000400 /* Enable source routing features */ +#define IFM_TOK_ALLR 0x00000800 /* All routes / Single route bcast */ +#define IFM_TOK_DTR 0x00002000 /* Dedicated token ring */ +#define IFM_TOK_CLASSIC 0x00004000 /* Classic token ring */ +#define IFM_TOK_AUTO 0x00008000 /* Automatic Dedicate/Classic token ring */ + +/* + * FDDI + */ +#define IFM_FDDI 0x00000060 +#define IFM_FDDI_SMF 3 /* Single-mode fiber */ +#define IFM_FDDI_MMF 4 /* Multi-mode fiber */ +#define IFM_FDDI_UTP 5 /* CDDI / UTP */ +#define IFM_FDDI_DA 0x00000100 /* Dual attach / single attach */ + +/* + * IEEE 802.11 Wireless + */ +#define IFM_IEEE80211 0x00000080 +#define IFM_IEEE80211_FH1 3 /* Frequency Hopping 1Mbps */ +#define IFM_IEEE80211_FH2 4 /* Frequency Hopping 2Mbps */ +#define IFM_IEEE80211_DS2 5 /* Direct Sequence 2Mbps */ +#define IFM_IEEE80211_DS5 6 /* Direct Sequence 5Mbps*/ +#define IFM_IEEE80211_DS11 7 /* Direct Sequence 11Mbps*/ +#define IFM_IEEE80211_DS1 8 /* Direct Sequence 1Mbps */ +#define IFM_IEEE80211_DS22 9 /* Direct Sequence 22Mbps */ +#define IFM_IEEE80211_ADHOC 0x00000100 /* Operate in Adhoc mode */ + +/* + * Shared media sub-types + */ +#define IFM_AUTO 0 /* Autoselect best media */ +#define IFM_MANUAL 1 /* Jumper/dipswitch selects media */ +#define IFM_NONE 2 /* Deselect all media */ + +/* + * Shared options + */ +#define IFM_FDX 0x00100000 /* Force full duplex */ +#define IFM_HDX 0x00200000 /* Force half duplex */ +#define IFM_FLOW 0x00400000 /* enable hardware flow control */ +#define IFM_EEE 0x00800000 /* Support energy efficient ethernet */ +#define IFM_FLAG0 0x01000000 /* Driver defined flag */ +#define IFM_FLAG1 0x02000000 /* Driver defined flag */ +#define IFM_FLAG2 0x04000000 /* Driver defined flag */ +#define IFM_LOOP 0x08000000 /* Put hardware in loopback */ + +/* + * Macros to access bits of extended media sub-types (media variants) + */ +#define IFM_TMASK_COMPAT 0x0000001f /* Lower bits of media sub-type */ +#define IFM_TMASK_EXT 0x000f0000 /* For extended media sub-type */ +#define IFM_TMASK_EXT_SHIFT 11 /* to extract high bits */ +#define IFM_X_SUBTYPE(x) (((x) & IFM_TMASK_COMPAT) | \ + (((x) & (IFM_TMASK_EXT >> IFM_TMASK_EXT_SHIFT)) << IFM_TMASK_EXT_SHIFT)) + +/* + * Masks + */ +#define IFM_NMASK 0x000000e0 /* Network type */ +#define IFM_TMASK (IFM_TMASK_COMPAT|IFM_TMASK_EXT) /* Media sub-type */ +#define IFM_IMASK 0xf0000000 /* Instance */ +#define IFM_ISHIFT 28 /* Instance shift */ +#define IFM_OMASK 0x0000ff00 /* Type specific options */ +#define IFM_GMASK 0x0ff00000 /* Global options */ + +/* + * Status bits + */ +#define IFM_AVALID 0x00000001 /* Active bit valid */ +#define IFM_ACTIVE 0x00000002 /* Interface attached to working net */ +#define IFM_WAKESAMENET 0x00000004 /* No link transition while asleep */ + +/* + * Macros to extract various bits of information from the media word. + */ +#define IFM_TYPE(x) ((x) & IFM_NMASK) +#define IFM_SUBTYPE(x) ((x) & IFM_TMASK) +#define IFM_TYPE_OPTIONS(x) ((x) & IFM_OMASK) +#define IFM_INST(x) (((x) & IFM_IMASK) >> IFM_ISHIFT) +#define IFM_OPTIONS(x) ((x) & (IFM_OMASK|IFM_GMASK)) + +#define IFM_INST_MAX IFM_INST(IFM_IMASK) + +/* + * Macro to create a media word. + */ +#define IFM_MAKEWORD(type, subtype, options, instance) \ + ((type) | (subtype) | (options) | ((instance) << IFM_ISHIFT)) + +/* + * NetBSD extension not defined in the BSDI API. This is used in various + * places to get the canonical description for a given type/subtype. + * + * NOTE: all but the top-level type descriptions must contain NO whitespace! + * Otherwise, parsing these in ifconfig(8) would be a nightmare. + */ +struct ifmedia_description { + int ifmt_word; /* word value; may be masked */ + const char *ifmt_string; /* description */ +}; + +#define IFM_TYPE_DESCRIPTIONS { \ + { IFM_ETHER, "Ethernet" }, \ + { IFM_TOKEN, "Token ring" }, \ + { IFM_FDDI, "FDDI" }, \ + { IFM_IEEE80211, "IEEE802.11" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_ETHERNET_DESCRIPTIONS { \ + { IFM_10_T, "10baseT/UTP" }, \ + { IFM_10_2, "10base2/BNC" }, \ + { IFM_10_5, "10base5/AUI" }, \ + { IFM_100_TX, "100baseTX" }, \ + { IFM_100_FX, "100baseFX" }, \ + { IFM_100_T4, "100baseT4" }, \ + { IFM_100_VG, "100baseVG" }, \ + { IFM_100_T2, "100baseT2" }, \ + { IFM_10_STP, "10baseSTP" }, \ + { IFM_10_FL, "10baseFL" }, \ + { IFM_1000_SX, "1000baseSX" }, \ + { IFM_1000_LX, "1000baseLX" }, \ + { IFM_1000_CX, "1000baseCX" }, \ + { IFM_1000_T, "1000baseT" }, \ + { IFM_HPNA_1, "homePNA" }, \ + { IFM_10G_LR, "10Gbase-LR" }, \ + { IFM_10G_SR, "10Gbase-SR" }, \ + { IFM_10G_CX4, "10Gbase-CX4" }, \ + { IFM_2500_SX, "2500BaseSX" }, \ + { IFM_10G_LRM, "10Gbase-LRM" }, \ + { IFM_10G_TWINAX, "10Gbase-Twinax" }, \ + { IFM_10G_TWINAX_LONG, "10Gbase-Twinax-Long" }, \ + { IFM_10G_T, "10Gbase-T" }, \ + { IFM_40G_CR4, "40Gbase-CR4" }, \ + { IFM_40G_SR4, "40Gbase-SR4" }, \ + { IFM_40G_LR4, "40Gbase-LR4" }, \ + { IFM_1000_KX, "1000Base-KX" }, \ + { IFM_OTHER, "Other" }, \ + { IFM_10G_KX4, "10GBase-KX4" }, \ + { IFM_10G_KR, "10GBase-KR" }, \ + { IFM_10G_CR1, "10GBase-CR1" }, \ + { IFM_20G_KR2, "20GBase-KR2" }, \ + { IFM_2500_KX, "2500Base-KX" }, \ + { IFM_2500_T, "2500Base-T" }, \ + { IFM_5000_T, "5000Base-T" }, \ + { IFM_50G_PCIE, "PCIExpress-50G" }, \ + { IFM_25G_PCIE, "PCIExpress-25G" }, \ + { IFM_1000_SGMII, "1000Base-SGMII" }, \ + { IFM_10G_SFI, "10GBase-SFI" }, \ + { IFM_40G_XLPPI, "40GBase-XLPPI" }, \ + { IFM_1000_CX_SGMII, "1000Base-CX-SGMII" }, \ + { IFM_40G_KR4, "40GBase-KR4" }, \ + { IFM_10G_ER, "10GBase-ER" }, \ + { IFM_100G_CR4, "100GBase-CR4" }, \ + { IFM_100G_SR4, "100GBase-SR4" }, \ + { IFM_100G_KR4, "100GBase-KR4" }, \ + { IFM_100G_LR4, "100GBase-LR4" }, \ + { IFM_56G_R4, "56GBase-R4" }, \ + { IFM_100_T, "100BaseT" }, \ + { IFM_25G_CR, "25GBase-CR" }, \ + { IFM_25G_KR, "25GBase-KR" }, \ + { IFM_25G_SR, "25GBase-SR" }, \ + { IFM_50G_CR2, "50GBase-CR2" }, \ + { IFM_50G_KR2, "50GBase-KR2" }, \ + { IFM_25G_LR, "25GBase-LR" }, \ + { IFM_10G_AOC, "10GBase-AOC" }, \ + { IFM_25G_ACC, "25GBase-ACC" }, \ + { IFM_25G_AOC, "25GBase-AOC" }, \ + { IFM_100_SGMII, "100M-SGMII" }, \ + { IFM_2500_X, "2500Base-X" }, \ + { IFM_5000_KR, "5000Base-KR" }, \ + { IFM_25G_T, "25GBase-T" }, \ + { IFM_25G_CR_S, "25GBase-CR-S" }, \ + { IFM_25G_CR1, "25GBase-CR1" }, \ + { IFM_25G_KR_S, "25GBase-KR-S" }, \ + { IFM_5000_KR_S, "5000Base-KR-S" }, \ + { IFM_5000_KR1, "5000Base-KR1" }, \ + { IFM_25G_AUI, "25G-AUI" }, \ + { IFM_40G_XLAUI, "40G-XLAUI" }, \ + { IFM_40G_XLAUI_AC, "40G-XLAUI-AC" }, \ + { IFM_40G_ER4, "40GBase-ER4" }, \ + { IFM_50G_SR2, "50GBase-SR2" }, \ + { IFM_50G_LR2, "50GBase-LR2" }, \ + { IFM_50G_LAUI2_AC, "50G-LAUI2-AC" }, \ + { IFM_50G_LAUI2, "50G-LAUI2" }, \ + { IFM_50G_AUI2_AC, "50G-AUI2-AC" }, \ + { IFM_50G_AUI2, "50G-AUI2" }, \ + { IFM_50G_CP, "50GBase-CP" }, \ + { IFM_50G_SR, "50GBase-SR" }, \ + { IFM_50G_LR, "50GBase-LR" }, \ + { IFM_50G_FR, "50GBase-FR" }, \ + { IFM_50G_KR_PAM4, "50GBase-KR-PAM4" }, \ + { IFM_25G_KR1, "25GBase-KR1" }, \ + { IFM_50G_AUI1_AC, "50G-AUI1-AC" }, \ + { IFM_50G_AUI1, "50G-AUI1" }, \ + { IFM_100G_CAUI4_AC, "100G-CAUI4-AC" }, \ + { IFM_100G_CAUI4, "100G-CAUI4" }, \ + { IFM_100G_AUI4_AC, "100G-AUI4-AC" }, \ + { IFM_100G_AUI4, "100G-AUI4" }, \ + { IFM_100G_CR_PAM4, "100GBase-CR-PAM4" }, \ + { IFM_100G_KR_PAM4, "100GBase-KR-PAM4" }, \ + { IFM_100G_CP2, "100GBase-CP2" }, \ + { IFM_100G_SR2, "100GBase-SR2" }, \ + { IFM_100G_DR, "100GBase-DR" }, \ + { IFM_100G_KR2_PAM4, "100GBase-KR2-PAM4" }, \ + { IFM_100G_CAUI2_AC, "100G-CAUI2-AC" }, \ + { IFM_100G_CAUI2, "100G-CAUI2" }, \ + { IFM_100G_AUI2_AC, "100G-AUI2-AC" }, \ + { IFM_100G_AUI2, "100G-AUI2" }, \ + { IFM_200G_CR4_PAM4, "200GBase-CR4-PAM4" }, \ + { IFM_200G_SR4, "200GBase-SR4" }, \ + { IFM_200G_FR4, "200GBase-FR4" }, \ + { IFM_200G_LR4, "200GBase-LR4" }, \ + { IFM_200G_DR4, "200GBase-DR4" }, \ + { IFM_200G_KR4_PAM4, "200GBase-KR4-PAM4" }, \ + { IFM_200G_AUI4_AC, "200G-AUI4-AC" }, \ + { IFM_200G_AUI4, "200G-AUI4" }, \ + { IFM_200G_AUI8_AC, "200G-AUI8-AC" }, \ + { IFM_200G_AUI8, "200G-AUI8" }, \ + { IFM_400G_FR8, "400GBase-FR8" }, \ + { IFM_400G_LR8, "400GBase-LR8" }, \ + { IFM_400G_DR4, "400GBase-DR4" }, \ + { IFM_400G_AUI8_AC, "400G-AUI8-AC" }, \ + { IFM_400G_AUI8, "400G-AUI8" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_ETHERNET_ALIASES { \ + { IFM_10_T, "UTP" }, \ + { IFM_10_T, "10UTP" }, \ + { IFM_10_2, "BNC" }, \ + { IFM_10_2, "10BNC" }, \ + { IFM_10_5, "AUI" }, \ + { IFM_10_5, "10AUI" }, \ + { IFM_100_TX, "100TX" }, \ + { IFM_100_FX, "100FX" }, \ + { IFM_100_T4, "100T4" }, \ + { IFM_100_VG, "100VG" }, \ + { IFM_100_T2, "100T2" }, \ + { IFM_1000_SX, "1000SX" }, \ + { IFM_10_STP, "STP" }, \ + { IFM_10_STP, "10STP" }, \ + { IFM_10_FL, "FL" }, \ + { IFM_10_FL, "10FL" }, \ + { IFM_1000_LX, "1000LX" }, \ + { IFM_1000_CX, "1000CX" }, \ + { IFM_1000_T, "1000T" }, \ + { IFM_HPNA_1, "HPNA1" }, \ + { IFM_10G_SR, "10GSR" }, \ + { IFM_10G_LR, "10GLR" }, \ + { IFM_10G_CX4, "10GCX4" }, \ + { IFM_10G_T, "10GT" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS { \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_TOKENRING_DESCRIPTIONS { \ + { IFM_TOK_STP4, "DB9/4Mbit" }, \ + { IFM_TOK_STP16, "DB9/16Mbit" }, \ + { IFM_TOK_UTP4, "UTP/4Mbit" }, \ + { IFM_TOK_UTP16, "UTP/16Mbit" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_TOKENRING_ALIASES { \ + { IFM_TOK_STP4, "4STP" }, \ + { IFM_TOK_STP16, "16STP" }, \ + { IFM_TOK_UTP4, "4UTP" }, \ + { IFM_TOK_UTP16, "16UTP" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS { \ + { IFM_TOK_ETR, "EarlyTokenRelease" }, \ + { IFM_TOK_SRCRT, "SourceRouting" }, \ + { IFM_TOK_ALLR, "AllRoutes" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_FDDI_DESCRIPTIONS { \ + { IFM_FDDI_SMF, "Single-mode" }, \ + { IFM_FDDI_MMF, "Multi-mode" }, \ + { IFM_FDDI_UTP, "UTP" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_FDDI_ALIASES { \ + { IFM_FDDI_SMF, "SMF" }, \ + { IFM_FDDI_MMF, "MMF" }, \ + { IFM_FDDI_UTP, "CDDI" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS { \ + { IFM_FDDI_DA, "Dual-attach" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_IEEE80211_DESCRIPTIONS { \ + { IFM_IEEE80211_FH1, "FH1" }, \ + { IFM_IEEE80211_FH2, "FH2" }, \ + { IFM_IEEE80211_DS1, "DS1" }, \ + { IFM_IEEE80211_DS2, "DS2" }, \ + { IFM_IEEE80211_DS5, "DS5" }, \ + { IFM_IEEE80211_DS11, "DS11" }, \ + { IFM_IEEE80211_DS22, "DS22" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS { \ + { IFM_IEEE80211_ADHOC, "adhoc" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_SHARED_DESCRIPTIONS { \ + { IFM_AUTO, "autoselect" }, \ + { IFM_MANUAL, "manual" }, \ + { IFM_NONE, "none" }, \ + { 0, NULL }, \ +} + +#define IFM_SUBTYPE_SHARED_ALIASES { \ + { IFM_AUTO, "auto" }, \ + { 0, NULL }, \ +} + +#define IFM_SHARED_OPTION_DESCRIPTIONS { \ + { IFM_FDX, "full-duplex" }, \ + { IFM_HDX, "half-duplex" }, \ + { IFM_FLOW, "flow-control" }, \ + { IFM_EEE, "energy-efficient-ethernet" }, \ + { IFM_FLAG0, "flag0" }, \ + { IFM_FLAG1, "flag1" }, \ + { IFM_FLAG2, "flag2" }, \ + { IFM_LOOP, "hw-loopback" }, \ + { 0, NULL }, \ +} + +#endif /* _NET_IF_MEDIA_H_ */ \ No newline at end of file diff --git a/src/libraries/Native/Unix/System.Native/ios/netinet/icmp_var.h b/src/libraries/Native/Unix/System.Native/ios/netinet/icmp_var.h new file mode 100644 index 00000000000000..2633ab1bcf5a3e --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/ios/netinet/icmp_var.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)icmp_var.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/netinet/icmp_var.h,v 1.15.2.1 2001/02/24 21:35:18 bmilekic Exp $ + */ + +#ifndef _NETINET_ICMP_VAR_H_ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#define _NETINET_ICMP_VAR_H_ +#pragma clang diagnostic pop +#include + +/* + * Variables related to this implementation + * of the internet control message protocol. + */ +struct icmpstat { +/* statistics related to icmp packets generated */ + u_int32_t icps_error; /* # of calls to icmp_error */ + u_int32_t icps_oldshort; /* no error 'cuz old ip too short */ + u_int32_t icps_oldicmp; /* no error 'cuz old was icmp */ + u_int32_t icps_outhist[ICMP_MAXTYPE + 1]; +/* statistics related to input messages processed */ + u_int32_t icps_badcode; /* icmp_code out of range */ + u_int32_t icps_tooshort; /* packet < ICMP_MINLEN */ + u_int32_t icps_checksum; /* bad checksum */ + u_int32_t icps_badlen; /* calculated bound mismatch */ + u_int32_t icps_reflect; /* number of responses */ + u_int32_t icps_inhist[ICMP_MAXTYPE + 1]; + u_int32_t icps_bmcastecho;/* b/mcast echo requests dropped */ + u_int32_t icps_bmcasttstamp; /* b/mcast tstamp requests dropped */ +}; + +/* + * Names for ICMP sysctl objects + */ +#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */ +#define ICMPCTL_STATS 2 /* statistics (read-only) */ +#define ICMPCTL_ICMPLIM 3 +#define ICMPCTL_TIMESTAMP 4 /* allow replies to time stamp requests */ +#define ICMPCTL_MAXID 5 + +#ifdef BSD_KERNEL_PRIVATE +#define ICMPCTL_NAMES { \ + { 0, 0 }, \ + { "maskrepl", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ + { "icmplim", CTLTYPE_INT }, \ + { "icmptimestamp", CTLTYPE_INT }, \ +} + +SYSCTL_DECL(_net_inet_icmp); +#ifdef ICMP_BANDLIM +extern boolean_t badport_bandlim(int which); +#endif +#define BANDLIM_ICMP_UNREACH 0 +#define BANDLIM_ICMP_ECHO 1 +#define BANDLIM_ICMP_TSTAMP 2 +#define BANDLIM_MAX 4 + +extern struct icmpstat icmpstat; +#endif /* BSD_KERNEL_PRIVATE */ +#endif /* _NETINET_ICMP_VAR_H_ */ \ No newline at end of file diff --git a/src/libraries/Native/Unix/System.Native/ios/netinet/ip_var.h b/src/libraries/Native/Unix/System.Native/ios/netinet/ip_var.h new file mode 100644 index 00000000000000..e5137effeed46f --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/ios/netinet/ip_var.h @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2000-2020 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_var.h 8.2 (Berkeley) 1/9/95 + */ +/* + * NOTICE: This file was modified by SPARTA, Inc. in 2007 to introduce + * support for mandatory and extensible security protections. This notice + * is included in support of clause 2.2 (b) of the Apple Public License, + * Version 2.0. + */ + +#ifndef _NETINET_IP_VAR_H_ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#define _NETINET_IP_VAR_H_ +#pragma clang diagnostic pop +#include + +/* + * Overlay for ip header used by other protocols (tcp, udp). + */ +struct ipovly { + u_char ih_x1[9]; /* (unused) */ + u_char ih_pr; /* protocol */ + u_short ih_len; /* protocol length */ + struct in_addr ih_src; /* source internet address */ + struct in_addr ih_dst; /* destination internet address */ +}; + +#ifdef BSD_KERNEL_PRIVATE +/* + * Ip reassembly queue structure. Each fragment + * being reassembled is attached to one of these structures. + * They are timed out after ipq_ttl drops to 0, and may also + * be reclaimed if memory becomes tight. + */ +struct ipq { + TAILQ_ENTRY(ipq) ipq_list; /* to other reass headers */ + struct mbuf *ipq_frags; /* to ip headers of fragments */ + u_char ipq_ttl; /* time for reass q to live */ + u_char ipq_p; /* protocol of this fragment */ + u_short ipq_id; /* sequence id for reassembly */ + struct in_addr ipq_src, ipq_dst; + u_int32_t ipq_nfrags; /* # frags in this packet */ + uint32_t ipq_csum_flags; /* checksum flags */ + uint32_t ipq_csum; /* partial checksum value */ +}; + +/* + * Structure stored in mbuf in inpcb.ip_options + * and passed to ip_output when ip options are in use. + * The actual length of the options (including ipopt_dst) + * is in m_len. + */ +#endif /* BSD_KERNEL_PRIVATE */ +#define MAX_IPOPTLEN 40 +#ifdef BSD_KERNEL_PRIVATE +struct ipoption { + struct in_addr ipopt_dst; /* first-hop dst if source routed */ + char ipopt_list[MAX_IPOPTLEN]; /* options proper */ +}; + +/* + * Structure attached to inpcb.ip_moptions and + * passed to ip_output when IP multicast options are in use. + */ +struct ip_moptions { + decl_lck_mtx_data(, imo_lock); + uint32_t imo_refcnt; /* ref count */ + uint32_t imo_debug; /* see ifa_debug flags */ + struct ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */ + u_char imo_multicast_ttl; /* TTL for outgoing multicasts */ + u_char imo_multicast_loop; /* 1 => hear sends if a member */ + u_short imo_num_memberships; /* no. memberships this socket */ + u_short imo_max_memberships; /* max memberships this socket */ + struct in_multi **imo_membership; /* group memberships */ + struct in_mfilter *imo_mfilters; /* source filters */ + u_int32_t imo_multicast_vif; /* vif num outgoing multicasts */ + struct in_addr imo_multicast_addr; /* ifindex/addr on MULTICAST_IF */ + void (*imo_trace) /* callback fn for tracing refs */ + (struct ip_moptions *, int); +}; + +#define IMO_LOCK_ASSERT_HELD(_imo) \ + LCK_MTX_ASSERT(&(_imo)->imo_lock, LCK_MTX_ASSERT_OWNED) + +#define IMO_LOCK_ASSERT_NOTHELD(_imo) \ + LCK_MTX_ASSERT(&(_imo)->imo_lock, LCK_MTX_ASSERT_NOTOWNED) + +#define IMO_LOCK(_imo) \ + lck_mtx_lock(&(_imo)->imo_lock) + +#define IMO_LOCK_SPIN(_imo) \ + lck_mtx_lock_spin(&(_imo)->imo_lock) + +#define IMO_CONVERT_LOCK(_imo) do { \ + IMO_LOCK_ASSERT_HELD(_imo); \ + lck_mtx_convert_spin(&(_imo)->imo_lock); \ +} while (0) + +#define IMO_UNLOCK(_imo) \ + lck_mtx_unlock(&(_imo)->imo_lock) + +#define IMO_ADDREF(_imo) \ + imo_addref(_imo, 0) + +#define IMO_ADDREF_LOCKED(_imo) \ + imo_addref(_imo, 1) + +#define IMO_REMREF(_imo) \ + imo_remref(_imo) + +/* mbuf tag for ip_forwarding info */ +struct ip_fwd_tag { + struct sockaddr_in *next_hop; /* next_hop */ +}; +#endif /* BSD_KERNEL_PRIVATE */ + +struct ipstat { + u_int32_t ips_total; /* total packets received */ + u_int32_t ips_badsum; /* checksum bad */ + u_int32_t ips_tooshort; /* packet too short */ + u_int32_t ips_toosmall; /* not enough data */ + u_int32_t ips_badhlen; /* ip header length < data size */ + u_int32_t ips_badlen; /* ip length < ip header length */ + u_int32_t ips_fragments; /* fragments received */ + u_int32_t ips_fragdropped; /* frags dropped (dups, out of space) */ + u_int32_t ips_fragtimeout; /* fragments timed out */ + u_int32_t ips_forward; /* packets forwarded */ + u_int32_t ips_fastforward; /* packets fast forwarded */ + u_int32_t ips_cantforward; /* packets rcvd for unreachable dest */ + u_int32_t ips_redirectsent; /* packets forwarded on same net */ + u_int32_t ips_noproto; /* unknown or unsupported protocol */ + u_int32_t ips_delivered; /* datagrams delivered to upper level */ + u_int32_t ips_localout; /* total ip packets generated here */ + u_int32_t ips_odropped; /* lost packets due to nobufs, etc. */ + u_int32_t ips_reassembled; /* total packets reassembled ok */ + u_int32_t ips_fragmented; /* datagrams successfully fragmented */ + u_int32_t ips_ofragments; /* output fragments created */ + u_int32_t ips_cantfrag; /* don't fragment flag was set, etc. */ + u_int32_t ips_badoptions; /* error in option processing */ + u_int32_t ips_noroute; /* packets discarded due to no route */ + u_int32_t ips_badvers; /* ip version != 4 */ + u_int32_t ips_rawout; /* total raw ip packets generated */ + u_int32_t ips_toolong; /* ip length > max ip packet size */ + u_int32_t ips_notmember; /* multicasts for unregistered grps */ + u_int32_t ips_nogif; /* no match gif found */ + u_int32_t ips_badaddr; /* invalid address on header */ + u_int32_t ips_pktdropcntrl; /* pkt dropped, no mbufs for ctl data */ + u_int32_t ips_rcv_swcsum; /* ip hdr swcksum (inbound), packets */ + u_int32_t ips_rcv_swcsum_bytes; /* ip hdr swcksum (inbound), bytes */ + u_int32_t ips_snd_swcsum; /* ip hdr swcksum (outbound), packets */ + u_int32_t ips_snd_swcsum_bytes; /* ip hdr swcksum (outbound), bytes */ + u_int32_t ips_adj; /* total packets trimmed/adjusted */ + u_int32_t ips_adj_hwcsum_clr; /* hwcksum discarded during adj */ + u_int32_t ips_rxc_collisions; /* rx chaining collisions */ + u_int32_t ips_rxc_chained; /* rx chains */ + u_int32_t ips_rxc_notchain; /* rx bypassed chaining */ + u_int32_t ips_rxc_chainsz_gt2; /* rx chain size greater than 2 */ + u_int32_t ips_rxc_chainsz_gt4; /* rx chain size greater than 4 */ + u_int32_t ips_rxc_notlist; /* count of pkts through ip_input */ + u_int32_t ips_raw_sappend_fail; /* sock append failed */ + u_int32_t ips_necp_policy_drop; /* NECP policy related drop */ + u_int32_t ips_rcv_if_weak_match; /* packets whose receive interface that passed the Weak ES address check */ + u_int32_t ips_rcv_if_no_match; /* packets whose receive interface did not pass the address check */ +}; + +struct ip_linklocal_stat { + u_int32_t iplls_in_total; + u_int32_t iplls_in_badttl; + u_int32_t iplls_out_total; + u_int32_t iplls_out_badttl; +}; + +#ifdef KERNEL_PRIVATE +/* forward declarations for ip_output() */ +struct ip_out_args; +struct ip_moptions; +#endif /* KERNEL_PRIVATE */ + +#ifdef BSD_KERNEL_PRIVATE +/* flags passed to ip_output as last parameter */ +#define IP_FORWARDING 0x1 /* most of ip header exists */ +#define IP_RAWOUTPUT 0x2 /* raw ip header exists */ +#define IP_NOIPSEC 0x4 /* No IPsec processing */ +#define IP_ROUTETOIF SO_DONTROUTE /* bypass routing tables (0x0010) */ +#define IP_ALLOWBROADCAST SO_BROADCAST /* can send broadcast pkts (0x0020) */ +#define IP_OUTARGS 0x100 /* has ancillary output info */ + +#define IP_HDR_ALIGNED_P(_ip) ((((uintptr_t)(_ip)) & ((uintptr_t)3)) == 0) +#define IP_OFF_IS_ATOMIC(_ip_off) ((_ip_off & (IP_DF | IP_MF | IP_OFFMASK)) == IP_DF) + +/* + * On platforms which require strict alignment (currently for anything but + * i386 or x86_64), this macro checks whether the pointer to the IP header + * is 32-bit aligned, and assert otherwise. + */ +#if defined(__i386__) || defined(__x86_64__) +#define IP_HDR_STRICT_ALIGNMENT_CHECK(_ip) do { } while (0) +#else /* !__i386__ && !__x86_64__ */ +#define IP_HDR_STRICT_ALIGNMENT_CHECK(_ip) do { \ + if (!IP_HDR_ALIGNED_P(_ip)) { \ + panic_plain("\n%s: Unaligned IP header %p\n", \ + __func__, _ip); \ + } \ +} while (0) +#endif /* !__i386__ && !__x86_64__ */ + +struct ip; +struct inpcb; +struct route; +struct sockopt; + +#include +#include + +/* + * Extra information passed to ip_output when IP_OUTARGS is set. + * + * Upon returning an error to the caller, ip_output may indicate through + * ipoa_retflags any additional information regarding the error. + */ +struct ip_out_args { + unsigned int ipoa_boundif; /* boundif interface index */ + struct flowadv ipoa_flowadv; /* flow advisory code */ + u_int32_t ipoa_flags; /* IPOAF output flags (see below) */ +#define IPOAF_SELECT_SRCIF 0x00000001 /* src interface selection */ +#define IPOAF_BOUND_IF 0x00000002 /* boundif value is valid */ +#define IPOAF_BOUND_SRCADDR 0x00000004 /* bound to src address */ +#define IPOAF_NO_CELLULAR 0x00000010 /* skip IFT_CELLULAR */ +#define IPOAF_NO_EXPENSIVE 0x00000020 /* skip IFT_EXPENSIVE */ +#define IPOAF_AWDL_UNRESTRICTED 0x00000040 /* can send over + * AWDL_RESTRICTED */ +#define IPOAF_QOSMARKING_ALLOWED 0x00000080 /* policy allows Fastlane DSCP marking */ +#define IPOAF_NO_CONSTRAINED 0x00000100 /* skip IFXF_CONSTRAINED */ +#define IPOAF_REDO_QOSMARKING_POLICY 0x00000200 /* Re-evaluate QOS marking policy */ + u_int32_t ipoa_retflags; /* IPOARF return flags (see below) */ +#define IPOARF_IFDENIED 0x00000001 /* denied access to interface */ + int ipoa_sotc; /* traffic class for Fastlane DSCP mapping */ + int ipoa_netsvctype; /* network service type */ + int32_t qos_marking_gencount; +}; + +extern struct ipstat ipstat; +extern int ip_use_randomid; +extern u_short ip_id; /* ip packet ctr, for ids */ +extern int ip_defttl; /* default IP ttl */ +extern int ipforwarding; /* ip forwarding */ +extern int rfc6864; +extern struct protosw *ip_protox[]; +extern struct pr_usrreqs rip_usrreqs; + +extern void ip_moptions_init(void); +extern struct ip_moptions *ip_allocmoptions(zalloc_flags_t); +extern int inp_getmoptions(struct inpcb *, struct sockopt *); +extern int inp_setmoptions(struct inpcb *, struct sockopt *); +extern void imo_addref(struct ip_moptions *, int); +extern void imo_remref(struct ip_moptions *); + +struct protosw; +struct domain; + +extern int ip_checkrouteralert(struct mbuf *); +extern int ip_ctloutput(struct socket *, struct sockopt *sopt); +extern void ip_drain(void); +extern void ip_init(struct protosw *, struct domain *); +extern int ip_output(struct mbuf *, struct mbuf *, struct route *, int, + struct ip_moptions *, struct ip_out_args *); +extern int ip_output_list(struct mbuf *, int, struct mbuf *, struct route *, + int, struct ip_moptions *, struct ip_out_args *); +extern void ip_output_checksum(struct ifnet *, struct mbuf *, int, int, + uint32_t *); +extern struct in_ifaddr *ip_rtaddr(struct in_addr); +extern int ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, + struct mbuf *); +extern struct mbuf *ip_srcroute(void); +extern void ip_stripoptions(struct mbuf *); +extern void ip_initid(void); +extern u_int16_t ip_randomid(void); +extern int ip_fragment(struct mbuf *, struct ifnet *, uint32_t, int); + +extern void ip_setsrcifaddr_info(struct mbuf *, uint32_t, struct in_ifaddr *); +extern void ip_setdstifaddr_info(struct mbuf *, uint32_t, struct in_ifaddr *); +extern int ip_getsrcifaddr_info(struct mbuf *, uint32_t *, uint32_t *); +extern int ip_getdstifaddr_info(struct mbuf *, uint32_t *, uint32_t *); + +extern int rip_ctloutput(struct socket *, struct sockopt *); +extern void rip_ctlinput(int, struct sockaddr *, void *, struct ifnet *); +extern void rip_init(struct protosw *, struct domain *); +extern void rip_input(struct mbuf *, int); +extern int rip_output(struct mbuf *, struct socket *, u_int32_t, struct mbuf *); +extern int rip_unlock(struct socket *, int, void *); +extern int rip_send(struct socket *, int, struct mbuf *, struct sockaddr *, + struct mbuf *, struct proc *); + +extern void tcp_in_cksum_stats(u_int32_t); +extern void tcp_out_cksum_stats(u_int32_t); + +extern void udp_in_cksum_stats(u_int32_t); +extern void udp_out_cksum_stats(u_int32_t); + +extern void tcp_in6_cksum_stats(u_int32_t); +extern void tcp_out6_cksum_stats(u_int32_t); + +extern void udp_in6_cksum_stats(u_int32_t); +extern void udp_out6_cksum_stats(u_int32_t); +#endif /* BSD_KERNEL_PRIVATE */ +#ifdef KERNEL_PRIVATE +/* for PPP/PPTP */ +extern int ip_gre_output(struct mbuf *); +typedef struct mbuf *(*gre_input_func_t)(struct mbuf *, int, int); +extern int ip_gre_register_input(gre_input_func_t); +#endif /* KERNEL_PRIVATE */ +#endif /* !_NETINET_IP_VAR_H_ */ \ No newline at end of file diff --git a/src/libraries/Native/Unix/System.Native/ios/netinet/tcp_fsm.h b/src/libraries/Native/Unix/System.Native/ios/netinet/tcp_fsm.h new file mode 100644 index 00000000000000..869d9bcef8d511 --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/ios/netinet/tcp_fsm.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp_fsm.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/netinet/tcp_fsm.h,v 1.14 1999/11/07 04:18:30 jlemon Exp $ + */ + +#ifndef _NETINET_TCP_FSM_H_ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#define _NETINET_TCP_FSM_H_ +#pragma clang diagnostic pop +#include + +/* + * TCP FSM state definitions. + * Per RFC793, September, 1981. + */ + +#define TCP_NSTATES 11 + +#define TCPS_CLOSED 0 /* closed */ +#define TCPS_LISTEN 1 /* listening for connection */ +#define TCPS_SYN_SENT 2 /* active, have sent syn */ +#define TCPS_SYN_RECEIVED 3 /* have send and received syn */ +/* states < TCPS_ESTABLISHED are those where connections not established */ +#define TCPS_ESTABLISHED 4 /* established */ +#define TCPS_CLOSE_WAIT 5 /* rcvd fin, waiting for close */ +/* states > TCPS_CLOSE_WAIT are those where user has closed */ +#define TCPS_FIN_WAIT_1 6 /* have closed, sent fin */ +#define TCPS_CLOSING 7 /* closed xchd FIN; await FIN ACK */ +#define TCPS_LAST_ACK 8 /* had fin and close; await FIN ACK */ +/* states > TCPS_CLOSE_WAIT && < TCPS_FIN_WAIT_2 await ACK of FIN */ +#define TCPS_FIN_WAIT_2 9 /* have closed, fin is acked */ +#define TCPS_TIME_WAIT 10 /* in 2*msl quiet wait after close */ + +/* for KAME src sync over BSD*'s */ +#define TCP6_NSTATES TCP_NSTATES +#define TCP6S_CLOSED TCPS_CLOSED +#define TCP6S_LISTEN TCPS_LISTEN +#define TCP6S_SYN_SENT TCPS_SYN_SENT +#define TCP6S_SYN_RECEIVED TCPS_SYN_RECEIVED +#define TCP6S_ESTABLISHED TCPS_ESTABLISHED +#define TCP6S_CLOSE_WAIT TCPS_CLOSE_WAIT +#define TCP6S_FIN_WAIT_1 TCPS_FIN_WAIT_1 +#define TCP6S_CLOSING TCPS_CLOSING +#define TCP6S_LAST_ACK TCPS_LAST_ACK +#define TCP6S_FIN_WAIT_2 TCPS_FIN_WAIT_2 +#define TCP6S_TIME_WAIT TCPS_TIME_WAIT + +#define TCPS_HAVERCVDSYN(s) ((s) >= TCPS_SYN_RECEIVED) +#define TCPS_HAVEESTABLISHED(s) ((s) >= TCPS_ESTABLISHED) +#define TCPS_HAVERCVDFIN(s) ((s) >= TCPS_TIME_WAIT) +#define TCPS_HAVERCVDFIN2(s) ((s) == TCPS_CLOSE_WAIT || \ + (s) == TCPS_CLOSING || \ + (s) == TCPS_LAST_ACK || \ + (s) == TCPS_TIME_WAIT) + +#ifdef KERNEL_PRIVATE +#ifdef TCPOUTFLAGS +/* + * Flags used when sending segments in tcp_output. + * Basic flags (TH_RST,TH_ACK,TH_SYN,TH_FIN) are totally + * determined by state, with the proviso that TH_FIN is sent only + * if all data queued for output is included in the segment. + */ +static u_char tcp_outflags[TCP_NSTATES] = { + TH_RST | TH_ACK, /* 0, CLOSED */ + 0, /* 1, LISTEN */ + TH_SYN, /* 2, SYN_SENT */ + TH_SYN | TH_ACK, /* 3, SYN_RECEIVED */ + TH_ACK, /* 4, ESTABLISHED */ + TH_ACK, /* 5, CLOSE_WAIT */ + TH_FIN | TH_ACK, /* 6, FIN_WAIT_1 */ + TH_FIN | TH_ACK, /* 7, CLOSING */ + TH_FIN | TH_ACK, /* 8, LAST_ACK */ + TH_ACK, /* 9, FIN_WAIT_2 */ + TH_ACK, /* 10, TIME_WAIT */ +}; +#endif +#endif /* KERNEL_PRIVATE */ + +#if KPROF +#ifdef KERNEL_PRIVATE +int tcp_acounts[TCP_NSTATES][PRU_NREQ]; +#endif /* KERNEL_PRIVATE */ +#endif + +#ifdef TCPSTATES +char *tcpstates[] = { + "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", + "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", + "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT" +}; +#endif + +#endif \ No newline at end of file diff --git a/src/libraries/Native/Unix/System.Native/ios/netinet/udp_var.h b/src/libraries/Native/Unix/System.Native/ios/netinet/udp_var.h new file mode 100644 index 00000000000000..12e4ea51f0b49e --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/ios/netinet/udp_var.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2008-2016 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)udp_var.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_UDP_VAR_H_ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#define _NETINET_UDP_VAR_H_ +#pragma clang diagnostic pop + +#include +#include + +/* + * UDP kernel structures and variables. + */ +struct udpiphdr { + struct ipovly ui_i; /* overlaid ip structure */ + struct udphdr ui_u; /* udp header */ +}; +#define ui_x1 ui_i.ih_x1 +#define ui_pr ui_i.ih_pr +#define ui_len ui_i.ih_len +#define ui_src ui_i.ih_src +#define ui_dst ui_i.ih_dst +#define ui_sport ui_u.uh_sport +#define ui_dport ui_u.uh_dport +#define ui_ulen ui_u.uh_ulen +#define ui_sum ui_u.uh_sum +#define ui_next ui_i.ih_next +#define ui_prev ui_i.ih_prev + +struct udpstat { + /* input statistics: */ + u_int32_t udps_ipackets; /* total input packets */ + u_int32_t udps_hdrops; /* packet shorter than header */ + u_int32_t udps_badsum; /* checksum error */ + u_int32_t udps_badlen; /* data length larger than packet */ + u_int32_t udps_noport; /* no socket on port */ + u_int32_t udps_noportbcast; /* of above, arrived as broadcast */ + u_int32_t udps_fullsock; /* not delivered, input socket full */ + u_int32_t udpps_pcbcachemiss; /* input packets missing pcb cache */ + u_int32_t udpps_pcbhashmiss; /* input packets not for hashed pcb */ + /* output statistics: */ + u_int32_t udps_opackets; /* total output packets */ + u_int32_t udps_fastout; /* output packets on fast path */ + u_int32_t udps_nosum; /* no checksum */ + u_int32_t udps_noportmcast; /* of no socket on port, multicast */ + u_int32_t udps_filtermcast; /* blocked by multicast filter */ + /* checksum statistics: */ + u_int32_t udps_rcv_swcsum; /* udp swcksum (inbound), packets */ + u_int32_t udps_rcv_swcsum_bytes; /* udp swcksum (inbound), bytes */ + u_int32_t udps_rcv6_swcsum; /* udp6 swcksum (inbound), packets */ + u_int32_t udps_rcv6_swcsum_bytes; /* udp6 swcksum (inbound), bytes */ + u_int32_t udps_snd_swcsum; /* udp swcksum (outbound), packets */ + u_int32_t udps_snd_swcsum_bytes; /* udp swcksum (outbound), bytes */ + u_int32_t udps_snd6_swcsum; /* udp6 swcksum (outbound), packets */ + u_int32_t udps_snd6_swcsum_bytes; /* udp6 swcksum (outbound), bytes */ +}; + +/* + * Names for UDP sysctl objects + */ +#define UDPCTL_CHECKSUM 1 /* checksum UDP packets */ +#define UDPCTL_STATS 2 /* statistics (read-only) */ +#define UDPCTL_MAXDGRAM 3 /* max datagram size */ +#define UDPCTL_RECVSPACE 4 /* default receive buffer space */ +#define UDPCTL_PCBLIST 5 /* list of PCBs for UDP sockets */ +#define UDPCTL_MAXID 6 + +#ifdef BSD_KERNEL_PRIVATE +#include +#include + +#define UDPCTL_NAMES { \ + { 0, 0 }, \ + { "checksum", CTLTYPE_INT }, \ + { "stats", CTLTYPE_STRUCT }, \ + { "maxdgram", CTLTYPE_INT }, \ + { "recvspace", CTLTYPE_INT }, \ + { "pcblist", CTLTYPE_STRUCT }, \ +} + +#define udp6stat udpstat +#define udp6s_opackets udps_opackets + +SYSCTL_DECL(_net_inet_udp); + +struct udpstat_local { + u_int64_t port_unreach; + u_int64_t faithprefix; /* deprecated */ + u_int64_t port0; + u_int64_t badlength; + u_int64_t badchksum; + u_int64_t badmcast; + u_int64_t cleanup; + u_int64_t badipsec; +}; + +extern struct pr_usrreqs udp_usrreqs; +extern struct inpcbhead udb; +extern struct inpcbinfo udbinfo; +extern u_int32_t udp_sendspace; +extern u_int32_t udp_recvspace; +extern struct udpstat udpstat; +extern int udp_log_in_vain; + +__BEGIN_DECLS +extern void udp_ctlinput(int, struct sockaddr *, void *, struct ifnet *); +extern int udp_ctloutput(struct socket *, struct sockopt *); +extern void udp_init(struct protosw *, struct domain *); +extern void udp_input(struct mbuf *, int); +extern int udp_connectx_common(struct socket *, int, struct sockaddr *, + struct sockaddr *, struct proc *, uint32_t, sae_associd_t, + sae_connid_t *, uint32_t, void *, uint32_t, struct uio*, user_ssize_t *); +extern void udp_notify(struct inpcb *inp, int errno); +extern int udp_shutdown(struct socket *so); +extern int udp_lock(struct socket *, int, void *); +extern int udp_unlock(struct socket *, int, void *); +extern lck_mtx_t *udp_getlock(struct socket *, int); +extern void udp_get_ports_used(u_int32_t, int, u_int32_t, bitstr_t *); +extern uint32_t udp_count_opportunistic(unsigned int, u_int32_t); +extern uint32_t udp_find_anypcb_byaddr(struct ifaddr *); + +extern void udp_fill_keepalive_offload_frames(struct ifnet *, + struct ifnet_keepalive_offload_frame *, u_int32_t, size_t, u_int32_t *); + +__END_DECLS +#endif /* BSD_KERNEL_PRIVATE */ +#endif /* _NETINET_UDP_VAR_H_ */ \ No newline at end of file diff --git a/src/libraries/Native/Unix/System.Native/pal_environment.c b/src/libraries/Native/Unix/System.Native/pal_environment.c new file mode 100644 index 00000000000000..fd9e68f0230281 --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/pal_environment.c @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "pal_config.h" +#include "pal_environment.h" + +#include +#include +#if HAVE_NSGETENVIRON +#include +#endif + +char* SystemNative_GetEnv(const char* variable) +{ + return getenv(variable); +} + +char** SystemNative_GetEnviron() +{ +#if HAVE_NSGETENVIRON + return *(_NSGetEnviron()); +#else + extern char **environ; + return environ; +#endif +} + +void SystemNative_FreeEnviron(char** environ) +{ + // no op + (void)environ; +} diff --git a/src/libraries/Native/Unix/System.Native/pal_environment.h b/src/libraries/Native/Unix/System.Native/pal_environment.h new file mode 100644 index 00000000000000..dee7a10f3aecdc --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/pal_environment.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include "pal_compiler.h" +#include "pal_types.h" + +PALEXPORT char* SystemNative_GetEnv(const char* variable); + +PALEXPORT char** SystemNative_GetEnviron(void); + +PALEXPORT void SystemNative_FreeEnviron(char** environ); diff --git a/src/libraries/Native/Unix/System.Native/pal_environment.m b/src/libraries/Native/Unix/System.Native/pal_environment.m new file mode 100644 index 00000000000000..ea4edc6ccd3196 --- /dev/null +++ b/src/libraries/Native/Unix/System.Native/pal_environment.m @@ -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. + +#include "pal_config.h" +#include "pal_environment.h" + +#include +#include +#include +#include + +char* SystemNative_GetEnv(const char* variable) +{ + return getenv(variable); +} + +static char *empty_key_value_pair = "="; + +static void get_environ_helper(const void *key, const void *value, void *context) +{ + char ***temp_environ_ptr = (char***)context; + const char *utf8_key = [(NSString *)key UTF8String]; + const char *utf8_value = [(NSString *)value UTF8String]; + int utf8_key_length = strlen(utf8_key); + int utf8_value_length = strlen(utf8_value); + char *key_value_pair; + + key_value_pair = malloc(utf8_key_length + utf8_value_length + 2); + if (key_value_pair != NULL) + { + strcpy(key_value_pair, utf8_key); + key_value_pair[utf8_key_length] = '='; + strcpy(key_value_pair + utf8_key_length + 1, utf8_value); + } + else + { + // In case of failed allocation add pointer to preallocated entry. This is + // ignored on the managed side and skipped over in SystemNative_FreeEnviron. + key_value_pair = empty_key_value_pair; + } + + **temp_environ_ptr = key_value_pair; + (*temp_environ_ptr)++; +} + +char** SystemNative_GetEnviron() +{ + char **temp_environ; + char **temp_environ_ptr; + + CFDictionaryRef environment = (CFDictionaryRef)[[NSProcessInfo processInfo] environment]; + int count = CFDictionaryGetCount(environment); + temp_environ = (char **)malloc((count + 1) * sizeof(char *)); + if (temp_environ != NULL) + { + temp_environ_ptr = temp_environ; + CFDictionaryApplyFunction(environment, get_environ_helper, &temp_environ_ptr); + *temp_environ_ptr = NULL; + } + + return temp_environ; +} + +void SystemNative_FreeEnviron(char** environ) +{ + if (environ != NULL) + { + for (char** environ_ptr = environ; *environ_ptr != NULL; environ_ptr++) + { + if (*environ_ptr != empty_key_value_pair) + { + free(*environ_ptr); + } + } + + free(environ); + } +} diff --git a/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c b/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c index bc95883b7cb04d..620f2e81495bc6 100644 --- a/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c +++ b/src/libraries/Native/Unix/System.Native/pal_interfaceaddresses.c @@ -11,7 +11,13 @@ #include #include #include +#if HAVE_IFADDRS || HAVE_GETIFADDRS #include +#endif +#if !HAVE_GETIFADDRS && TARGET_ANDROID +#include +#include +#endif #include #include #include @@ -29,6 +35,8 @@ #endif #if HAVE_NET_IFMEDIA_H #include +#elif HAVE_IOS_NET_IFMEDIA_H +#include "ios/net/if_media.h" #endif #if defined(AF_PACKET) @@ -53,7 +61,6 @@ #endif #endif -#if HAVE_GETIFADDRS // Convert mask to prefix length e.g. 255.255.255.0 -> 24 // mask parameter is pointer to buffer where address starts and length is // buffer length e.g. 4 for IPv4 and 16 for IPv6. @@ -93,6 +100,50 @@ static inline uint8_t mask2prefix(uint8_t* mask, int length) return len; } + +#if !HAVE_IFADDRS && TARGET_ANDROID +// This structure is exactly the same as struct ifaddrs defined in ifaddrs.h but since the header +// might not be available (e.g., in bionics used in Android before API 24) we need to mirror it here +// so that we can dynamically load the getifaddrs function and use it. +struct ifaddrs +{ + struct ifaddrs *ifa_next; + char *ifa_name; + unsigned int ifa_flags; + struct sockaddr *ifa_addr; + struct sockaddr *ifa_netmask; + union + { + struct sockaddr *ifu_broadaddr; + struct sockaddr *ifu_dstaddr; + } ifa_ifu; + void *ifa_data; +}; +#endif + +#if !HAVE_GETIFADDRS && TARGET_ANDROID +// Try to load the getifaddrs and freeifaddrs functions manually. +// This workaround is necessary on Android prior to API 24 and it can be removed once +// we drop support for earlier Android versions. +static int (*getifaddrs)(struct ifaddrs**) = NULL; +static void (*freeifaddrs)(struct ifaddrs*) = NULL; + +static void try_loading_getifaddrs() +{ + void *libc = dlopen("libc.so", RTLD_NOW); + if (libc) + { + getifaddrs = (int (*)(struct ifaddrs**)) dlsym(libc, "getifaddrs"); + freeifaddrs = (void (*)(struct ifaddrs*)) dlsym(libc, "freeifaddrs"); + } +} + +static bool ensure_getifaddrs_is_loaded() +{ + static pthread_once_t getifaddrs_is_loaded = PTHREAD_ONCE_INIT; + pthread_once(&getifaddrs_is_loaded, try_loading_getifaddrs); + return getifaddrs != NULL && freeifaddrs != NULL; +} #endif int32_t SystemNative_EnumerateInterfaceAddresses(void* context, @@ -100,7 +151,16 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, IPv6AddressFound onIpv6Found, LinkLayerAddressFound onLinkLayerFound) { -#if HAVE_GETIFADDRS +#if !HAVE_GETIFADDRS && TARGET_ANDROID + // Workaround for Android API < 24 + if (!ensure_getifaddrs_is_loaded()) + { + errno = ENOTSUP; + return -1; + } +#endif + +#if HAVE_GETIFADDRS || TARGET_ANDROID struct ifaddrs* headAddr; if (getifaddrs(&headAddr) == -1) { @@ -203,7 +263,7 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, lla.NumAddressBytes = sadl->sdl_alen; lla.HardwareType = MapHardwareType(sadl->sdl_type); -#if HAVE_NET_IFMEDIA_H +#if HAVE_NET_IFMEDIA_H || HAVE_IOS_NET_IFMEDIA_H if (lla.HardwareType == NetworkInterfaceType_Ethernet) { // WI-FI and Ethernet have same address type so we can try to distinguish more @@ -233,7 +293,7 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, freeifaddrs(headAddr); return 0; #else - // Not supported on e.g. Android. Also, prevent a compiler error because parameters are unused + // Not supported. Also, prevent a compiler error because parameters are unused (void)context; (void)onIpv4Found; (void)onIpv6Found; @@ -245,7 +305,16 @@ int32_t SystemNative_EnumerateInterfaceAddresses(void* context, int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInterfaceInfo **interfaceList, int32_t * addressCount, IpAddressInfo **addressList ) { -#if HAVE_GETIFADDRS +#if !HAVE_GETIFADDRS && TARGET_ANDROID + // Workaround for Android API < 24 + if (!ensure_getifaddrs_is_loaded()) + { + errno = ENOTSUP; + return -1; + } +#endif + +#if HAVE_GETIFADDRS || TARGET_ANDROID struct ifaddrs* head; // Pointer to block allocated by getifaddrs(). struct ifaddrs* ifaddrsEntry; IpAddressInfo *ai; @@ -451,7 +520,7 @@ int32_t SystemNative_GetNetworkInterfaces(int32_t * interfaceCount, NetworkInter return 0; #else - // Not supported on e.g. Android. Also, prevent a compiler error because parameters are unused + // Not supported. Also, prevent a compiler error because parameters are unused (void)interfaceCount; (void)interfaceList; (void)addressCount; diff --git a/src/libraries/Native/Unix/System.Native/pal_io.c b/src/libraries/Native/Unix/System.Native/pal_io.c index 51d841ffc55bdb..3541a90f1858bb 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.c +++ b/src/libraries/Native/Unix/System.Native/pal_io.c @@ -324,6 +324,12 @@ int32_t SystemNative_Unlink(const char* path) intptr_t SystemNative_ShmOpen(const char* name, int32_t flags, int32_t mode) { +#if defined(SHM_NAME_MAX) // macOS + assert(strlen(name) <= SHM_NAME_MAX); +#elif defined(PATH_MAX) // other Unixes + assert(strlen(name) <= PATH_MAX); +#endif + #if HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP flags = ConvertOpenFlags(flags); if (flags == -1) @@ -1008,83 +1014,35 @@ int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, i #endif } -int32_t SystemNative_PosixFAllocate(intptr_t fd, int64_t offset, int64_t length) +int32_t SystemNative_FAllocate(intptr_t fd, int64_t offset, int64_t length) { assert_msg(offset == 0, "Invalid offset value", (int)offset); - int fileDescriptor = ToFileDescriptor(fd); int32_t result; -#if HAVE_POSIX_FALLOCATE64 // 64-bit Linux - while ((result = posix_fallocate64(fileDescriptor, (off64_t)offset, (off64_t)length)) == EINTR); -#elif HAVE_POSIX_FALLOCATE // 32-bit Linux - while ((result = posix_fallocate(fileDescriptor, (off_t)offset, (off_t)length)) == EINTR); +#if HAVE_FALLOCATE // Linux + int fileDescriptor = ToFileDescriptor(fd); + while ((result = fallocate(fileDescriptor, FALLOC_FL_KEEP_SIZE, (off_t)offset, (off_t)length)) == EINTR); #elif defined(F_PREALLOCATE) // macOS + int fileDescriptor = ToFileDescriptor(fd); fstore_t fstore; - fstore.fst_flags = F_ALLOCATECONTIG; // ensure contiguous space - fstore.fst_posmode = F_PEOFPOSMODE; // allocate from the physical end of file, as offset MUST NOT be 0 for F_VOLPOSMODE + fstore.fst_flags = F_ALLOCATEALL; // Allocate all requested space or no space at all. + fstore.fst_posmode = F_PEOFPOSMODE; // Allocate from the physical end of file. fstore.fst_offset = (off_t)offset; fstore.fst_length = (off_t)length; fstore.fst_bytesalloc = 0; // output size, can be > length while ((result = fcntl(fileDescriptor, F_PREALLOCATE, &fstore)) == -1 && errno == EINTR); - - if (result == -1) - { - // we have failed to allocate contiguous space, let's try non-contiguous - fstore.fst_flags = F_ALLOCATEALL; // all or nothing - while ((result = fcntl(fileDescriptor, F_PREALLOCATE, &fstore)) == -1 && errno == EINTR); - } -#elif defined(F_ALLOCSP) || defined(F_ALLOCSP64) // FreeBSD - #if HAVE_FLOCK64 - struct flock64 lockArgs; - int command = F_ALLOCSP64; - #else - struct flock lockArgs; - int command = F_ALLOCSP; - #endif - - lockArgs.l_whence = SEEK_SET; - lockArgs.l_start = (off_t)offset; - lockArgs.l_len = (off_t)length; - - while ((result = fcntl(fileDescriptor, command, &lockArgs)) == -1 && errno == EINTR); +#else + (void)fd; // unused + (void)offset; // unused + (void)length; // unused + result = -1; + errno = EOPNOTSUPP; #endif -#if defined(F_PREALLOCATE) || defined(F_ALLOCSP) || defined(F_ALLOCSP64) - // most of the Unixes implement posix_fallocate which does NOT set the last error - // fctnl does, but to mimic the posix_fallocate behaviour we just return error - if (result == -1) - { - result = errno; - } - else - { - // align the behaviour with what posix_fallocate does (change reported file size) - ftruncate(fileDescriptor, length); - } -#endif + assert(result == 0 || errno != EINVAL); - // error codes can be OS-specific, so this is why this handling is done here rather than in the managed layer - switch (result) - { - case ENOSPC: // there was not enough space - return -1; - case EFBIG: // the file was too large - return -2; - case ENODEV: // not a regular file - case ESPIPE: // a pipe - // We ignore it, as FileStream contract makes it clear that allocationSize is ignored for non-regular files. - return 0; - case EINVAL: - // We control the offset and length so they are correct. - assert_msg(length >= 0, "Invalid length value", (int)length); - // But if the underlying filesystem does not support the operation, we just ignore it and treat as a hint. - return 0; - default: - assert(result != EINTR); // it can't happen here as we retry the call on EINTR - assert(result != EBADF); // it can't happen here as this method is being called after a succesfull call to open (with write permissions) before returning the SafeFileHandle to the user - return 0; - } + return result; } int32_t SystemNative_Read(intptr_t fd, void* buffer, int32_t bufferSize) @@ -1427,6 +1385,7 @@ int64_t SystemNative_GetFileSystemType(intptr_t fd) else if (strcmp(statfsArgs.f_basetype, "befs") == 0) result = 0x42465331; else if (strcmp(statfsArgs.f_basetype, "bdevfs") == 0) result = 0x62646576; else if (strcmp(statfsArgs.f_basetype, "bfs") == 0) result = 0x1BADFACE; + else if (strcmp(statfsArgs.f_basetype, "bpf_fs") == 0) result = 0xCAFE4A11; else if (strcmp(statfsArgs.f_basetype, "binfmt_misc") == 0) result = 0x42494E4D; else if (strcmp(statfsArgs.f_basetype, "bootfs") == 0) result = 0xA56D3FF9; else if (strcmp(statfsArgs.f_basetype, "btrfs") == 0) result = 0x9123683E; @@ -1452,6 +1411,7 @@ int64_t SystemNative_GetFileSystemType(intptr_t fd) else if (strcmp(statfsArgs.f_basetype, "ext2") == 0) result = 0xEF53; else if (strcmp(statfsArgs.f_basetype, "ext3") == 0) result = 0xEF53; else if (strcmp(statfsArgs.f_basetype, "ext4") == 0) result = 0xEF53; + else if (strcmp(statfsArgs.f_basetype, "f2fs") == 0) result = 0xF2F52010; else if (strcmp(statfsArgs.f_basetype, "fat") == 0) result = 0x4006; else if (strcmp(statfsArgs.f_basetype, "fd") == 0) result = 0xF00D1E; else if (strcmp(statfsArgs.f_basetype, "fhgfs") == 0) result = 0x19830326; @@ -1519,6 +1479,7 @@ int64_t SystemNative_GetFileSystemType(intptr_t fd) else if (strcmp(statfsArgs.f_basetype, "sysv2") == 0) result = 0x012FF7B6; else if (strcmp(statfsArgs.f_basetype, "sysv4") == 0) result = 0x012FF7B5; else if (strcmp(statfsArgs.f_basetype, "tmpfs") == 0) result = 0x01021994; + else if (strcmp(statfsArgs.f_basetype, "tracefs") == 0) result = 0x74726163; else if (strcmp(statfsArgs.f_basetype, "ubifs") == 0) result = 0x24051905; else if (strcmp(statfsArgs.f_basetype, "udf") == 0) result = 0x15013346; else if (strcmp(statfsArgs.f_basetype, "ufs") == 0) result = 0x00011954; @@ -1560,13 +1521,21 @@ int32_t SystemNative_LockFileRegion(intptr_t fd, int64_t offset, int64_t length, struct flock lockArgs; #endif +#if defined(TARGET_ANDROID) && defined(HAVE_FLOCK64) + // On Android, fcntl is always implemented by fcntl64 but before https://github.com/aosp-mirror/platform_bionic/commit/09e77f35ab8d291bf88302bb9673aaa518c6bcb0 + // there was no remapping of F_SETLK to F_SETLK64 when _FILE_OFFSET_BITS=64 (which we set in eng/native/configurecompiler.cmake) so we need to always pass F_SETLK64 + int command = F_SETLK64; +#else + int command = F_SETLK; +#endif + lockArgs.l_type = unixLockType; lockArgs.l_whence = SEEK_SET; lockArgs.l_start = (off_t)offset; lockArgs.l_len = (off_t)length; int32_t ret; - while ((ret = fcntl (ToFileDescriptor(fd), F_SETLK, &lockArgs)) < 0 && errno == EINTR); + while ((ret = fcntl (ToFileDescriptor(fd), command, &lockArgs)) < 0 && errno == EINTR); return ret; } diff --git a/src/libraries/Native/Unix/System.Native/pal_io.h b/src/libraries/Native/Unix/System.Native/pal_io.h index 3f0db054d4368b..0e5d4cae2feb8f 100644 --- a/src/libraries/Native/Unix/System.Native/pal_io.h +++ b/src/libraries/Native/Unix/System.Native/pal_io.h @@ -620,11 +620,11 @@ PALEXPORT int32_t SystemNative_Poll(PollEvent* pollEvents, uint32_t eventCount, PALEXPORT int32_t SystemNative_PosixFAdvise(intptr_t fd, int64_t offset, int64_t length, int32_t advice); /** - * Ensures that disk space is allocated. + * Preallocates disk space. * - * Returns -1 on ENOSPC, -2 on EFBIG. On success or ignorable error, 0 is returned. + * Returns 0 for success, -1 for failure. Sets errno on failure. */ -PALEXPORT int32_t SystemNative_PosixFAllocate(intptr_t fd, int64_t offset, int64_t length); +PALEXPORT int32_t SystemNative_FAllocate(intptr_t fd, int64_t offset, int64_t length); /** * Reads the number of bytes specified into the provided buffer from the specified, opened file descriptor. diff --git a/src/libraries/Native/Unix/System.Native/pal_networkstatistics.c b/src/libraries/Native/Unix/System.Native/pal_networkstatistics.c index c0ab5dfc3ad94a..33bb76b1583a90 100644 --- a/src/libraries/Native/Unix/System.Native/pal_networkstatistics.c +++ b/src/libraries/Native/Unix/System.Native/pal_networkstatistics.c @@ -36,6 +36,9 @@ #if HAVE_NET_IFMEDIA_H #include #include +#elif HAVE_IOS_NET_IFMEDIA_H +#include "ios/net/if_media.h" +#include #endif #include #include @@ -44,6 +47,8 @@ #include #if HAVE_NETINET_IP_VAR_H #include +#elif HAVE_IOS_NETINET_IP_VAR_H +#include "ios/netinet/ip_var.h" #endif #include #if HAVE_TCP_FSM_H @@ -53,10 +58,14 @@ #include #if HAVE_NETINET_UDP_VAR_H #include +#elif HAVE_IOS_NETINET_UDP_VAR_H +#include "ios/netinet/udp_var.h" #endif #include #if HAVE_NETINET_ICMP_VAR_H #include +#elif HAVE_IOS_NETINET_ICMP_VAR_H +#include "ios/netinet/icmp_var.h" #endif static _Atomic(int) icmp6statSize = sizeof(struct icmp6stat); @@ -105,7 +114,7 @@ int32_t SystemNative_GetTcpGlobalStatistics(TcpGlobalStatistics* retStats) int32_t SystemNative_GetIPv4GlobalStatistics(IPv4GlobalStatistics* retStats) { -#if HAVE_NETINET_IP_VAR_H +#if HAVE_NETINET_IP_VAR_H || HAVE_IOS_NETINET_IP_VAR_H size_t oldlenp; assert(retStats != NULL); @@ -154,7 +163,7 @@ int32_t SystemNative_GetIPv4GlobalStatistics(IPv4GlobalStatistics* retStats) int32_t SystemNative_GetUdpGlobalStatistics(UdpGlobalStatistics* retStats) { -#if HAVE_NETINET_UDP_VAR_H +#if HAVE_NETINET_UDP_VAR_H || HAVE_IOS_NETINET_UDP_VAR_H size_t oldlenp; assert(retStats != NULL); @@ -194,7 +203,7 @@ int32_t SystemNative_GetUdpGlobalStatistics(UdpGlobalStatistics* retStats) int32_t SystemNative_GetIcmpv4GlobalStatistics(Icmpv4GlobalStatistics* retStats) { -#if HAVE_NETINET_ICMP_VAR_H +#if HAVE_NETINET_ICMP_VAR_H || HAVE_IOS_NETINET_ICMP_VAR_H size_t oldlenp; assert(retStats != NULL); @@ -587,7 +596,7 @@ int32_t SystemNative_GetNativeIPInterfaceStatistics(char* interfaceName, NativeI if (ifHdr->ifm_flags & IFF_UP) { retStats->Flags |= InterfaceUp; -#if HAVE_NET_IFMEDIA_H +#if HAVE_NET_IFMEDIA_H || HAVE_IOS_NET_IFMEDIA_H int fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { retStats->Flags |= InterfaceError; diff --git a/src/libraries/Native/Unix/System.Native/pal_process.c b/src/libraries/Native/Unix/System.Native/pal_process.c index 5e97d958f74d17..fabdfae76187ca 100644 --- a/src/libraries/Native/Unix/System.Native/pal_process.c +++ b/src/libraries/Native/Unix/System.Native/pal_process.c @@ -191,6 +191,24 @@ static int SetGroups(uint32_t* userGroups, int32_t userGroupsLength, uint32_t* p return rv; } +typedef void (*VoidIntFn)(int); + +static +VoidIntFn +handler_from_sigaction (struct sigaction *sa) +{ + if (((unsigned int)sa->sa_flags) & SA_SIGINFO) + { + // work around -Wcast-function-type + void (*tmp)(void) = (void (*)(void))sa->sa_sigaction; + return (void (*)(int))tmp; + } + else + { + return sa->sa_handler; + } +} + int32_t SystemNative_ForkAndExecProcess(const char* filename, char* const argv[], char* const envp[], @@ -371,7 +389,7 @@ int32_t SystemNative_ForkAndExecProcess(const char* filename, } if (!sigaction(sig, NULL, &sa_old)) { - void (*oldhandler)(int) = (((unsigned int)sa_old.sa_flags) & SA_SIGINFO) ? (void (*)(int))sa_old.sa_sigaction : sa_old.sa_handler; + void (*oldhandler)(int) = handler_from_sigaction (&sa_old); if (oldhandler != SIG_IGN && oldhandler != SIG_DFL) { // It has a custom handler, put the default handler back. diff --git a/src/libraries/Native/Unix/System.Native/pal_searchpath.c b/src/libraries/Native/Unix/System.Native/pal_searchpath.c index fbf3d903df01c7..de8037dc1a2959 100644 --- a/src/libraries/Native/Unix/System.Native/pal_searchpath.c +++ b/src/libraries/Native/Unix/System.Native/pal_searchpath.c @@ -10,3 +10,9 @@ const char* SystemNative_SearchPath(int32_t folderId) __builtin_unreachable(); return NULL; } + +const char* SystemNative_SearchPath_TempDirectory() +{ + __builtin_unreachable(); + return NULL; +} diff --git a/src/libraries/Native/Unix/System.Native/pal_searchpath.h b/src/libraries/Native/Unix/System.Native/pal_searchpath.h index e2de05d8c8860a..cdb872914624ca 100644 --- a/src/libraries/Native/Unix/System.Native/pal_searchpath.h +++ b/src/libraries/Native/Unix/System.Native/pal_searchpath.h @@ -7,3 +7,5 @@ #include "pal_types.h" PALEXPORT const char* SystemNative_SearchPath(int32_t folderId); + +PALEXPORT const char* SystemNative_SearchPath_TempDirectory(void); diff --git a/src/libraries/Native/Unix/System.Native/pal_searchpath.m b/src/libraries/Native/Unix/System.Native/pal_searchpath.m index 2e96041f3dda82..231c508c527cab 100644 --- a/src/libraries/Native/Unix/System.Native/pal_searchpath.m +++ b/src/libraries/Native/Unix/System.Native/pal_searchpath.m @@ -11,3 +11,10 @@ const char* path = [[url path] UTF8String]; return path == NULL ? NULL : strdup (path); } + +const char* SystemNative_SearchPath_TempDirectory() +{ + NSString* tempPath = NSTemporaryDirectory(); + const char *path = [tempPath UTF8String]; + return path == NULL ? NULL : strdup (path); +} diff --git a/src/libraries/Native/Unix/System.Native/pal_signal.h b/src/libraries/Native/Unix/System.Native/pal_signal.h index 146fdabbfceb14..c3c21009dc836c 100644 --- a/src/libraries/Native/Unix/System.Native/pal_signal.h +++ b/src/libraries/Native/Unix/System.Native/pal_signal.h @@ -40,8 +40,8 @@ typedef enum PosixSignalSIGQUIT = -3, PosixSignalSIGTERM = -4, PosixSignalSIGCHLD = -5, - PosixSignalSIGWINCH = -6, - PosixSignalSIGCONT = -7, + PosixSignalSIGCONT = -6, + PosixSignalSIGWINCH = -7, PosixSignalSIGTTIN = -8, PosixSignalSIGTTOU = -9, PosixSignalSIGTSTP = -10 diff --git a/src/libraries/Native/Unix/System.Native/pal_tcpstate.c b/src/libraries/Native/Unix/System.Native/pal_tcpstate.c index 5b428ba6c8f11b..db5f775164c4c8 100644 --- a/src/libraries/Native/Unix/System.Native/pal_tcpstate.c +++ b/src/libraries/Native/Unix/System.Native/pal_tcpstate.c @@ -7,6 +7,8 @@ #if HAVE_TCP_FSM_H #include +#elif HAVE_IOS_NETINET_TCPFSM_H +#include "ios/netinet/tcp_fsm.h" #elif HAVE_TCP_H_TCPSTATE_ENUM #include #endif @@ -15,7 +17,7 @@ int32_t SystemNative_MapTcpState(int32_t tcpState) { switch (tcpState) { -#if HAVE_TCP_FSM_H +#if HAVE_TCP_FSM_H || HAVE_IOS_NETINET_TCPFSM_H case TCPS_CLOSED: return TcpState_Closed; case TCPS_LISTEN: diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index d5b0e0bcdda1b3..ef84a024777d3c 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -123,7 +123,7 @@ static void* volatile s_gssLib = NULL; #define GSS_C_NT_HOSTBASED_SERVICE (*GSS_C_NT_HOSTBASED_SERVICE_ptr) #define gss_mech_krb5 (*gss_mech_krb5_ptr) -#define gss_lib_name "libgssapi_krb5.so" +#define gss_lib_name "libgssapi_krb5.so.2" static int32_t ensure_gss_shim_initialized() { diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c index 4b95faf7a191bd..d9054e5c46f33a 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Android/pal_sslstream.c @@ -585,13 +585,14 @@ AndroidCryptoNative_SSLStreamRead(SSLStream* sslStream, uint8_t* buffer, int32_t if (rem > 0) { - data = make_java_byte_array(env, rem); + int32_t bytes_to_read = rem < length ? rem : length; + data = make_java_byte_array(env, bytes_to_read); IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferGet, data)); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); IGNORE_RETURN((*env)->CallObjectMethod(env, sslStream->appInBuffer, g_ByteBufferCompact)); ON_EXCEPTION_PRINT_AND_GOTO(cleanup); - (*env)->GetByteArrayRegion(env, data, 0, rem, (jbyte*)buffer); - *read = rem; + (*env)->GetByteArrayRegion(env, data, 0, bytes_to_read, (jbyte*)buffer); + *read = bytes_to_read; ret = SSLStreamStatus_OK; } else diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.c index 2d66847c1731b3..0770a946bee1ed 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ssl.c @@ -596,19 +596,19 @@ int32_t AppleCryptoNative_SslSetEnabledCipherSuites(SSLContextRef sslContext, co // Max numCipherSuites is 2^16 (all possible cipher suites) assert(numCipherSuites < (1 << 16)); -#if !defined(TARGET_MACCATALYST) && !defined(TARGET_IOS) && !defined(TARGET_TVOS) +#if !defined(TARGET_ARM64) && !defined(TARGET_IOS) && !defined(TARGET_TVOS) if (sizeof(SSLCipherSuite) == sizeof(uint32_t)) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - // macOS + // macOS & MacCatalyst x64 return SSLSetEnabledCiphers(sslContext, (const SSLCipherSuite *)cipherSuites, (size_t)numCipherSuites); #pragma clang diagnostic pop } else #endif { - // MacCatalyst, iOS, tvOS, watchOS + // MacCatalyst arm64, iOS, tvOS, watchOS SSLCipherSuite* cipherSuites16 = (SSLCipherSuite*)calloc((size_t)numCipherSuites, sizeof(SSLCipherSuite)); if (cipherSuites16 == NULL) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509chain.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509chain.c index ec12984bb3a9c5..06f09cfd9f47a8 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509chain.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native.Apple/pal_x509chain.c @@ -195,7 +195,7 @@ static void MergeStatusCodes(CFTypeRef key, CFTypeRef value, void* context) } else if (CFEqual(keyString, CFSTR("NonEmptySubject")) || CFEqual(keyString, CFSTR("GrayListedKey")) || CFEqual(keyString, CFSTR("CTRequired")) || CFEqual(keyString, CFSTR("GrayListedLeaf")) || - CFEqual(keyString, CFSTR("IdLinkage"))) + CFEqual(keyString, CFSTR("IdLinkage")) || CFEqual(keyString, CFSTR("DuplicateExtension"))) { // Not a "problem" that we report. } diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c index ad93dbf74d87d7..c18eb0ffb7c6bb 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c @@ -564,7 +564,7 @@ BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssue if (answer) { BIO* b = BIO_new(BIO_s_mem()); - ASN1_STRING_print_ex(b, answer, 0); + ASN1_STRING_print_ex(b, answer, ASN1_STRFLGS_UTF8_CONVERT); return b; } } @@ -646,7 +646,7 @@ BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssue if (str) { BIO* b = BIO_new(BIO_s_mem()); - ASN1_STRING_print_ex(b, str, 0); + ASN1_STRING_print_ex(b, str, ASN1_STRFLGS_UTF8_CONVERT); sk_GENERAL_NAME_free(altNames); return b; } @@ -1068,27 +1068,30 @@ int32_t CryptoNative_LookupFriendlyNameByOid(const char* oidValue, const char** return -2; } + // First, check if oidValue parses as a dotted decimal OID. If not, we'll + // return not-found and let the system cache that. + int asnRet = a2d_ASN1_OBJECT(NULL, 0, oidValue, -1); + + if (asnRet <= 0) + { + return 0; + } + // Do a lookup with no_name set. The purpose of this function is to map only the // dotted decimal to the friendly name. "sha1" in should not result in "sha1" out. oid = OBJ_txt2obj(oidValue, 1); - if (!oid) + if (oid == NULL) { - unsigned long err = ERR_peek_last_error(); - - // If the most recent error pushed onto the error queue is NOT from OID parsing - // then signal for an exception to be thrown. - if (err != 0 && ERR_GET_FUNC(err) != ASN1_F_A2D_ASN1_OBJECT) - { - return -1; - } - - return 0; + // We know that the OID parsed (unless it underwent concurrent modification, + // which is unsupported), so any error in this stage should be an exception. + return -1; } // Look in the predefined, and late-registered, OIDs list to get the lookup table // identifier for this OID. The OBJ_txt2obj object will not have ln set. nid = OBJ_obj2nid(oid); + ASN1_OBJECT_free(oid); if (nid == NID_undef) { diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h index 69c95b532ade08..58063bde6c7027 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h @@ -159,6 +159,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); // that needs to be added. #define FOR_ALL_OPENSSL_FUNCTIONS \ + REQUIRED_FUNCTION(a2d_ASN1_OBJECT) \ REQUIRED_FUNCTION(ASN1_BIT_STRING_free) \ REQUIRED_FUNCTION(ASN1_d2i_bio) \ REQUIRED_FUNCTION(ASN1_i2d_bio) \ @@ -269,6 +270,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); LEGACY_FUNCTION(ERR_load_crypto_strings) \ LIGHTUP_FUNCTION(ERR_new) \ REQUIRED_FUNCTION(ERR_peek_error) \ + REQUIRED_FUNCTION(ERR_peek_error_line) \ REQUIRED_FUNCTION(ERR_peek_last_error) \ FALLBACK_FUNCTION(ERR_put_error) \ REQUIRED_FUNCTION(ERR_reason_error_string) \ @@ -607,6 +609,7 @@ FOR_ALL_OPENSSL_FUNCTIONS // Redefine all calls to OpenSSL functions as calls through pointers that are set // to the functions from the libssl.so selected by the shim. +#define a2d_ASN1_OBJECT a2d_ASN1_OBJECT_ptr #define ASN1_BIT_STRING_free ASN1_BIT_STRING_free_ptr #define ASN1_GENERALIZEDTIME_free ASN1_GENERALIZEDTIME_free_ptr #define ASN1_d2i_bio ASN1_d2i_bio_ptr @@ -717,6 +720,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define ERR_load_crypto_strings ERR_load_crypto_strings_ptr #define ERR_new ERR_new_ptr #define ERR_peek_error ERR_peek_error_ptr +#define ERR_peek_error_line ERR_peek_error_line_ptr #define ERR_peek_last_error ERR_peek_last_error_ptr #define ERR_put_error ERR_put_error_ptr #define ERR_reason_error_string ERR_reason_error_string_ptr diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.c index 6839d4c2fe04ef..79de386f097215 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.c @@ -152,20 +152,59 @@ EVP_PKEY* CryptoNative_DecodePkcs8PrivateKey(const uint8_t* buf, int32_t len, in return key; } -int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey) +int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey, int32_t* p8size) { assert(pkey != NULL); + assert(p8size != NULL); + + *p8size = 0; + ERR_clear_error(); PKCS8_PRIV_KEY_INFO* p8 = EVP_PKEY2PKCS8(pkey); if (p8 == NULL) { + // OpenSSL 1.1 and 3 have a behavioral change with EVP_PKEY2PKCS8 + // with regard to handling EVP_PKEYs that do not contain a private key. + // + // In OpenSSL 1.1, it would always succeed, but the private parameters + // would be missing (thus making an invalid PKCS8 structure). + // Over in the managed side, we detect these invalid PKCS8 blobs and + // convert that to a "no private key" error. + // + // In OpenSSL 3, this now correctly errors, with the error + // ASN1_R_ILLEGAL_ZERO_CONTENT. We want to preserve allocation failures + // as OutOfMemoryException. So we peek at the error. If it's a malloc + // failure, -1 is returned to indcate "throw what is on the error queue". + // If the error is not a malloc failure, return -2 to mean "no private key". + // If OpenSSL ever changes the error to something more to explicitly mean + // "no private key" then we should test for that explicitly. Until then, + // we treat all errors, except a malloc error, to mean "no private key". + + const char* file = NULL; + int line = 0; + unsigned long error = ERR_peek_error_line(&file, &line); + + // If it's not a malloc failure, assume it's because the private key is + // missing. + if (ERR_GET_REASON(error) != ERR_R_MALLOC_FAILURE) + { + ERR_clear_error(); + return -2; + } + + // It is a malloc failure. Clear the error queue and set the error + // as a malloc error so it's the only error in the queue. + ERR_clear_error(); + ERR_put_error(ERR_GET_LIB(error), 0, ERR_R_MALLOC_FAILURE, file, line); + return -1; } - int ret = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL); + *p8size = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL); PKCS8_PRIV_KEY_INFO_free(p8); - return ret; + + return *p8size < 0 ? -1 : 1; } int32_t CryptoNative_EncodePkcs8PrivateKey(EVP_PKEY* pkey, uint8_t* buf) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h index 012ac98e03db20..fac7ee32b5bbcc 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey.h @@ -58,9 +58,13 @@ Requres a non-null buf, and len > 0. PALEXPORT EVP_PKEY* CryptoNative_DecodePkcs8PrivateKey(const uint8_t* buf, int32_t len, int32_t algId); /* -Reports the number of bytes rqeuired to encode an EVP_PKEY* as a Pkcs8PrivateKeyInfo, or a negative value on error. +Gets the number of bytes rqeuired to encode an EVP_PKEY* as a Pkcs8PrivateKeyInfo. + +On success, 1 is returned and p8size contains the size of the Pkcs8PrivateKeyInfo. +On failure, -1 is used to indicate the openssl error queue contains the error. +On failure, -2 is used to indcate that the supplied EVP_PKEY* is possibly missing a private key. */ -PALEXPORT int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey); +PALEXPORT int32_t CryptoNative_GetPkcs8PrivateKeySize(EVP_PKEY* pkey, int32_t* p8size); /* Encodes the EVP_PKEY* as a Pkcs8PrivateKeyInfo, writing the encoded value to buf. diff --git a/src/libraries/Native/Unix/configure.cmake b/src/libraries/Native/Unix/configure.cmake index 18afacc2dbc59c..e00b35d0f9e1f1 100644 --- a/src/libraries/Native/Unix/configure.cmake +++ b/src/libraries/Native/Unix/configure.cmake @@ -7,6 +7,7 @@ include(CheckStructHasMember) include(CheckSymbolExists) include(CheckTypeSize) include(CheckLibraryExists) +include(CheckFunctionExists) # CMP0075 Include file check macros honor CMAKE_REQUIRED_LIBRARIES. if(POLICY CMP0075) @@ -141,6 +142,18 @@ check_c_source_compiles( " HAVE_FLOCK64) +check_c_source_compiles( + " + #include + #include + int main(void) + { + struct ifaddrs ia; + return 0; + } + " + HAVE_IFADDRS) + check_symbol_exists( O_CLOEXEC fcntl.h @@ -156,9 +169,8 @@ check_symbol_exists( fcntl.h HAVE_F_FULLFSYNC) -check_symbol_exists( +check_function_exists( getifaddrs - ifaddrs.h HAVE_GETIFADDRS) check_symbol_exists( @@ -232,14 +244,9 @@ check_symbol_exists( HAVE_POSIX_ADVISE) check_symbol_exists( - posix_fallocate - fcntl.h - HAVE_POSIX_FALLOCATE) - -check_symbol_exists( - posix_fallocate64 + fallocate fcntl.h - HAVE_POSIX_FALLOCATE64) + HAVE_FALLOCATE) check_symbol_exists( preadv @@ -879,7 +886,15 @@ check_symbol_exists( if(CLR_CMAKE_TARGET_MACCATALYST OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS) set(HAVE_IOS_NET_ROUTE_H 1) - set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h "${CMAKE_CURRENT_SOURCE_DIR}/System.Native/ios/net/route.h") + set(HAVE_IOS_NET_IFMEDIA_H 1) + set(HAVE_IOS_NETINET_TCPFSM_H 1) + set(HAVE_IOS_NETINET_IP_VAR_H 1) + set(HAVE_IOS_NETINET_ICMP_VAR_H 1) + set(HAVE_IOS_NETINET_UDP_VAR_H 1) + set(CMAKE_EXTRA_INCLUDE_FILES + sys/types.h + "${CMAKE_CURRENT_SOURCE_DIR}/System.Native/ios/net/route.h" + ) else() set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h net/if.h net/route.h) endif() diff --git a/src/libraries/System.CodeDom/src/CompatibilitySuppressions.xml b/src/libraries/System.CodeDom/src/CompatibilitySuppressions.xml deleted file mode 100644 index 292caf8b32fd1a..00000000000000 --- a/src/libraries/System.CodeDom/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - CP0001 - lib/netstandard2.0/System.CodeDom.dll - lib/net461/System.CodeDom.dll - - \ No newline at end of file diff --git a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs index aa1912cdb0f9d7..c78333ddf64333 100644 --- a/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs +++ b/src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs @@ -6,15 +6,12 @@ namespace System.ComponentModel.DataAnnotations { - // TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated -#nullable disable public partial class AssociatedMetadataTypeTypeDescriptionProvider : System.ComponentModel.TypeDescriptionProvider { public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type) { } public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type associatedMetadataType) { } - public override System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType, object instance) { throw null; } + public override System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type objectType, object? instance) { throw null; } } -#nullable enable [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] [System.ObsoleteAttribute("AssociationAttribute has been deprecated and is not supported.")] public sealed partial class AssociationAttribute : System.Attribute diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs index a408e38342083e..fbfe36a6c888b8 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated -#nullable disable - using System.Diagnostics.CodeAnalysis; namespace System.ComponentModel.DataAnnotations @@ -15,7 +12,7 @@ namespace System.ComponentModel.DataAnnotations public class AssociatedMetadataTypeTypeDescriptionProvider : TypeDescriptionProvider { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - private readonly Type _associatedMetadataType; + private readonly Type? _associatedMetadataType; /// /// Initializes a new instance of the System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProvider @@ -53,9 +50,9 @@ public AssociatedMetadataTypeTypeDescriptionProvider( /// The type of object to retrieve the type descriptor for. /// An instance of the type. /// The descriptor that provides metadata for the type. - public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object instance) + public override ICustomTypeDescriptor GetTypeDescriptor([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type objectType, object? instance) { - ICustomTypeDescriptor baseDescriptor = base.GetTypeDescriptor(objectType, instance); + ICustomTypeDescriptor? baseDescriptor = base.GetTypeDescriptor(objectType, instance); return new AssociatedMetadataTypeTypeDescriptor(baseDescriptor, objectType, _associatedMetadataType); } } diff --git a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs index 5c49bd6062f710..ab8b86b13161df 100644 --- a/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs +++ b/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated -#nullable disable - using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -15,14 +12,14 @@ namespace System.ComponentModel.DataAnnotations internal sealed class AssociatedMetadataTypeTypeDescriptor : CustomTypeDescriptor { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - private Type AssociatedMetadataType { get; set; } + private Type? AssociatedMetadataType { get; set; } private bool IsSelfAssociated { get; set; } public AssociatedMetadataTypeTypeDescriptor( - ICustomTypeDescriptor parent, + ICustomTypeDescriptor? parent, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] Type type, - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type associatedMetadataType) + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? associatedMetadataType) : base(parent) { AssociatedMetadataType = associatedMetadataType ?? TypeDescriptorCache.GetAssociatedMetadataType(type); @@ -34,7 +31,7 @@ public AssociatedMetadataTypeTypeDescriptor( } [RequiresUnreferencedCode("PropertyDescriptor's PropertyType cannot be statically discovered. The public parameterless constructor or the 'Default' static field may be trimmed from the Attribute's Type.")] - public override PropertyDescriptorCollection GetProperties(Attribute[] attributes) + public override PropertyDescriptorCollection GetProperties(Attribute[]? attributes) { return GetPropertiesWithMetadata(base.GetProperties(attributes)); } @@ -96,7 +93,7 @@ public override AttributeCollection GetAttributes() private static class TypeDescriptorCache { // Stores the associated metadata type for a type - private static readonly ConcurrentDictionary s_metadataTypeCache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary s_metadataTypeCache = new ConcurrentDictionary(); // Stores the attributes for a member info private static readonly ConcurrentDictionary<(Type, string), Attribute[]> s_typeMemberCache = new ConcurrentDictionary<(Type, string), Attribute[]>(); @@ -117,16 +114,16 @@ public static void ValidateMetadataType( } [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - public static Type GetAssociatedMetadataType(Type type) + public static Type? GetAssociatedMetadataType(Type type) { - Type associatedMetadataType = null; + Type? associatedMetadataType; if (s_metadataTypeCache.TryGetValue(type, out associatedMetadataType)) { return associatedMetadataType; } // Try association attribute - MetadataTypeAttribute attribute = (MetadataTypeAttribute)Attribute.GetCustomAttribute(type, typeof(MetadataTypeAttribute)); + MetadataTypeAttribute? attribute = (MetadataTypeAttribute?)Attribute.GetCustomAttribute(type, typeof(MetadataTypeAttribute)); if (attribute != null) { associatedMetadataType = attribute.MetadataClassType; @@ -164,7 +161,7 @@ public static Attribute[] GetAssociatedMetadata( string memberName) { (Type, string) memberTuple = (type, memberName); - Attribute[] attributes; + Attribute[]? attributes; if (s_typeMemberCache.TryGetValue(memberTuple, out attributes)) { return attributes; @@ -175,7 +172,7 @@ public static Attribute[] GetAssociatedMetadata( // Only public static/instance members BindingFlags searchFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; // Try to find a matching member on type - MemberInfo matchingMember = type.GetMember(memberName, allowedMemberTypes, searchFlags).FirstOrDefault(); + MemberInfo? matchingMember = type.GetMember(memberName, allowedMemberTypes, searchFlags).FirstOrDefault(); if (matchingMember != null) { attributes = Attribute.GetCustomAttributes(matchingMember, true /* inherit */); diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml b/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml index 5441f0c558b51a..f1cdac2f6519bb 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml @@ -1,7 +1,38 @@  - CP0001 + CP0002 + M:System.Configuration.SettingsAttributeDictionary.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext) + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/net461/System.Configuration.ConfigurationManager.dll + + + CP0002 + M:System.Configuration.SettingsContext.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext) + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/net461/System.Configuration.ConfigurationManager.dll + + + CP0002 + M:System.Configuration.Internal.DelegatingConfigHost.RefreshConfigPaths + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/net461/System.Configuration.ConfigurationManager.dll + + + CP0002 + M:System.Configuration.Internal.DelegatingConfigHost.get_HasLocalConfig + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/net461/System.Configuration.ConfigurationManager.dll + + + CP0002 + M:System.Configuration.Internal.DelegatingConfigHost.get_HasRoamingConfig + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/net461/System.Configuration.ConfigurationManager.dll + + + CP0002 + M:System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp lib/netstandard2.0/System.Configuration.ConfigurationManager.dll lib/net461/System.Configuration.ConfigurationManager.dll diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj index 302b9688391665..92cadbe1711a78 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System.Configuration.ConfigurationManager.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);netstandard2.0;net461 + $(NetCoreAppCurrent);netstandard2.0;net461-windows false $(NoWarn);CA1847 diff --git a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj index 975159597c1bb9..4c5895f0a26c90 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj +++ b/src/libraries/System.Configuration.ConfigurationManager/tests/System.Configuration.ConfigurationManager.Tests.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent);net461 + $(NetCoreAppCurrent);net461-windows true diff --git a/src/libraries/System.Console/src/System.Console.csproj b/src/libraries/System.Console/src/System.Console.csproj index c464007dc95e95..6cbdc48890bb04 100644 --- a/src/libraries/System.Console/src/System.Console.csproj +++ b/src/libraries/System.Console/src/System.Console.csproj @@ -13,6 +13,7 @@ + buffer) => throw Error.GetReadNotSupported(); - - public override unsafe void Write(ReadOnlySpan buffer) + protected override void Print(ReadOnlySpan line) { - string log = ConsolePal.OutputEncoding.GetString(buffer); + string log = line.ToString(); Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Info, "DOTNET", log); } } @@ -26,9 +24,9 @@ internal static void EnsureConsoleInitialized() { } public static Stream OpenStandardInput() => throw new PlatformNotSupportedException(); - public static Stream OpenStandardOutput() => new LogcatStream(); + public static Stream OpenStandardOutput() => new LogcatStream(OutputEncoding); - public static Stream OpenStandardError() => new LogcatStream(); + public static Stream OpenStandardError() => new LogcatStream(OutputEncoding); public static Encoding InputEncoding => throw new PlatformNotSupportedException(); diff --git a/src/libraries/System.Console/src/System/ConsolePal.iOS.cs b/src/libraries/System.Console/src/System/ConsolePal.iOS.cs index 5279df26401d04..8794d55aeff86d 100644 --- a/src/libraries/System.Console/src/System/ConsolePal.iOS.cs +++ b/src/libraries/System.Console/src/System/ConsolePal.iOS.cs @@ -1,22 +1,22 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; +using System.Diagnostics; using System.IO; using System.Text; namespace System { - internal sealed class NSLogStream : ConsoleStream + internal sealed class NSLogStream : CachedConsoleStream { - public NSLogStream() : base(FileAccess.Write) {} + public NSLogStream(Encoding encoding) : base(encoding) {} - public override int Read(Span buffer) => throw Error.GetReadNotSupported(); - - public override unsafe void Write(ReadOnlySpan buffer) + protected override unsafe void Print(ReadOnlySpan line) { - fixed (byte* ptr = buffer) + fixed (char* ptr = line) { - Interop.Sys.Log(ptr, buffer.Length); + Interop.Sys.Log((byte*)ptr, line.Length * 2); } } } @@ -28,9 +28,9 @@ internal static void EnsureConsoleInitialized() public static Stream OpenStandardInput() => throw new PlatformNotSupportedException(); - public static Stream OpenStandardOutput() => new NSLogStream(); + public static Stream OpenStandardOutput() => new NSLogStream(OutputEncoding); - public static Stream OpenStandardError() => new NSLogStream(); + public static Stream OpenStandardError() => new NSLogStream(OutputEncoding); public static Encoding InputEncoding => throw new PlatformNotSupportedException(); diff --git a/src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs b/src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs new file mode 100644 index 00000000000000..6aacda65a082a3 --- /dev/null +++ b/src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Diagnostics; +using System.IO; +using System.Text; + +namespace System.IO +{ + internal abstract class CachedConsoleStream : ConsoleStream + { + private readonly StringBuilder _buffer = new StringBuilder(); + private readonly Encoding _encoding; + private readonly Decoder _decoder; + + public CachedConsoleStream(Encoding encoding) : base(FileAccess.Write) + { + _encoding = encoding; + _decoder = _encoding.GetDecoder(); + } + + public override int Read(Span buffer) => throw Error.GetReadNotSupported(); + + public override void Write(ReadOnlySpan buffer) + { + int maxCharCount = _encoding.GetMaxCharCount(buffer.Length); + char[]? pooledBuffer = null; + Span charSpan = maxCharCount <= 512 ? stackalloc char[512] : (pooledBuffer = ArrayPool.Shared.Rent(maxCharCount)); + try + { + int count = _decoder.GetChars(buffer, charSpan, false); + if (count > 0) + { + WriteOrCache(this, _buffer, charSpan.Slice(0, count)); + } + } + finally + { + if (pooledBuffer != null) + { + ArrayPool.Shared.Return(pooledBuffer); + } + } + } + + protected abstract void Print(ReadOnlySpan line); + + private static void WriteOrCache(CachedConsoleStream stream, StringBuilder cache, Span charBuffer) + { + int lastNewLine = charBuffer.LastIndexOf('\n'); + if (lastNewLine != -1) + { + Span lineSpan = charBuffer.Slice(0, lastNewLine); + if (cache.Length > 0) + { + stream.Print(cache.Append(lineSpan).ToString()); + cache.Clear(); + } + else + { + stream.Print(lineSpan); + } + + if (lastNewLine + 1 < charBuffer.Length) + { + cache.Append(charBuffer.Slice(lastNewLine + 1)); + } + + return; + } + + // no newlines found, add the entire buffer to the cache + cache.Append(charBuffer); + } + } +} diff --git a/src/libraries/System.Console/tests/ReadAndWrite.cs b/src/libraries/System.Console/tests/ReadAndWrite.cs index 6fd77d6afa9918..c671e4f90313f0 100644 --- a/src/libraries/System.Console/tests/ReadAndWrite.cs +++ b/src/libraries/System.Console/tests/ReadAndWrite.cs @@ -194,6 +194,25 @@ public static async Task OutWriteAndWriteLineOverloads() } } + [Fact] + [PlatformSpecific(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS)] + public void TestConsoleWrite() + { + Stream s = new MemoryStream(); + TextWriter w = new StreamWriter(s); + ((StreamWriter)w).AutoFlush = true; + TextReader r = new StreamReader(s); + Console.SetOut(w); + + Console.Write("A"); + Console.Write("B"); + Console.Write("C"); + + s.Position = 0; + string line = r.ReadToEnd(); + Assert.Equal("ABC", line); + } + private static unsafe void ValidateConsoleEncoding(Encoding encoding) { Assert.NotNull(encoding); diff --git a/src/libraries/System.Data.Odbc/src/CompatibilitySuppressions.xml b/src/libraries/System.Data.Odbc/src/CompatibilitySuppressions.xml index 627b6d1f8addb7..e20e47d1100c30 100644 --- a/src/libraries/System.Data.Odbc/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Data.Odbc/src/CompatibilitySuppressions.xml @@ -1,9 +1,16 @@  - CP0001 - lib/netstandard2.0/System.Data.Odbc.dll - lib/net461/System.Data.Odbc.dll + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + lib/net6.0/System.Data.Odbc.dll + runtimes/win/lib/net6.0/System.Data.Odbc.dll + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + lib/net6.0/System.Data.Odbc.dll + runtimes/win/lib/net6.0/System.Data.Odbc.dll CP0002 @@ -92,14 +99,14 @@ CP0002 M:System.Data.Odbc.OdbcParameter.get_Offset - lib/net6.0/System.Data.Odbc.dll - runtimes/win/lib/net6.0/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll + runtimes/win/lib/netcoreapp3.1/System.Data.Odbc.dll CP0002 M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) - lib/net6.0/System.Data.Odbc.dll - runtimes/win/lib/net6.0/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll + runtimes/win/lib/netcoreapp3.1/System.Data.Odbc.dll CP0002 @@ -140,97 +147,169 @@ CP0002 M:System.Data.Odbc.OdbcParameter.get_Offset - lib/netcoreapp3.1/System.Data.Odbc.dll - runtimes/win/lib/netcoreapp3.1/System.Data.Odbc.dll + runtimes/freebsd/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true CP0002 M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) - lib/netcoreapp3.1/System.Data.Odbc.dll - runtimes/win/lib/netcoreapp3.1/System.Data.Odbc.dll + runtimes/freebsd/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/illumos/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/illumos/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/ios/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/ios/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true - CP0001 - T:System.Data.Odbc.ODBC32 - runtimes/freebsd/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/linux/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/linux/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.get_Offset - runtimes/freebsd/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/osx/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) - runtimes/freebsd/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/osx/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll true - CP0001 - T:System.Data.Odbc.ODBC32 - runtimes/linux/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/solaris/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/solaris/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.get_Offset - runtimes/linux/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/tvos/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) - runtimes/linux/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/tvos/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll true - CP0001 - T:System.Data.Odbc.ODBC32 - runtimes/osx/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/win/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/win/lib/net6.0/System.Data.Odbc.dll + lib/net6.0/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/freebsd/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/freebsd/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.get_Offset - runtimes/osx/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/linux/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) - runtimes/osx/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/linux/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll + true + + + CP0002 + M:System.Data.Odbc.OdbcParameter.get_Offset + runtimes/osx/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll true - CP0001 - T:System.Data.Odbc.ODBC32 - runtimes/win/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + CP0002 + M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) + runtimes/osx/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.get_Offset - runtimes/win/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/win/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll true CP0002 M:System.Data.Odbc.OdbcParameter.set_Offset(System.Int32) - runtimes/win/lib/netcoreapp2.0/System.Data.Odbc.dll - lib/netstandard2.0/System.Data.Odbc.dll + runtimes/win/lib/netcoreapp3.1/System.Data.Odbc.dll + lib/netcoreapp3.1/System.Data.Odbc.dll true \ No newline at end of file diff --git a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj index 628b8d1e9e0452..eff55039c3e9f4 100644 --- a/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj +++ b/src/libraries/System.Data.Odbc/src/System.Data.Odbc.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent);netcoreapp3.1-windows;netcoreapp3.1-FreeBSD;netcoreapp3.1-Linux;netcoreapp3.1-OSX;netcoreapp3.1;netstandard2.0;net461 + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent);netcoreapp3.1-windows;netcoreapp3.1-FreeBSD;netcoreapp3.1-Linux;netcoreapp3.1-OSX;netcoreapp3.1;netstandard2.0;net461-windows $(NoWarn);CA2249;CA1838 enable true diff --git a/src/libraries/System.Data.OleDb/ref/System.Data.OleDb.csproj b/src/libraries/System.Data.OleDb/ref/System.Data.OleDb.csproj index 4cc65fb4368cf9..370bfcc6896694 100644 --- a/src/libraries/System.Data.OleDb/ref/System.Data.OleDb.csproj +++ b/src/libraries/System.Data.OleDb/ref/System.Data.OleDb.csproj @@ -23,7 +23,6 @@ - diff --git a/src/libraries/System.Data.OleDb/src/CompatibilitySuppressions.xml b/src/libraries/System.Data.OleDb/src/CompatibilitySuppressions.xml deleted file mode 100644 index 3bdc38c1743f04..00000000000000 --- a/src/libraries/System.Data.OleDb/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - CP0001 - lib/netstandard2.0/System.Data.OleDb.dll - lib/net461/System.Data.OleDb.dll - - \ No newline at end of file diff --git a/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj b/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj index a5e9b248302241..94d1b0e1b88bbc 100644 --- a/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj +++ b/src/libraries/System.Data.OleDb/src/System.Data.OleDb.csproj @@ -152,8 +152,6 @@ System.Data.OleDb.OleDbTransaction - - diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs index c7b92ad12ff2de..b598a75fa85e81 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs @@ -1345,7 +1345,19 @@ public static PropertyFetch FetcherForProperty(Type? type, string propertyName) } else { - PropertyInfo? propertyInfo = typeInfo.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + PropertyInfo? propertyInfo = typeInfo.GetDeclaredProperty(propertyName); + if (propertyInfo == null) + { + foreach (PropertyInfo pi in typeInfo.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) + { + if (pi.Name == propertyName) + { + propertyInfo = pi; + break; + } + } + } + if (propertyInfo == null) { Log.Message($"Property {propertyName} not found on {type}. Ensure the name is spelled correctly. If you published the application with PublishTrimmed=true, ensure the property was not trimmed away."); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs index c6f16f634022c5..b3fb43640498b9 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/DiagnosticSourceEventSourceBridgeTests.cs @@ -524,6 +524,39 @@ public void TestBaseClassProperties() }).Dispose(); } + /// + /// Tests that DiagnosticSourceEventSource can read property values from base classes + /// + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void TestBaseClassDuplicateProperties() + { + RemoteExecutor.Invoke(() => + { + using (var eventSourceListener = new TestDiagnosticSourceEventListener()) + using (var diagnosticSourceListener = new DiagnosticListener("TestBaseClassProperties")) + { + Assert.Equal(0, eventSourceListener.EventCount); + eventSourceListener.Enable( + " TestBaseClassProperties/TestEvent1:Point_X=Point.X;Point_Y=Point.Y;Url=Url\r\n"); + + /***************************************************************************************/ + // Emit an event that matches the first pattern. + MyClass val = new MyOtherDerivedClass() { Url = "MyUrl", Point = new MyDerivedPoint() { X = 3, Y = 5 } }; + if (diagnosticSourceListener.IsEnabled("TestEvent1")) + diagnosticSourceListener.Write("TestEvent1", val); + + Assert.Equal(1, eventSourceListener.EventCount); // Exactly one more event has been emitted. + Assert.Equal("TestBaseClassProperties", eventSourceListener.LastEvent.SourceName); + Assert.Equal("TestEvent1", eventSourceListener.LastEvent.EventName); + Assert.Equal(4, eventSourceListener.LastEvent.Arguments.Count); + Assert.Equal("3", eventSourceListener.LastEvent.Arguments["Point_X"]); + Assert.Equal("5", eventSourceListener.LastEvent.Arguments["Point_Y"]); + Assert.Equal("MyUrl", eventSourceListener.LastEvent.Arguments["Url"]); + eventSourceListener.ResetEventCountAndLastEvent(); + } + }).Dispose(); + } + /// /// Test that things work properly for Linux newline conventions. /// @@ -1353,6 +1386,11 @@ internal class MyDerivedClass : MyClass public string AnotherString { get; set; } } + internal class MyOtherDerivedClass : MyClass + { + public new MyDerivedPoint Point { get; set; } + } + /// /// classes for test data. /// @@ -1362,6 +1400,9 @@ internal class MyPoint public int Y { get; set; } } + internal class MyDerivedPoint : MyPoint + { } + /// /// classes for test data /// diff --git a/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml b/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml deleted file mode 100644 index 751a9e77e891e3..00000000000000 --- a/src/libraries/System.Diagnostics.EventLog/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - CP0001 - lib/netstandard2.0/System.Diagnostics.EventLog.dll - lib/net461/System.Diagnostics.EventLog.dll - - \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/EventLogRecordTests.cs b/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/EventLogRecordTests.cs index 6d4f252bdefb47..7808662bcb0201 100644 --- a/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/EventLogRecordTests.cs +++ b/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/EventLogRecordTests.cs @@ -90,7 +90,8 @@ public void ToXml() [ConditionalFact(typeof(Helpers), nameof(Helpers.SupportsEventLogs))] public void ExceptionOnce() { - if (PlatformDetection.IsWindows7) // Null events in PowerShell log + if (PlatformDetection.IsWindows7 || // Null events in PowerShell log + PlatformDetection.IsWindows10Version22000OrGreater) // ActiveIssue("https://github.com/dotnet/runtime/issues/58829") return; var query = new EventLogQuery("Application", PathType.LogName, "*[System]") { ReverseDirection = true }; var eventLog = new EventLogReader(query, Helpers.GetBookmark("Application", PathType.LogName)); diff --git a/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/ProviderMetadataTests.cs b/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/ProviderMetadataTests.cs index 0f7f4511022d65..1a47f63af4322f 100644 --- a/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/ProviderMetadataTests.cs +++ b/src/libraries/System.Diagnostics.EventLog/tests/System/Diagnostics/Reader/ProviderMetadataTests.cs @@ -23,6 +23,9 @@ public void SourceDoesNotExist_Throws() [InlineData(false)] public void ProviderNameTests(bool noProviderName) { + if (PlatformDetection.IsWindows10Version22000OrGreater) // ActiveIssue("https://github.com/dotnet/runtime/issues/58829") + return; + string log = "Application"; string source = "Source_" + nameof(ProviderNameTests); using (var session = new EventLogSession()) diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/CompatibilitySuppressions.xml b/src/libraries/System.Diagnostics.PerformanceCounter/src/CompatibilitySuppressions.xml deleted file mode 100644 index 5dd8d50f606e67..00000000000000 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - CP0001 - lib/netstandard2.0/System.Diagnostics.PerformanceCounter.dll - lib/net461/System.Diagnostics.PerformanceCounter.dll - - \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs b/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs index 4c98a461f323e7..7e1f6d5d77adec 100644 --- a/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs +++ b/src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs @@ -43,8 +43,8 @@ public Process() { } public System.Diagnostics.ProcessModule? MainModule { get { throw null; } } public System.IntPtr MainWindowHandle { get { throw null; } } public string MainWindowTitle { get { throw null; } } - public System.IntPtr MaxWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } - public System.IntPtr MinWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public System.IntPtr MaxWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + public System.IntPtr MinWorkingSet { [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios"), System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("freebsd"), System.Runtime.Versioning.SupportedOSPlatformAttribute("macos"), System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst"), System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } public System.Diagnostics.ProcessModuleCollection Modules { get { throw null; } } [System.ObsoleteAttribute("Process.NonpagedSystemMemorySize has been deprecated because the type of the property can't represent all valid results. Use System.Diagnostics.Process.NonpagedSystemMemorySize64 instead.")] public int NonpagedSystemMemorySize { get { throw null; } } @@ -84,7 +84,13 @@ public Process() { } public System.DateTime StartTime { get { throw null; } } public System.ComponentModel.ISynchronizeInvoke? SynchronizingObject { get { throw null; } set { } } public System.Diagnostics.ProcessThreadCollection Threads { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public System.TimeSpan TotalProcessorTime { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public System.TimeSpan UserProcessorTime { get { throw null; } } [System.ObsoleteAttribute("Process.VirtualMemorySize has been deprecated because the type of the property can't represent all valid results. Use System.Diagnostics.Process.VirtualMemorySize64 instead.")] public int VirtualMemorySize { get { throw null; } } @@ -106,33 +112,52 @@ public static void EnterDebugMode() { } public static System.Diagnostics.Process GetCurrentProcess() { throw null; } public static System.Diagnostics.Process GetProcessById(int processId) { throw null; } public static System.Diagnostics.Process GetProcessById(int processId, string machineName) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process[] GetProcesses() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process[] GetProcesses(string machineName) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process[] GetProcessesByName(string? processName) { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process[] GetProcessesByName(string? processName, string machineName) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public void Kill() { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public void Kill(bool entireProcessTree) { } public static void LeaveDebugMode() { } protected void OnExited() { } public void Refresh() { } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public bool Start() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process? Start(System.Diagnostics.ProcessStartInfo startInfo) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process Start(string fileName) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process Start(string fileName, string arguments) { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public static System.Diagnostics.Process Start(string fileName, System.Collections.Generic.IEnumerable arguments) { throw null; } [System.CLSCompliantAttribute(false)] [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] @@ -233,6 +258,9 @@ internal ProcessThread() { } public int IdealProcessor { set { } } public bool PriorityBoostEnabled { get { throw null; } set { } } public System.Diagnostics.ThreadPriorityLevel PriorityLevel { [System.Runtime.Versioning.SupportedOSPlatform("windows")] [System.Runtime.Versioning.SupportedOSPlatform("linux")] [System.Runtime.Versioning.SupportedOSPlatform("freebsd")] get { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] set { } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public System.TimeSpan PrivilegedProcessorTime { get { throw null; } } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public System.IntPtr ProcessorAffinity { set { } } @@ -241,7 +269,13 @@ public System.IntPtr ProcessorAffinity { set { } } [System.Runtime.Versioning.SupportedOSPlatform("linux")] public System.DateTime StartTime { get { throw null; } } public System.Diagnostics.ThreadState ThreadState { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public System.TimeSpan TotalProcessorTime { get { throw null; } } + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("ios")] + [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("tvos")] + [System.Runtime.Versioning.SupportedOSPlatformAttribute("maccatalyst")] public System.TimeSpan UserProcessorTime { get { throw null; } } public System.Diagnostics.ThreadWaitReason WaitReason { get { throw null; } } public void ResetIdealProcessor() { } diff --git a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj index 1bf0c43270e42e..64de4a154066de 100644 --- a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj +++ b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj @@ -2,7 +2,7 @@ $(DefineConstants);FEATURE_REGISTRY true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent);$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent);$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS enable $(NoWarn);0649 @@ -309,7 +309,7 @@ - + @@ -329,7 +329,7 @@ - + @@ -345,6 +345,11 @@ + + + + + diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.BSD.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.BSD.cs index 02b7cce02263d6..70c408cea290bb 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.BSD.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.BSD.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; +using System.Runtime.Versioning; namespace System.Diagnostics { @@ -12,6 +13,9 @@ public partial class Process /// Creates an array of components that are associated with process resources on a /// remote computer. These process resources share the specified process name. /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process[] GetProcessesByName(string? processName, string machineName) { if (processName == null) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs index 6942d82d6d1595..e4b149b84a6d23 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs @@ -7,6 +7,7 @@ using System.ComponentModel; using System.Globalization; using System.IO; +using System.Runtime.Versioning; using System.Text; namespace System.Diagnostics @@ -17,6 +18,9 @@ public partial class Process : IDisposable /// Creates an array of components that are associated with process resources on a /// remote computer. These process resources share the specified process name. /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process[] GetProcessesByName(string? processName, string machineName) { ProcessManager.ThrowIfRemoteMachine(machineName); diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs index 0dff87802214e9..2bad9c22c9b6d9 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs @@ -11,6 +11,7 @@ public partial class Process : IDisposable { [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public void Kill(bool entireProcessTree) { if (!entireProcessTree) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs index 69b4481ae2087b..0cbb98891ab235 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs @@ -58,9 +58,10 @@ public static Process Start(string fileName, string arguments, string userName, /// Terminates the associated process immediately. [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public void Kill() { - if (OperatingSystem.IsIOS() || OperatingSystem.IsTvOS()) + if (PlatformDoesNotSupportProcessStartAndKill) { throw new PlatformNotSupportedException(); } @@ -372,7 +373,7 @@ private SafeProcessHandle GetProcessHandle() /// The start info with which to start the process. private bool StartCore(ProcessStartInfo startInfo) { - if (OperatingSystem.IsIOS() || OperatingSystem.IsTvOS()) + if (PlatformDoesNotSupportProcessStartAndKill) { throw new PlatformNotSupportedException(); } @@ -1105,5 +1106,8 @@ private static int OnSigChild(int reapAll, int configureConsole) s_processStartLock.ExitWriteLock(); } } + + private static bool PlatformDoesNotSupportProcessStartAndKill + => (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS(); } } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.UnknownUnix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.UnknownUnix.cs index 46c652a7fb6a69..f56acfbbb5e0fa 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.UnknownUnix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.UnknownUnix.cs @@ -9,7 +9,10 @@ public partial class Process : IDisposable /// Creates an array of components that are associated with process resources on a /// remote computer. These process resources share the specified process name. /// - public static Process[] GetProcessesByName(string processName, string machineName) + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] + public static Process[] GetProcessesByName(string? processName, string machineName) { throw new PlatformNotSupportedException(); } @@ -82,5 +85,6 @@ private string GetPathToOpenFile() throw new PlatformNotSupportedException(); } + private int ParentProcessId => throw new PlatformNotSupportedException(); } } diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs index 9c59f54333bf64..8935edc549ba98 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs @@ -21,6 +21,9 @@ public partial class Process : IDisposable /// Creates an array of components that are associated with process resources on a /// remote computer. These process resources share the specified process name. /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process[] GetProcessesByName(string? processName, string machineName) { if (processName == null) @@ -91,6 +94,7 @@ public static void LeaveDebugMode() /// Terminates the associated process immediately. [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public void Kill() { using (SafeProcessHandle handle = GetProcessHandle(Interop.Advapi32.ProcessOptions.PROCESS_TERMINATE | Interop.Advapi32.ProcessOptions.PROCESS_QUERY_LIMITED_INFORMATION, throwIfExited: false)) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs index 0c5bf3a96542ae..a1796844b59810 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs @@ -193,6 +193,9 @@ public bool HasExited } /// Gets the time the associated process was started. + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public DateTime StartTime { get @@ -262,14 +265,16 @@ public IntPtr MaxWorkingSet { [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] get { EnsureWorkingSetLimits(); return _maxWorkingSet; } - [SupportedOSPlatform("windows")] - [SupportedOSPlatform("macos")] [SupportedOSPlatform("freebsd")] + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("maccatalyst")] + [SupportedOSPlatform("windows")] set { SetWorkingSetLimits(null, value); @@ -284,14 +289,16 @@ public IntPtr MinWorkingSet { [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] get { EnsureWorkingSetLimits(); return _minWorkingSet; } - [SupportedOSPlatform("windows")] - [SupportedOSPlatform("macos")] [SupportedOSPlatform("freebsd")] + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("maccatalyst")] + [SupportedOSPlatform("windows")] set { SetWorkingSetLimits(value, null); @@ -1039,6 +1046,9 @@ public static Process GetProcessById(int processId) /// local computer. These process resources share the specified process name. /// /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process[] GetProcessesByName(string? processName) { return GetProcessesByName(processName, "."); @@ -1050,6 +1060,9 @@ public static Process[] GetProcessesByName(string? processName) /// component for each process resource on the local computer. /// /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process[] GetProcesses() { return GetProcesses("."); @@ -1062,6 +1075,9 @@ public static Process[] GetProcesses() /// process resource on the specified computer. /// /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process[] GetProcesses(string machineName) { bool isRemoteMachine = ProcessManager.IsRemoteMachine(machineName); @@ -1205,6 +1221,7 @@ private void SetProcessId(int processId) /// [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public bool Start() { Close(); @@ -1248,6 +1265,7 @@ public bool Start() /// [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process Start(string fileName) { // the underlying Start method can only return null on Windows platforms, @@ -1266,6 +1284,7 @@ public static Process Start(string fileName) /// [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process Start(string fileName, string arguments) { // the underlying Start method can only return null on Windows platforms, @@ -1279,6 +1298,7 @@ public static Process Start(string fileName, string arguments) /// [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process Start(string fileName, IEnumerable arguments) { if (fileName == null) @@ -1305,6 +1325,7 @@ public static Process Start(string fileName, IEnumerable arguments) /// [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static Process? Start(ProcessStartInfo startInfo) { Process process = new Process(); diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.iOS.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.iOS.cs new file mode 100644 index 00000000000000..abbb712d4006ac --- /dev/null +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.iOS.cs @@ -0,0 +1,124 @@ +// 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.ComponentModel; +using System.Runtime.Versioning; + +namespace System.Diagnostics +{ + public partial class Process : IDisposable + { + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] + public void Kill(bool entireProcessTree) + { + throw new PlatformNotSupportedException(); + } + + /// + /// Creates an array of components that are associated with process resources on a + /// remote computer. These process resources share the specified process name. + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] + public static Process[] GetProcessesByName(string? processName, string machineName) + { + throw new PlatformNotSupportedException(); + } + + /// Gets the amount of time the process has spent running code inside the operating system core. + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public TimeSpan PrivilegedProcessorTime + { + get { throw new PlatformNotSupportedException(); } + } + + /// Gets the time the associated process was started. + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + internal DateTime StartTimeCore + { + get { throw new PlatformNotSupportedException(); } + } + + /// + /// Gets the amount of time the associated process has spent utilizing the CPU. + /// It is the sum of the and + /// . + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public TimeSpan TotalProcessorTime + { + get { throw new PlatformNotSupportedException(); } + } + + /// + /// Gets the amount of time the associated process has spent running code + /// inside the application portion of the process (not the operating system core). + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public TimeSpan UserProcessorTime + { + get { throw new PlatformNotSupportedException(); } + } + + /// + /// Returns all immediate child processes. + /// + private IReadOnlyList GetChildProcesses(Process[]? processes = null) + { + throw new PlatformNotSupportedException(); + } + + /// Gets parent process ID + private int GetParentProcessId => + throw new PlatformNotSupportedException(); + + /// + /// Gets or sets which processors the threads in this process can be scheduled to run on. + /// + private IntPtr ProcessorAffinityCore + { + get { throw new PlatformNotSupportedException(); } + set { throw new PlatformNotSupportedException(); } + } + + /// + /// Make sure we have obtained the min and max working set limits. + /// + private void GetWorkingSetLimits(out IntPtr minWorkingSet, out IntPtr maxWorkingSet) + { + throw new PlatformNotSupportedException(); + } + + /// Sets one or both of the minimum and maximum working set limits. + /// The new minimum working set limit, or null not to change it. + /// The new maximum working set limit, or null not to change it. + /// The resulting minimum working set limit after any changes applied. + /// The resulting maximum working set limit after any changes applied. + private void SetWorkingSetLimitsCore(IntPtr? newMin, IntPtr? newMax, out IntPtr resultingMin, out IntPtr resultingMax) + { + throw new PlatformNotSupportedException(); + } + + /// Gets execution path + private string GetPathToOpenFile() + { + throw new PlatformNotSupportedException(); + } + + private int ParentProcessId => throw new PlatformNotSupportedException(); + + private static bool IsProcessInvalidException(Exception e) => + // InvalidOperationException signifies conditions such as the process already being dead. + // Win32Exception signifies issues such as insufficient permissions to get details on the process. + // In either case, the predicate couldn't be applied so return the fallback result. + e is InvalidOperationException || e is Win32Exception; + } +} diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Unix.cs index 5df7ece329e1d3..1ef579803c622f 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Unix.cs @@ -3,6 +3,7 @@ using Microsoft.Win32.SafeHandles; using System.Collections.Generic; +using System.Runtime.Versioning; using System.Text; namespace System.Diagnostics @@ -44,6 +45,9 @@ public static bool IsProcessRunning(int processId) /// Gets the IDs of all processes on the specified machine. /// The machine to examine. /// An array of process IDs from the specified machine. + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] public static int[] GetProcessIds(string machineName) { ThrowIfRemoteMachine(machineName); diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.iOS.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.iOS.cs new file mode 100644 index 00000000000000..2fddb3b200e7e3 --- /dev/null +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.iOS.cs @@ -0,0 +1,39 @@ +// 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.Versioning; + +namespace System.Diagnostics +{ + internal static partial class ProcessManager + { + /// Gets the IDs of all processes on the current machine. + public static int[] GetProcessIds() + { + throw new PlatformNotSupportedException(); + } + + /// Gets process infos for each process on the specified machine. + /// The target machine. + /// An array of process infos, one per found process. + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public static ProcessInfo[] GetProcessInfos(string machineName) + { + throw new PlatformNotSupportedException(); + } + + /// Gets an array of module infos for the specified process. + /// The ID of the process whose modules should be enumerated. + /// The array of modules. + internal static ProcessModuleCollection GetModules(int processId) + { + return new ProcessModuleCollection(0); + } + + private static ProcessInfo CreateProcessInfo(int pid) + { + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs new file mode 100644 index 00000000000000..8faa430900aabf --- /dev/null +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThread.iOS.cs @@ -0,0 +1,56 @@ +// 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.Versioning; + +namespace System.Diagnostics +{ + public partial class ProcessThread + { + /// + /// Returns or sets the priority level of the associated thread. The priority level is + /// not an absolute level, but instead contributes to the actual thread priority by + /// considering the priority class of the process. + /// + private ThreadPriorityLevel PriorityLevelCore + { + get { throw new PlatformNotSupportedException(); } + set { throw new PlatformNotSupportedException(); } + } + + /// + /// Returns the amount of time the thread has spent running code inside the operating + /// system core. + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public TimeSpan PrivilegedProcessorTime + { + get { throw new PlatformNotSupportedException(); } + } + + private DateTime GetStartTime() => throw new PlatformNotSupportedException(); + /// + /// Returns the amount of time the associated thread has spent utilizing the CPU. + /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and + /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public TimeSpan TotalProcessorTime + { + get { throw new PlatformNotSupportedException(); } + } + + /// + /// Returns the amount of time the associated thread has spent running code + /// inside the application (not the operating system core). + /// + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + public TimeSpan UserProcessorTime + { + get { throw new PlatformNotSupportedException(); } + } + } +} diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ThreadInfo.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ThreadInfo.cs index c12c143e5a53a1..1205e732e67328 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ThreadInfo.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ThreadInfo.cs @@ -12,6 +12,7 @@ namespace System.Diagnostics /// internal sealed class ThreadInfo { +#pragma warning disable CS0649 // The fields are unused on iOS/tvOS as the respective managed logic (mostly around libproc) is excluded. internal ulong _threadId; internal int _processId; internal int _basePriority; @@ -19,5 +20,6 @@ internal sealed class ThreadInfo internal IntPtr _startAddress; internal ThreadState _threadState; internal ThreadWaitReason _threadWaitReason; +#pragma warning restore CS0649 } } diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessModuleTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessModuleTests.cs index 33f84717da7198..fd4e9d2751753f 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessModuleTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessModuleTests.cs @@ -10,6 +10,7 @@ namespace System.Diagnostics.Tests public partial class ProcessModuleTests : ProcessTestBase { [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void TestModuleProperties() { ProcessModuleCollection modules = Process.GetCurrentProcess().Modules; @@ -29,6 +30,7 @@ public void TestModuleProperties() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void Modules_Get_ContainsHostFileName() { ProcessModuleCollection modules = Process.GetCurrentProcess().Modules; diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs index 38062773cb3671..6f304b08989f55 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.cs @@ -1318,7 +1318,7 @@ private void VerifyNotepadMainWindowTitle(Process process, string filename) string expected = Path.GetFileNameWithoutExtension(filename); process.WaitForInputIdle(); // Give the file a chance to load - Assert.Equal("notepad", process.ProcessName); + Assert.Equal("notepad", process.ProcessName.ToLower()); // Notepad calls CreateWindowEx with pWindowName of empty string, then calls SetWindowTextW // with "Untitled - Notepad" then finally if you're opening a file, calls SetWindowTextW diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs index 63d7f3d6d02b3c..e27e143f75b642 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.Unix.cs @@ -78,6 +78,7 @@ public void ProcessStart_UseShellExecute_OnLinux_ThrowsIfNoProgramInstalled() [Fact] [OuterLoop("Opens program")] + [SkipOnPlatform(TestPlatforms.MacCatalyst, "In App Sandbox mode, the process doesn't have read access to the binary.")] public void ProcessStart_DirectoryNameInCurDirectorySameAsFileNameInExecDirectory_Success() { string fileToOpen = "dotnet"; @@ -157,8 +158,8 @@ public void ProcessStart_UseShellExecute_OnUnix_SuccessWhenProgramInstalled(bool } [Fact] - [SkipOnPlatform(TestPlatforms.OSX, "On OSX, ProcessName returns the script interpreter.")] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on iOS, MacCatalyst, or tvOS.")] + [SkipOnPlatform(TestPlatforms.OSX | TestPlatforms.MacCatalyst, "On OSX, ProcessName returns the script interpreter.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void ProcessNameMatchesScriptName() { string scriptName = GetTestFileName(); @@ -379,7 +380,7 @@ public void ProcessStart_OnLinux_UsesSpecifiedProgramUsingArgumentList() } [Theory, InlineData("/usr/bin/open"), InlineData("/usr/bin/nano")] - [PlatformSpecific(TestPlatforms.OSX)] + [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst)] [OuterLoop("Opens program")] public void ProcessStart_OpenFileOnOsx_UsesSpecifiedProgram(string programToOpenWith) { @@ -396,7 +397,7 @@ public void ProcessStart_OpenFileOnOsx_UsesSpecifiedProgram(string programToOpen } [Theory, InlineData("Safari"), InlineData("\"Google Chrome\"")] - [PlatformSpecific(TestPlatforms.OSX)] + [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst)] [OuterLoop("Opens browser")] public void ProcessStart_OpenUrl_UsesSpecifiedApplication(string applicationToOpenWith) { @@ -410,7 +411,7 @@ public void ProcessStart_OpenUrl_UsesSpecifiedApplication(string applicationToOp } [Theory, InlineData("-a Safari"), InlineData("-a \"Google Chrome\"")] - [PlatformSpecific(TestPlatforms.OSX)] + [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst)] [OuterLoop("Opens browser")] public void ProcessStart_UseShellExecuteTrue_OpenUrl_SuccessfullyReadsArgument(string arguments) { @@ -432,7 +433,7 @@ public void ProcessStart_UseShellExecuteTrue_OpenUrl_SuccessfullyReadsArgument(s [Theory, MemberData(nameof(StartOSXProcessWithArgumentList))] - [PlatformSpecific(TestPlatforms.OSX)] + [PlatformSpecific(TestPlatforms.OSX | TestPlatforms.MacCatalyst)] [OuterLoop("Opens browser")] public void ProcessStart_UseShellExecuteTrue_OpenUrl_SuccessfullyReadsArgumentArray(string[] argumentList) { @@ -502,7 +503,7 @@ public void TestBasePriorityOnUnix() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on iOS, MacCatalyst, or tvOS.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void TestStartOnUnixWithBadPermissions() { string path = GetTestFilePath(); @@ -514,7 +515,7 @@ public void TestStartOnUnixWithBadPermissions() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on iOS, MacCatalyst, or tvOS.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS or tvOS.")] public void TestStartOnUnixWithBadFormat() { string path = GetTestFilePath(); diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs index 880da43a646539..febe1a0e8e767a 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs @@ -171,28 +171,28 @@ public void TestExited_SynchronizingObject(bool invokeRequired) } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_TryExitCommandAsFileName_ThrowsWin32Exception() { Assert.Throws(() => Process.Start(new ProcessStartInfo { UseShellExecute = false, FileName = "exit", Arguments = "42" })); } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_UseShellExecuteFalse_FilenameIsUrl_ThrowsWin32Exception() { Assert.Throws(() => Process.Start(new ProcessStartInfo { UseShellExecute = false, FileName = "https://www.github.com/corefx" })); } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_TryOpenFolder_UseShellExecuteIsFalse_ThrowsWin32Exception() { Assert.Throws(() => Process.Start(new ProcessStartInfo { UseShellExecute = false, FileName = Path.GetTempPath() })); } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void TestStartWithBadWorkingDirectory() { string program; @@ -230,7 +230,7 @@ public void TestStartWithBadWorkingDirectory() [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.HasWindowsShell))] [OuterLoop("Launches File Explorer")] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_UseShellExecute_OnWindows_OpenMissingFile_Throws() { string fileToOpen = Path.Combine(Environment.CurrentDirectory, "_no_such_file.TXT"); @@ -243,7 +243,7 @@ public void ProcessStart_UseShellExecute_OnWindows_OpenMissingFile_Throws() [InlineData(true)] [InlineData(false)] [OuterLoop("Launches File Explorer")] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_UseShellExecute_OnWindows_DoesNotThrow(bool isFolder) { string fileToOpen; @@ -267,21 +267,27 @@ public void ProcessStart_UseShellExecute_OnWindows_DoesNotThrow(bool isFolder) { if (px != null) // sometimes process is null { - Assert.Equal("notepad", px.ProcessName); - - px.Kill(); - Assert.True(px.WaitForExit(WaitInMS)); - px.WaitForExit(); // wait for event handlers to complete + try + { + Assert.Equal("notepad", px.ProcessName.ToLower()); + } + finally + { + px.Kill(); + Assert.True(px.WaitForExit(WaitInMS)); + px.WaitForExit(); // wait for event handlers to complete + } } } } } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsServerCore), - nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsIoTCore))] + nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsIoTCore), + nameof(PlatformDetection.IsNotAppSandbox))] [ActiveIssue("https://github.com/dotnet/runtime/issues/34685", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [InlineData(true), InlineData(false)] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on iOS, MacCatalyst, or tvOS.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_UseShellExecute_Executes(bool filenameAsUrl) { string filename = WriteScriptFile(TestDirectory, GetTestFileName(), returnValue: 42); @@ -304,7 +310,9 @@ public void ProcessStart_UseShellExecute_Executes(bool filenameAsUrl) PlatformDetection.IsNotWindowsIoTCore && RemoteExecutor.IsSupported; - [ConditionalFact(nameof(UseShellExecuteExecuteOrderIsRunnablePlatform))] + private static bool IsNotAppSandbox => PlatformDetection.IsNotAppSandbox; + + [ConditionalFact(nameof(UseShellExecuteExecuteOrderIsRunnablePlatform), nameof(IsNotAppSandbox))] [ActiveIssue("https://github.com/dotnet/runtime/issues/34685", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] public void ProcessStart_UseShellExecute_ExecuteOrder() { @@ -348,9 +356,10 @@ public void ProcessStart_UseShellExecute_ExecuteOrder() } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsServerCore), - nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsIoTCore))] + nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsIoTCore), + nameof(PlatformDetection.IsNotAppSandbox))] [ActiveIssue("https://github.com/dotnet/runtime/issues/34685", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on iOS, MacCatalyst, or tvOS.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void ProcessStart_UseShellExecute_WorkingDirectory() { // Create a directory that will ProcessStartInfo.WorkingDirectory @@ -414,6 +423,7 @@ public void TestExitTime() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void StartTime_GetNotStarted_ThrowsInvalidOperationException() { var process = new Process(); @@ -501,7 +511,7 @@ public void HasExited_GetNotStarted_ThrowsInvalidOperationException() } [Fact] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst, "Not supported on iOS, tvOS, or MacCatalyst.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void Kill_NotStarted_ThrowsInvalidOperationException() { var process = new Process(); @@ -525,6 +535,7 @@ public void MachineName_GetNotStarted_ThrowsInvalidOperationException() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void TestMainModule() { Process p = Process.GetCurrentProcess(); @@ -854,6 +865,7 @@ public void TotalProcessorTime_PerformLoop_TotalProcessorTimeValid() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void UserProcessorTime_GetNotStarted_ThrowsInvalidOperationException() { var process = new Process(); @@ -861,6 +873,7 @@ public void UserProcessorTime_GetNotStarted_ThrowsInvalidOperationException() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void PriviledgedProcessorTime_GetNotStarted_ThrowsInvalidOperationException() { var process = new Process(); @@ -868,6 +881,7 @@ public void PriviledgedProcessorTime_GetNotStarted_ThrowsInvalidOperationExcepti } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void TotalProcessorTime_GetNotStarted_ThrowsInvalidOperationException() { var process = new Process(); @@ -1105,6 +1119,7 @@ public void TestGetProcessById() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void TestGetProcesses() { Process currentProcess = Process.GetCurrentProcess(); @@ -1170,6 +1185,7 @@ public void GetProcesses_RemoteMachinePath_ReturnsExpected() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void GetProcessesByName_ProcessName_ReturnsExpected() { // Get the current process using its name @@ -1229,6 +1245,7 @@ public static IEnumerable MachineName_Remote_TestData() [Theory] [MemberData(nameof(MachineName_TestData))] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void GetProcessesByName_ProcessNameMachineName_ReturnsExpected(string machineName) { Process currentProcess = Process.GetCurrentProcess(); @@ -1255,6 +1272,7 @@ public void GetProcessesByName_RemoteMachineNameWindows_ReturnsExpected(string m } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void GetProcessesByName_NoSuchProcess_ReturnsEmpty() { string processName = Guid.NewGuid().ToString("N"); @@ -1262,6 +1280,7 @@ public void GetProcessesByName_NoSuchProcess_ReturnsEmpty() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void GetProcessesByName_NullMachineName_ThrowsArgumentNullException() { Process currentProcess = Process.GetCurrentProcess(); @@ -1269,6 +1288,7 @@ public void GetProcessesByName_NullMachineName_ThrowsArgumentNullException() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void GetProcessesByName_EmptyMachineName_ThrowsArgumentException() { Process currentProcess = Process.GetCurrentProcess(); @@ -1331,6 +1351,7 @@ public void StartInfo_SetOnRunningProcess_ThrowsInvalidOperationException() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void StartInfo_SetGet_ReturnsExpected() { var process = new Process() { StartInfo = new ProcessStartInfo(RemoteExecutor.HostRunner) }; @@ -1407,7 +1428,7 @@ public void CanBeFinalized() [Theory] [InlineData(false)] [InlineData(true)] - [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on iOS, MacCatalyst, or tvOS.")] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Not supported on iOS and tvOS.")] public void TestStartWithMissingFile(bool fullPath) { string path = Guid.NewGuid().ToString("N"); @@ -1715,6 +1736,7 @@ public void MainWindowTitle_GetWithGui_ShouldRefresh_Windows() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void RefreshResetsAllRefreshableFields() { // testing Process.Responding using a real unresponsive process would be very hard to do properly @@ -2271,6 +2293,7 @@ public void BothArgumentSetAndArgumentListSet() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void Kill_EntireProcessTree_True_ProcessNotStarted_ThrowsInvalidOperationException() { var process = new Process(); @@ -2300,6 +2323,7 @@ public void Kill_EntireProcessTree_True_CalledByNonLocalProcess_ThrowsInvalidOpe } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void Kill_EntireProcessTree_True_CalledOnCallingProcess_ThrowsInvalidOperationException() { var process = Process.GetCurrentProcess(); diff --git a/src/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs b/src/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs index 2266582ac5190f..6db4fd1a2cdeea 100644 --- a/src/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs +++ b/src/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs @@ -46,6 +46,7 @@ public void TestCommonPriorityAndTimeProperties() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void TestThreadCount() { int numOfThreads = 10; @@ -161,6 +162,7 @@ await Task.Factory.StartNew(() => } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public void TestStartAddressProperty() { using (Process p = Process.GetCurrentProcess()) diff --git a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/XmlWriterTraceListenerTests.cs b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/XmlWriterTraceListenerTests.cs index 418e7b04d952f0..d00e72ce7c12b7 100644 --- a/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/XmlWriterTraceListenerTests.cs +++ b/src/libraries/System.Diagnostics.TextWriterTraceListener/tests/XmlWriterTraceListenerTests.cs @@ -12,6 +12,7 @@ namespace System.Diagnostics.TextWriterTraceListenerTests { + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "libproc is not supported on iOS/tvOS")] public class XmlWriterTraceListenerTests : FileCleanupTestBase { private readonly string _processName; diff --git a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs index 62e82e3e09c3b1..e57585e4d8fd7f 100644 --- a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs @@ -69,7 +69,7 @@ protected override void OnValueChanged() { } public abstract partial class Switch { protected Switch(string displayName, string? description) { } - protected Switch(string displayName, string? description, string? defaultSwitchValue) { } + protected Switch(string displayName, string? description, string defaultSwitchValue) { } public System.Collections.Specialized.StringDictionary Attributes { get { throw null; } } public string Description { get { throw null; } } public string DisplayName { get { throw null; } } diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs index 23b40732ea4b5a..583d4cc1c8a050 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Switch.cs @@ -24,7 +24,7 @@ public abstract class Switch private volatile bool _initialized; private bool _initializing; private volatile string _switchValueString = string.Empty; - private readonly string? _defaultValue; + private readonly string _defaultValue; private object? _initializedLock; private static readonly List> s_switches = new List>(); @@ -53,7 +53,7 @@ protected Switch(string displayName, string? description) : this(displayName, de { } - protected Switch(string displayName, string? description, string? defaultSwitchValue) + protected Switch(string displayName, string? description, string defaultSwitchValue) { // displayName is used as a hashtable key, so it can never // be null. @@ -203,7 +203,7 @@ private bool InitializeWithStatus() // called again, we don't want to get caught in an infinite loop. _initializing = true; - _switchValueString = _defaultValue!; + _switchValueString = _defaultValue; OnValueChanged(); _initialized = true; _initializing = false; diff --git a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEventToListener.cs b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEventToListener.cs index d7c7046ab693ed..97470a2ff4450e 100644 --- a/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEventToListener.cs +++ b/src/libraries/System.Diagnostics.Tracing/tests/BasicEventSourceTest/TestsWriteEventToListener.cs @@ -452,6 +452,7 @@ public void Test_EventSourceCreatedEvents_AfterListener() [Theory] [InlineData(true)] [InlineData(false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/51382", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void Test_EventListenerThrows_ExceptionIsNotRethrownToCaller(bool setThrowOnEventWriteErrorsFlag) { TestUtilities.CheckNoEventSourcesRunning("Start"); diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj index b994abfb5ee24b..81b52cb94e34bf 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System.DirectoryServices.AccountManagement.csproj @@ -97,10 +97,10 @@ - + @@ -115,7 +115,6 @@ - diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj index d317292d1144a0..229b659e0231eb 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj +++ b/src/libraries/System.DirectoryServices.Protocols/src/System.DirectoryServices.Protocols.csproj @@ -1,4 +1,4 @@ - + true true @@ -6,6 +6,7 @@ true true true + 1 Provides the methods defined in the Lightweight Directory Access Protocol (LDAP) version 3 (V3) and Directory Services Markup Language (DSML) version 2.0 (V2) standards. @@ -67,7 +68,11 @@ + + + Common\System\LocalAppContextSwitches.Common.cs + Common\Interop\Linux\OpenLdap\Interop.Ldap.cs diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs index 701fae26108282..a2619871edecb4 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/LdapPal.Linux.cs @@ -111,7 +111,7 @@ internal static int BindToDirectory(ConnectionHandle ld, string who, string pass passwordPtr = LdapPal.StringToPtr(passwd); berval passwordBerval = new berval { - bv_len = passwd.Length, + bv_len = passwd?.Length ?? 0, bv_val = passwordPtr, }; @@ -123,7 +123,31 @@ internal static int BindToDirectory(ConnectionHandle ld, string who, string pass } } - internal static int StartTls(ConnectionHandle ldapHandle, ref int ServerReturnValue, ref IntPtr Message, IntPtr ServerControls, IntPtr ClientControls) => Interop.Ldap.ldap_start_tls(ldapHandle, ref ServerReturnValue, ref Message, ServerControls, ClientControls); + internal static int StartTls(ConnectionHandle ldapHandle, ref int serverReturnValue, ref IntPtr message, IntPtr serverControls, IntPtr clientControls) + { + // Windows and Linux have different signatures for ldap_start_tls_s. + // On Linux, we don't have a serverReturnValue or the message/result parameter. + // + // So in the PAL here, just emulate. + + int error = Interop.Ldap.ldap_start_tls(ldapHandle, serverControls, clientControls); + + // On Windows, serverReturnValue only has meaning if the result code is LDAP_OTHER. + // If OpenLDAP returns that, we don't have a better code, so assign that through. + // If we get any other error, assign serverReturnValue to 0 since it shouldn't be read. + if (error == (int)ResultCode.Other) + { + serverReturnValue = error; + } + else + { + serverReturnValue = 0; + } + + // We don't have a referrer/message/result value, so just set it to NULL. + message = IntPtr.Zero; + return error; + } // openldap doesn't have a ldap_stop_tls function. Returning true as no-op for Linux. internal static byte StopTls(ConnectionHandle ldapHandle) => 1; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs index 2383e816e1ddb6..a7e43947e20314 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/Interop/SafeHandles.Linux.cs @@ -16,6 +16,13 @@ public ConnectionHandle() _needDispose = true; } + internal ConnectionHandle(string uri) + :base(true) + { + Interop.Ldap.ldap_initialize(out handle, uri); + _needDispose = true; + } + internal ConnectionHandle(IntPtr value, bool disposeHandle) : base(true) { _needDispose = disposeHandle; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs index 02c8f0c239587b..6adf1ebac982cd 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapConnection.Linux.cs @@ -20,7 +20,7 @@ private void InternalInitConnectionHandle(string hostname) throw new NullReferenceException(); } - _ldapHandle = new ConnectionHandle(); + _ldapHandle = new ConnectionHandle($"ldap://{hostname}:{((LdapDirectoryIdentifier)_directoryIdentifier).PortNumber}"); } private int InternalConnectToServer() @@ -79,13 +79,39 @@ private int InternalConnectToServer() private int InternalBind(NetworkCredential tempCredential, SEC_WINNT_AUTH_IDENTITY_EX cred, BindMethod method) { int error; - if (tempCredential == null && (AuthType == AuthType.External || AuthType == AuthType.Kerberos)) + + if (LocalAppContextSwitches.UseBasicAuthFallback) { - error = BindSasl(); + if (tempCredential == null && (AuthType == AuthType.External || AuthType == AuthType.Kerberos)) + { + error = BindSasl(); + } + else + { + error = LdapPal.BindToDirectory(_ldapHandle, cred.user, cred.password); + } } else { - error = LdapPal.BindToDirectory(_ldapHandle, cred.user, cred.password); + if (method == BindMethod.LDAP_AUTH_NEGOTIATE) + { + if (tempCredential == null) + { + error = BindSasl(); + } + else + { + // Explicit credentials were provided. If we call ldap_bind_s it will + // return LDAP_NOT_SUPPORTED, so just skip the P/Invoke. + error = (int)LdapError.NotSupported; + } + } + else + { + // Basic and Anonymous are handled elsewhere. + Debug.Assert(AuthType != AuthType.Anonymous && AuthType != AuthType.Basic); + error = (int)LdapError.AuthUnknown; + } } return error; diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs index 5b28020eed2fd2..9a200fc5ba218b 100644 --- a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LdapSessionOptions.cs @@ -641,11 +641,14 @@ public unsafe void StartTransportLayerSecurity(DirectoryControlCollection contro response.ResponseName = "1.3.6.1.4.1.1466.20037"; throw new TlsOperationException(response); } - else if (LdapErrorMappings.IsLdapError(error)) + + if (LdapErrorMappings.IsLdapError(error)) { string errorMessage = LdapErrorMappings.MapResultCode(error); throw new LdapException(error, errorMessage); } + + throw new LdapException(error); } } finally diff --git a/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LocalAppContextSwitches.cs b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LocalAppContextSwitches.cs new file mode 100644 index 00000000000000..59ddfdf7f10ed3 --- /dev/null +++ b/src/libraries/System.DirectoryServices.Protocols/src/System/DirectoryServices/Protocols/ldap/LocalAppContextSwitches.cs @@ -0,0 +1,18 @@ +// 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 +{ + internal static partial class LocalAppContextSwitches + { + private static int s_useBasicAuthFallback; + + public static bool UseBasicAuthFallback + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => GetCachedSwitchValue("System.DirectoryServices.Protocols.UseBasicAuthFallback", ref s_useBasicAuthFallback); + } + } +} diff --git a/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs b/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs index 9a8074bf5222ad..a0522a61abc182 100644 --- a/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs +++ b/src/libraries/System.DirectoryServices.Protocols/tests/LdapConnectionTests.cs @@ -112,6 +112,16 @@ public void AuthType_SetValid_GetReturnsExpected() Assert.Equal(AuthType.Basic, connection.AuthType); } + [Fact] + public void AuthType_Anonymous_DoesNotThrowNull() + { + var connection = new LdapConnection("server"); + connection.AuthType = AuthType.Anonymous; + // When calling Bind we make sure that the exception thrown is not that there was a NullReferenceException + // trying to retrive a null password's lenght, but instead an LdapException given the server cannot be reached. + Assert.Throws(() => connection.Bind()); + } + [Theory] [InlineData(AuthType.Anonymous - 1)] [InlineData(AuthType.Kerberos + 1)] diff --git a/src/libraries/System.DirectoryServices/Directory.Build.props b/src/libraries/System.DirectoryServices/Directory.Build.props index bfa544ca6f649e..0740890146a71c 100644 --- a/src/libraries/System.DirectoryServices/Directory.Build.props +++ b/src/libraries/System.DirectoryServices/Directory.Build.props @@ -5,6 +5,9 @@ plan on shipping a new desktop version out of band. Instead add API to a different assembly. --> 4.0.0.0 + + true Microsoft windows diff --git a/src/libraries/System.DirectoryServices/ref/System.DirectoryServices.csproj b/src/libraries/System.DirectoryServices/ref/System.DirectoryServices.csproj index a8259f7fffe83c..0da0155f6eaed4 100644 --- a/src/libraries/System.DirectoryServices/ref/System.DirectoryServices.csproj +++ b/src/libraries/System.DirectoryServices/ref/System.DirectoryServices.csproj @@ -9,6 +9,7 @@ + @@ -16,7 +17,6 @@ - diff --git a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj index 6cbf2240119c76..41798f7bf3d1d7 100644 --- a/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj +++ b/src/libraries/System.DirectoryServices/src/System.DirectoryServices.csproj @@ -156,11 +156,11 @@ System.DirectoryServices.ActiveDirectory.DomainController + - @@ -183,7 +183,6 @@ System.DirectoryServices.ActiveDirectory.DomainController - diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs index 2a6e2a49ef3636..ba1d25352fc237 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.cs @@ -596,12 +596,16 @@ public void Flush(System.Drawing.Drawing2D.FlushIntention intention) { } public static System.Drawing.Graphics FromImage(System.Drawing.Image image) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] +#if NETCOREAPP3_1_OR_GREATER [System.ObsoleteAttribute("Use the Graphics.GetContextInfo overloads that accept arguments for better performance and fewer allocations.", DiagnosticId = "SYSLIB0016", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] +#endif public object GetContextInfo() { throw null; } +#if NETCOREAPP3_1_OR_GREATER [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public void GetContextInfo(out PointF offset) { throw null; } [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] public void GetContextInfo(out PointF offset, out Region? clip) { throw null; } +#endif public static System.IntPtr GetHalftonePalette() { throw null; } public System.IntPtr GetHdc() { throw null; } public System.Drawing.Color GetNearestColor(System.Drawing.Color color) { throw null; } diff --git a/src/libraries/System.Drawing.Common/src/CompatibilitySuppressions.xml b/src/libraries/System.Drawing.Common/src/CompatibilitySuppressions.xml index a7e39a278823c2..a623413023f20d 100644 --- a/src/libraries/System.Drawing.Common/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Drawing.Common/src/CompatibilitySuppressions.xml @@ -2,19 +2,56 @@ CP0001 + T:System.Drawing.FontConverter lib/netstandard2.0/System.Drawing.Common.dll lib/net461/System.Drawing.Common.dll CP0001 - T:System.Drawing.ColorTranslator + T:System.Drawing.IconConverter lib/netstandard2.0/System.Drawing.Common.dll - lib/netcoreapp3.1/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll + + + CP0001 + T:System.Drawing.ImageConverter + lib/netstandard2.0/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll + + + CP0001 + T:System.Drawing.ImageFormatConverter + lib/netstandard2.0/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll CP0001 - T:System.Drawing.SystemColors + T:System.Drawing.Printing.MarginsConverter + lib/netstandard2.0/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll + + + CP0002 + F:System.Drawing.Imaging.Encoder.ColorSpace + lib/netstandard2.0/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll + + + CP0002 + F:System.Drawing.Imaging.Encoder.ImageItems + lib/netstandard2.0/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll + + + CP0002 + F:System.Drawing.Imaging.Encoder.SaveAsCmyk lib/netstandard2.0/System.Drawing.Common.dll - lib/netcoreapp3.1/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll + + + CP0002 + F:System.Drawing.Imaging.EncoderParameterValueType.ValueTypePointer + lib/netstandard2.0/System.Drawing.Common.dll + lib/net461/System.Drawing.Common.dll \ No newline at end of file diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs index 3edf4a0e7b67ec..dbe2888361346e 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.Windows.cs @@ -269,13 +269,13 @@ private static void PlatformInitialize() [DllImport(LibraryName, ExactSpelling = true)] internal static extern IntPtr GdipCreateHalftonePalette(); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawBeziers(HandleRef graphics, HandleRef pen, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawBeziersI(HandleRef graphics, HandleRef pen, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillPath(HandleRef graphics, HandleRef brush, HandleRef path); [DllImport(LibraryName, ExactSpelling = true)] diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs index 18619993c0d1d3..c9539e24a38761 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/GdiplusNative.cs @@ -835,7 +835,7 @@ internal static unsafe partial class Gdip [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipDeleteRegion(HandleRef region); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillRegion(HandleRef graphics, HandleRef brush, HandleRef region); [DllImport(LibraryName, ExactSpelling = true)] @@ -1183,127 +1183,127 @@ internal static unsafe partial class Gdip [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipSaveGraphics(HandleRef graphics, out int state); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawArc(HandleRef graphics, HandleRef pen, float x, float y, float width, float height, float startAngle, float sweepAngle); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawArcI(HandleRef graphics, HandleRef pen, int x, int y, int width, int height, float startAngle, float sweepAngle); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawLinesI(HandleRef graphics, HandleRef pen, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawBezier(HandleRef graphics, HandleRef pen, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawEllipse(HandleRef graphics, HandleRef pen, float x, float y, float width, float height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawEllipseI(HandleRef graphics, HandleRef pen, int x, int y, int width, int height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawLine(HandleRef graphics, HandleRef pen, float x1, float y1, float x2, float y2); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawLineI(HandleRef graphics, HandleRef pen, int x1, int y1, int x2, int y2); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawLines(HandleRef graphics, HandleRef pen, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawPath(HandleRef graphics, HandleRef pen, HandleRef path); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawPie(HandleRef graphics, HandleRef pen, float x, float y, float width, float height, float startAngle, float sweepAngle); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawPieI(HandleRef graphics, HandleRef pen, int x, int y, int width, int height, float startAngle, float sweepAngle); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawPolygon(HandleRef graphics, HandleRef pen, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawPolygonI(HandleRef graphics, HandleRef pen, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillEllipse(HandleRef graphics, HandleRef brush, float x, float y, float width, float height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillEllipseI(HandleRef graphics, HandleRef brush, int x, int y, int width, int height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillPolygon(HandleRef graphics, HandleRef brush, PointF* points, int count, FillMode brushMode); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillPolygonI(HandleRef graphics, HandleRef brush, Point* points, int count, FillMode brushMode); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillRectangle(HandleRef graphics, HandleRef brush, float x, float y, float width, float height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillRectangleI(HandleRef graphics, HandleRef brush, int x, int y, int width, int height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillRectangles(HandleRef graphics, HandleRef brush, RectangleF* rects, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillRectanglesI(HandleRef graphics, HandleRef brush, Rectangle* rects, int count); - [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] + [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern int GdipDrawString(HandleRef graphics, string textString, int length, HandleRef font, ref RectangleF layoutRect, HandleRef stringFormat, HandleRef brush); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImageRectI(HandleRef graphics, HandleRef image, int x, int y, int width, int height); [DllImport(LibraryName, ExactSpelling = true)] internal static extern int GdipGraphicsClear(HandleRef graphics, int argb); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawClosedCurve(HandleRef graphics, HandleRef pen, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawClosedCurveI(HandleRef graphics, HandleRef pen, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawClosedCurve2(HandleRef graphics, HandleRef pen, PointF* points, int count, float tension); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawClosedCurve2I(HandleRef graphics, HandleRef pen, Point* points, int count, float tension); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawCurve(HandleRef graphics, HandleRef pen, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawCurveI(HandleRef graphics, HandleRef pen, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawCurve2(HandleRef graphics, HandleRef pen, PointF* points, int count, float tension); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawCurve2I(HandleRef graphics, HandleRef pen, Point* points, int count, float tension); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawCurve3(HandleRef graphics, HandleRef pen, PointF* points, int count, int offset, int numberOfSegments, float tension); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawCurve3I(HandleRef graphics, HandleRef pen, Point* points, int count, int offset, int numberOfSegments, float tension); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillClosedCurve(HandleRef graphics, HandleRef brush, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillClosedCurveI(HandleRef graphics, HandleRef brush, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillClosedCurve2(HandleRef graphics, HandleRef brush, PointF* points, int count, float tension, FillMode mode); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillClosedCurve2I(HandleRef graphics, HandleRef brush, Point* points, int count, float tension, FillMode mode); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillPie(HandleRef graphics, HandleRef brush, float x, float y, float width, float height, float startAngle, float sweepAngle); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipFillPieI(HandleRef graphics, HandleRef brush, int x, int y, int width, int height, float startAngle, float sweepAngle); [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] @@ -1312,49 +1312,49 @@ internal static unsafe partial class Gdip [DllImport(LibraryName, ExactSpelling = true, CharSet = CharSet.Unicode)] internal static extern int GdipMeasureCharacterRanges(HandleRef graphics, string textString, int length, HandleRef font, ref RectangleF layoutRect, HandleRef stringFormat, int characterCount, [In] [Out] IntPtr[] region); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImageI(HandleRef graphics, HandleRef image, int x, int y); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImage(HandleRef graphics, HandleRef image, float x, float y); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImagePoints(HandleRef graphics, HandleRef image, PointF* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImagePointsI(HandleRef graphics, HandleRef image, Point* points, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImageRectRectI(HandleRef graphics, HandleRef image, int dstx, int dsty, int dstwidth, int dstheight, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcunit, HandleRef imageAttributes, Graphics.DrawImageAbort? callback, HandleRef callbackdata); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImagePointsRect(HandleRef graphics, HandleRef image, PointF* points, int count, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcunit, HandleRef imageAttributes, Graphics.DrawImageAbort? callback, HandleRef callbackdata); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImageRectRect(HandleRef graphics, HandleRef image, float dstx, float dsty, float dstwidth, float dstheight, float srcx, float srcy, float srcwidth, float srcheight, GraphicsUnit srcunit, HandleRef imageAttributes, Graphics.DrawImageAbort? callback, HandleRef callbackdata); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImagePointsRectI(HandleRef graphics, HandleRef image, Point* points, int count, int srcx, int srcy, int srcwidth, int srcheight, GraphicsUnit srcunit, HandleRef imageAttributes, Graphics.DrawImageAbort? callback, HandleRef callbackdata); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImageRect(HandleRef graphics, HandleRef image, float x, float y, float width, float height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImagePointRect(HandleRef graphics, HandleRef image, float x, float y, float srcx, float srcy, float srcwidth, float srcheight, int srcunit); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawImagePointRectI(HandleRef graphics, HandleRef image, int x, int y, int srcx, int srcy, int srcwidth, int srcheight, int srcunit); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawRectangle(HandleRef graphics, HandleRef pen, float x, float y, float width, float height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawRectangleI(HandleRef graphics, HandleRef pen, int x, int y, int width, int height); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawRectangles(HandleRef graphics, HandleRef pen, RectangleF* rects, int count); - [DllImport(LibraryName, ExactSpelling = true)] + [DllImport(LibraryName, ExactSpelling = true, SetLastError = true)] internal static extern int GdipDrawRectanglesI(HandleRef graphics, HandleRef pen, Rectangle* rects, int count); [DllImport(LibraryName, ExactSpelling = true)] diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Unix.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Unix.cs index cba7e4aab0a55e..4baa41dad24499 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Unix.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Unix.cs @@ -583,6 +583,7 @@ public object GetContextInfo() throw new NotImplementedException(); } +#if NETCOREAPP3_1_OR_GREATER [EditorBrowsable(EditorBrowsableState.Never)] [SupportedOSPlatform("windows")] public void GetContextInfo(out PointF offset) @@ -596,6 +597,7 @@ public void GetContextInfo(out PointF offset, out Region? clip) { throw new PlatformNotSupportedException(); } +#endif private void CheckErrorStatus(int status) { diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs index 8dd2ad15b22d52..475e35a176ceac 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Graphics.Windows.cs @@ -684,7 +684,9 @@ public unsafe void EnumerateMetafile( /// WARNING: This method is for internal FX support only. /// [EditorBrowsable(EditorBrowsableState.Never)] +#if NETCOREAPP3_1_OR_GREATER [Obsolete(Obsoletions.GetContextInfoMessage, DiagnosticId = Obsoletions.GetContextInfoDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] +#endif [SupportedOSPlatform("windows")] public object GetContextInfo() { @@ -763,6 +765,7 @@ private void GetContextInfo(out Matrix3x2 cumulativeTransform, bool calculateCli } } +#if NETCOREAPP3_1_OR_GREATER /// /// Gets the cumulative offset. /// @@ -789,6 +792,7 @@ public void GetContextInfo(out PointF offset, out Region? clip) Vector2 translation = cumulativeTransform.Translation; offset = new PointF(translation.X, translation.Y); } +#endif public RectangleF VisibleClipBounds { diff --git a/src/libraries/System.Drawing.Common/src/misc/GDI/WindowsGraphics.cs b/src/libraries/System.Drawing.Common/src/misc/GDI/WindowsGraphics.cs index 6257a8219199b0..1322bd6e81d08b 100644 --- a/src/libraries/System.Drawing.Common/src/misc/GDI/WindowsGraphics.cs +++ b/src/libraries/System.Drawing.Common/src/misc/GDI/WindowsGraphics.cs @@ -61,6 +61,7 @@ public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties p { Region? clip = null; +#if NETCOREAPP3_1_OR_GREATER if (properties.HasFlag(ApplyGraphicsProperties.Clipping)) { g.GetContextInfo(out offset, out clip); @@ -69,6 +70,21 @@ public static WindowsGraphics FromGraphics(Graphics g, ApplyGraphicsProperties p { g.GetContextInfo(out offset); } +#else + Matrix? worldTransf = null; + if (g.GetContextInfo() is object[] data && data.Length == 2) + { + if (properties.HasFlag(ApplyGraphicsProperties.Clipping)) + { + clip = data[0] as Region; + } + worldTransf = data[1] as Matrix; + if (worldTransf != null) + { + offset = worldTransf.Offset; + } + } +#endif if (clip is not null) { diff --git a/src/libraries/System.Drawing.Common/tests/PenTests.cs b/src/libraries/System.Drawing.Common/tests/PenTests.cs index 3b413bc0f0b9dd..b5f39c4483855c 100644 --- a/src/libraries/System.Drawing.Common/tests/PenTests.cs +++ b/src/libraries/System.Drawing.Common/tests/PenTests.cs @@ -46,6 +46,7 @@ public static IEnumerable Ctor_Brush_Width_TestData() yield return new object[] { new SolidBrush(Color.Red), float.MaxValue, PenType.SolidColor }; } + [ActiveIssue("https://github.com/dotnet/runtime/issues/60731", TestPlatforms.Windows)] [ConditionalTheory(Helpers.IsDrawingSupported)] [MemberData(nameof(Ctor_Brush_Width_TestData))] public void Ctor_Brush_Width(T brush, float width, PenType expectedPenType) where T : Brush @@ -96,6 +97,7 @@ public void Ctor_Color() } } + [ActiveIssue("https://github.com/dotnet/runtime/issues/60731", TestPlatforms.Windows)] [ConditionalTheory(Helpers.IsDrawingSupported)] [InlineData(-1)] [InlineData(0)] diff --git a/src/libraries/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs b/src/libraries/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs index 480f6200208d30..9c4eb3000ae8b6 100644 --- a/src/libraries/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs +++ b/src/libraries/System.Dynamic.Runtime/tests/Dynamic.DynamicType/Conformance.dynamic.dynamicType.basic.cs @@ -3392,7 +3392,7 @@ public static int MainMethod(string[] args) } ; - if (d.GetType() != typeof(dynamic[])) + if (d.GetType() != typeof(object[])) return 1; return 0; } @@ -3420,7 +3420,7 @@ public static int MainMethod(string[] args) } ; - if (d.GetType() != typeof(dynamic[])) + if (d.GetType() != typeof(object[])) return 1; return 0; } @@ -3456,7 +3456,7 @@ public static int MainMethod(string[] args) } ; - if (d.GetType() != typeof(dynamic[])) + if (d.GetType() != typeof(object[])) return 1; return 0; } diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs index c89088b7119b6d..dac3b98dc2cea9 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs @@ -667,12 +667,6 @@ public void LcidTest(int lcid, string[] cultureNames, string specificCultureName CultureInfo ci = new CultureInfo(lcid); Assert.Contains(ci.Name, cultureNames, StringComparer.OrdinalIgnoreCase); - if (ci.LCID == 0x1000) - { - // Unsupported culture. - return; - } - Assert.True(lcid == ci.LCID || (ushort)lcid == (ushort)ci.LCID); Assert.True(ci.UseUserOverride, "UseUserOverride for lcid created culture expected to be true"); Assert.False(ci.IsReadOnly, "IsReadOnly for lcid created culture expected to be false"); @@ -719,10 +713,14 @@ public void LcidTest(int lcid, string[] cultureNames, string specificCultureName ci = CultureInfo.CreateSpecificCulture(cultureNames[0]); TestCultureName(specificCultureName, ci.Name); - ci = CultureInfo.GetCultureInfoByIetfLanguageTag(cultureNames[0]); - Assert.Contains(ci.Name, cultureNames, StringComparer.OrdinalIgnoreCase); - TestCultureName(ci.Name, ci.IetfLanguageTag); - Assert.True(lcid == ci.KeyboardLayoutId || (ushort)lcid == (ushort)ci.KeyboardLayoutId); + // CultureInfo.GetCultureInfoByIetfLanguageTag doesn't support alternative sort LCID's. + if (lcid <= 0xffff && lcid != 0x040a) + { + ci = CultureInfo.GetCultureInfoByIetfLanguageTag(cultureNames[0]); + Assert.Contains(ci.Name, cultureNames, StringComparer.OrdinalIgnoreCase); + TestCultureName(ci.Name, ci.IetfLanguageTag); + Assert.True(lcid == ci.KeyboardLayoutId || (ushort)lcid == (ushort)ci.KeyboardLayoutId); + } if (ci.GetConsoleFallbackUICulture().Name != "") { @@ -733,8 +731,8 @@ public void LcidTest(int lcid, string[] cultureNames, string specificCultureName { AssertExtensions.Throws(() => new CultureInfo(lcid)); } - - } + + } private static string[] hans = new[] { "zh-CN", "zh-CHS", "zh-Hans" }; private static string[] hant = new[] { "zh-HK", "zh-CHT", "zh-Hant" }; diff --git a/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs b/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs index e6399bb5cc6177..5a5e3dada218b1 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs @@ -32,12 +32,15 @@ public static IEnumerable GetCultureInfoTestData() if (PlatformDetection.IsIcuGlobalization) { - yield return new object[] { "x\u0000X-Yy", "x" }; // Null byte + if (PlatformDetection.IsNotWindows) + { + yield return new object[] { "x\u0000X-Yy", "x" }; // Null byte + yield return new object[] { "zh-cmn", "zh-CMN" }; + yield return new object[] { "zh-CMN-HANS" }; + yield return new object[] { "zh-cmn-Hant", "zh-CMN-HANT" }; + } yield return new object[] { "sgn-BE-FR" }; yield return new object[] { "zh-min-nan", "nan" }; - yield return new object[] { "zh-cmn", "zh-CMN" }; - yield return new object[] { "zh-CMN-HANS" }; - yield return new object[] { "zh-cmn-Hant", "zh-CMN-HANT" }; yield return new object[] { "zh-gan", "gan" }; yield return new object[] { "zh-Hans-CN" }; yield return new object[] { "zh-Hans-SG" }; @@ -58,6 +61,17 @@ public static IEnumerable GetCultureInfoTestData() } } + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] // Windows specific behavior + [InlineData("x\u0000X-Yy")] + [InlineData("zh-cmn")] + [InlineData("zh-CMN-HANS")] + [InlineData("zh-cmn-Hant")] + public void TestIvalidCultureNames(string cultureName) + { + Assert.Throws(() => new CultureInfo(cultureName)); + } + [ConditionalTheory(nameof(PlatformSupportsFakeCulture))] [MemberData(nameof(GetCultureInfoTestData))] public void GetCultureInfo(string name, string expected = null) diff --git a/src/libraries/System.Globalization/tests/IcuTests.cs b/src/libraries/System.Globalization/tests/IcuTests.cs index 190da7f676c807..e28872759bea7f 100644 --- a/src/libraries/System.Globalization/tests/IcuTests.cs +++ b/src/libraries/System.Globalization/tests/IcuTests.cs @@ -10,7 +10,9 @@ namespace System.Globalization.Tests public class IcuTests { private static bool IsIcuCompatiblePlatform => PlatformDetection.IsNotWindows || - PlatformDetection.IsWindows10Version1903OrGreater; + PlatformDetection.IsWindows10Version1903OrGreater && + // Server core doesn't have icu.dll on SysWOW64 + !(PlatformDetection.IsWindowsServerCore && PlatformDetection.IsX86Process); [ConditionalFact(nameof(IsIcuCompatiblePlatform))] public static void IcuShouldBeUsedByDefault() diff --git a/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs b/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs index eae275bc0b1a3e..c36ba960230ce6 100644 --- a/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs +++ b/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs @@ -287,7 +287,7 @@ public static IEnumerable ToLower_TestData() } yield return new object[] { cultureName, "\u0130", "i" }; yield return new object[] { cultureName, "i", "i" }; - + } // ICU has special tailoring for the en-US-POSIX locale which treats "i" and "I" as different letters @@ -478,5 +478,13 @@ public void ToStringTest(string name, string expected) { Assert.Equal(expected, new CultureInfo(name).TextInfo.ToString()); } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + [InlineData("es-ES")] + [InlineData("es-ES_tradnl")] + public void TestAsciiCodePageWithCulturesWithAlternativeSortNames(string cultureName) + { + Assert.Equal(1252, CultureInfo.GetCultureInfo(cultureName).TextInfo.ANSICodePage); + } } } diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs index 5d800c1f62ca71..fe725937441e24 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFileExtensions.ZipArchiveEntry.Extract.cs @@ -83,7 +83,7 @@ public static void ExtractToFile(this ZipArchiveEntry source, string destination { File.SetLastWriteTime(destinationFileName, source.LastWriteTime.DateTime); } - catch (UnauthorizedAccessException) + catch { // some OSes like Android (#35374) might not support setting the last write time, the extraction should not fail because of that } diff --git a/src/libraries/System.IO.FileSystem.Watcher/Directory.Build.props b/src/libraries/System.IO.FileSystem.Watcher/Directory.Build.props index ce244cbea56199..c581a9ef9e5a84 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/Directory.Build.props +++ b/src/libraries/System.IO.FileSystem.Watcher/Directory.Build.props @@ -3,6 +3,7 @@ Microsoft true - browser + browser;ios;tvos + maccatalyst \ No newline at end of file diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj index b6b0579e63026f..056431aa17e502 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent);$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent);$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-FreeBSD enable @@ -75,7 +75,7 @@ - + diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs index 94b42c5041cc9f..9659dd75903a73 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/AssemblyInfo.cs @@ -4,4 +4,4 @@ using System; using Xunit; -[assembly: SkipOnPlatform(TestPlatforms.Browser, "System.IO.FileSystem.Watcher is not supported on Browser")] +[assembly: SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "System.IO.FileSystem.Watcher is not supported on Browser/iOS/tvOS")] diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.WaitForChanged.cs b/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.WaitForChanged.cs index aec8019cdceb9d..cce5f54469f2dd 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.WaitForChanged.cs +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/FileSystemWatcher.WaitForChanged.cs @@ -111,6 +111,7 @@ public void NonZeroTimeout_NoEvents_TimesOut(bool enabledBeforeWait) [InlineData(WatcherChangeTypes.Changed, false)] [InlineData(WatcherChangeTypes.Renamed, true)] [InlineData(WatcherChangeTypes.All, true)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/58418", typeof(PlatformDetection), nameof(PlatformDetection.IsMacCatalyst), nameof(PlatformDetection.IsArm64Process))] public void NonZeroTimeout_NoActivity_TimesOut(WatcherChangeTypes changeType, bool enabledBeforeWait) { using (var testDirectory = new TempDirectory(GetTestFilePath())) diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj index 67c502fa83412a..1139f2ecf2a0cd 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj @@ -1,8 +1,8 @@ true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD - true + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-FreeBSD + true diff --git a/src/libraries/System.IO.FileSystem/tests/Base/BaseGetSetTimes.cs b/src/libraries/System.IO.FileSystem/tests/Base/BaseGetSetTimes.cs index a959e317682f4e..d55171847a0b7d 100644 --- a/src/libraries/System.IO.FileSystem/tests/Base/BaseGetSetTimes.cs +++ b/src/libraries/System.IO.FileSystem/tests/Base/BaseGetSetTimes.cs @@ -20,7 +20,9 @@ public abstract class BaseGetSetTimes : FileSystemTest protected static bool LowTemporalResolution => PlatformDetection.IsBrowser || isHFS; protected static bool HighTemporalResolution => !LowTemporalResolution; - protected abstract T GetExistingItem(); + protected abstract bool CanBeReadOnly { get; } + + protected abstract T GetExistingItem(bool readOnly = false); protected abstract T GetMissingItem(); protected abstract string GetItemPath(T item); @@ -42,11 +44,8 @@ public static TimeFunction Create(SetTime setter, GetTime getter, DateTimeKind k public DateTimeKind Kind => Item3; } - [Fact] - public void SettingUpdatesProperties() + private void SettingUpdatesPropertiesCore(T item) { - T item = GetExistingItem(); - Assert.All(TimeFunctions(requiresRoundtripping: true), (function) => { // Checking that milliseconds are not dropped after setter. @@ -70,6 +69,25 @@ public void SettingUpdatesProperties() }); } + [Fact] + public void SettingUpdatesProperties() + { + T item = GetExistingItem(); + SettingUpdatesPropertiesCore(item); + } + + [Fact] + public void SettingUpdatesPropertiesWhenReadOnly() + { + if (!CanBeReadOnly) + { + return; // directories can't be read only, so automatic pass + } + + T item = GetExistingItem(readOnly: true); + SettingUpdatesPropertiesCore(item); + } + [Fact] public void CanGetAllTimesAfterCreation() { diff --git a/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystem.cs b/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystem.cs index 0682f8ce16e5bb..ffecf938cb3df3 100644 --- a/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystem.cs +++ b/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystem.cs @@ -1,7 +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.Collections.Generic; +using System.IO.Enumeration; +using System.Linq; using Xunit; namespace System.IO.Tests @@ -156,7 +157,7 @@ public void ResolveLinkTarget_ReturnsNull_NotALink(bool returnFinalTarget) } [Theory] - [MemberData(nameof(ResolveLinkTarget_PathToTarget_Data))] + [MemberData(nameof(SymbolicLink_ResolveLinkTarget_PathToTarget_Data))] public void ResolveLinkTarget_Succeeds(string pathToTarget, bool returnFinalTarget) { string linkPath = GetRandomLinkPath(); @@ -342,32 +343,6 @@ public void DetectLinkReferenceToSelf() Assert.Throws(() => ResolveLinkTarget(linkPath, returnFinalTarget: true)); } - [Fact] - public void CreateSymbolicLink_WrongTargetType_Throws() - { - // dirLink -> file - // fileLink -> dir - - string targetPath = GetRandomFilePath(); - CreateFileOrDirectory(targetPath, createOpposite: true); // The underlying file system entry needs to be different - Assert.Throws(() => CreateSymbolicLink(GetRandomFilePath(), targetPath)); - } - - [Fact] - public void CreateSymbolicLink_WrongTargetType_Indirect_Throws() - { - // link-2 (dir) -> link-1 (file) -> file - // link-2 (file) -> link-1 (dir) -> dir - string targetPath = GetRandomFilePath(); - string firstLinkPath = GetRandomFilePath(); - string secondLinkPath = GetRandomFilePath(); - - CreateFileOrDirectory(targetPath, createOpposite: true); - CreateSymbolicLink_Opposite(firstLinkPath, targetPath); - - Assert.Throws(() => CreateSymbolicLink(secondLinkPath, firstLinkPath)); - } - [Fact] public void CreateSymbolicLink_CorrectTargetType_Indirect_Succeeds() { @@ -427,14 +402,14 @@ private void ResolveLinkTarget_ReturnFinalTarget(string link1Path, string link1T Assert.True(link2Info.Exists); Assert.True(link2Info.Attributes.HasFlag(FileAttributes.ReparsePoint)); AssertIsCorrectTypeAndDirectoryAttribute(link2Info); - Assert.Equal(link2Target, link2Info.LinkTarget); + AssertPathEquals_RelativeSegments(link2Target, link2Info.LinkTarget); // link1 to link2 FileSystemInfo link1Info = CreateSymbolicLink(link1Path, link1Target); Assert.True(link1Info.Exists); Assert.True(link1Info.Attributes.HasFlag(FileAttributes.ReparsePoint)); AssertIsCorrectTypeAndDirectoryAttribute(link1Info); - Assert.Equal(link1Target, link1Info.LinkTarget); + AssertPathEquals_RelativeSegments(link1Target, link1Info.LinkTarget); // link1: do not follow symlinks FileSystemInfo link1TargetInfo = ResolveLinkTarget(link1Path, returnFinalTarget: false); @@ -442,7 +417,7 @@ private void ResolveLinkTarget_ReturnFinalTarget(string link1Path, string link1T AssertIsCorrectTypeAndDirectoryAttribute(link1TargetInfo); Assert.True(link1TargetInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)); Assert.Equal(link2Path, link1TargetInfo.FullName); - Assert.Equal(link2Target, link1TargetInfo.LinkTarget); + AssertPathEquals_RelativeSegments(link2Target, link1TargetInfo.LinkTarget); // link2: do not follow symlinks FileSystemInfo link2TargetInfo = ResolveLinkTarget(link2Path, returnFinalTarget: false); @@ -458,13 +433,25 @@ private void ResolveLinkTarget_ReturnFinalTarget(string link1Path, string link1T AssertIsCorrectTypeAndDirectoryAttribute(finalTarget); Assert.False(finalTarget.Attributes.HasFlag(FileAttributes.ReparsePoint)); Assert.Equal(filePath, finalTarget.FullName); + + void AssertPathEquals_RelativeSegments(string expected, string actual) + { +#if WINDOWS + // DeviceIoControl canonicalizes the target path i.e: removes redundant segments. + int rootLength = PathInternal.GetRootLength(expected); + if (rootLength > 0) + { + expected = PathInternal.RemoveRelativeSegments(expected, rootLength); + } +#endif + Assert.Equal(expected, actual); + } } + // Must call inside a remote executor protected void CreateSymbolicLink_PathToTarget_RelativeToLinkPath_Internal(bool createOpposite) { - string tempCwd = GetRandomDirPath(); - Directory.CreateDirectory(tempCwd); - Directory.SetCurrentDirectory(tempCwd); + string tempCwd = ChangeCurrentDirectory(); // Create a dummy file or directory in cwd. string fileOrDirectoryInCwd = GetRandomFileName(); @@ -483,49 +470,32 @@ protected void CreateSymbolicLink_PathToTarget_RelativeToLinkPath_Internal(bool Assert.Equal(Path.GetDirectoryName(linkInfo.FullName), Path.GetDirectoryName(targetInfo.FullName)); } - public static IEnumerable ResolveLinkTarget_PathToTarget_Data + protected static string? GetAppExecLinkPath() { - get + string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA"); + if (localAppDataPath is null) { - foreach (string path in PathToTargetData) - { - yield return new object[] { path, false }; - yield return new object[] { path, true }; - } + return null; } - } - internal static IEnumerable PathToTargetData - { - get + string windowsAppsDir = Path.Join(localAppDataPath, "Microsoft", "WindowsApps"); + + if (!Directory.Exists(windowsAppsDir)) { - if (OperatingSystem.IsWindows()) - { - //Non-rooted relative - yield return "foo"; - yield return @".\foo"; - yield return @"..\foo"; - // Rooted relative - yield return @"\foo"; - // Rooted absolute - yield return Path.Combine(Path.GetTempPath(), "foo"); - // Extended DOS - yield return Path.Combine(@"\\?\", Path.GetTempPath(), "foo"); - // UNC - yield return @"\\LOCALHOST\share\path"; - } - else - { - //Non-rooted relative - yield return "foo"; - yield return "./foo"; - yield return "../foo"; - // Rooted relative - yield return "/foo"; - // Rooted absolute - Path.Combine(Path.GetTempPath(), "foo"); - } + return null; } + + var opts = new EnumerationOptions { RecurseSubdirectories = true }; + + return new FileSystemEnumerable( + windowsAppsDir, + (ref FileSystemEntry entry) => entry.ToFullPath(), + opts) + { + ShouldIncludePredicate = (ref FileSystemEntry entry) => + FileSystemName.MatchesWin32Expression("*.exe", entry.FileName) && + (entry.Attributes & FileAttributes.ReparsePoint) != 0 + }.FirstOrDefault(); } } } diff --git a/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystemInfo.cs b/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystemInfo.cs index e82864248eb434..05e18f14e9ecf2 100644 --- a/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystemInfo.cs +++ b/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.FileSystemInfo.cs @@ -1,8 +1,6 @@ // 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.Diagnostics; using Xunit; namespace System.IO.Tests @@ -54,7 +52,7 @@ public void LinkTarget_ReturnsNull_NotALink() } [Theory] - [MemberData(nameof(LinkTarget_PathToTarget_Data))] + [MemberData(nameof(SymbolicLink_LinkTarget_PathToTarget_Data))] public void LinkTarget_Succeeds(string pathToTarget) { FileSystemInfo linkInfo = CreateSymbolicLink(GetRandomLinkPath(), pathToTarget); @@ -86,16 +84,5 @@ public void LinkTarget_RefreshesCorrectly() Assert.Equal(newPathToTarget, linkInfo.LinkTarget); Assert.Equal(newLinkInfo.LinkTarget, linkInfo.LinkTarget); } - - public static IEnumerable LinkTarget_PathToTarget_Data - { - get - { - foreach (string path in PathToTargetData) - { - yield return new object[] { path }; - } - } - } } } diff --git a/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.cs b/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.cs index f120cdf10eba53..d506e7e5e9b2b2 100644 --- a/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.cs +++ b/src/libraries/System.IO.FileSystem/tests/Base/SymbolicLinks/BaseSymbolicLinks.cs @@ -1,10 +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.Buffers; -using System.Diagnostics; -using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; +using System.Collections.Generic; +using System.Linq; using Xunit; namespace System.IO.Tests @@ -36,5 +34,108 @@ protected DirectoryInfo CreateSelfReferencingSymbolicLink() protected string GetRandomDirPath() => Path.Join(ActualTestDirectory.Value, GetRandomDirName()); private Lazy ActualTestDirectory => new Lazy(() => GetTestDirectoryActualCasing()); + + /// + /// Changes the current working directory path to a new temporary directory. + /// Important: Make sure to call this inside a remote executor to avoid changing the cwd for all tests in same process. + /// + /// The path of the new cwd. + protected string ChangeCurrentDirectory() + { + string tempCwd = GetRandomDirPath(); + Directory.CreateDirectory(tempCwd); + Directory.SetCurrentDirectory(tempCwd); + return tempCwd; + } + + public static IEnumerable SymbolicLink_LinkTarget_PathToTarget_Data + { + get + { + foreach (string path in PathToTargetData.Union(PathToTargetUncData)) + { + yield return new object[] { path }; + } + } + } + + public static IEnumerable SymbolicLink_ResolveLinkTarget_PathToTarget_Data + { + get + { + foreach (string path in PathToTargetData.Union(PathToTargetUncData)) + { + yield return new object[] { path, false }; + yield return new object[] { path, true }; + } + } + } + + // Junctions doesn't support remote shares. + public static IEnumerable Junction_LinkTarget_PathToTarget_Data + { + get + { + foreach (string path in PathToTargetData) + { + yield return new object[] { path }; + } + } + } + + public static IEnumerable Junction_ResolveLinkTarget_PathToTarget_Data + { + get + { + foreach (string path in PathToTargetData) + { + yield return new object[] { path, false }; + yield return new object[] { path, true }; + } + } + } + + internal static IEnumerable PathToTargetData + { + get + { + if (OperatingSystem.IsWindows()) + { + //Non-rooted relative + yield return "foo"; + yield return @".\foo"; + yield return @"..\foo"; + // Rooted relative + yield return @"\foo"; + // Rooted absolute + yield return Path.Combine(Path.GetTempPath(), "foo"); + // Extended DOS + yield return Path.Combine(@"\\?\", Path.GetTempPath(), "foo"); + } + else + { + //Non-rooted relative + yield return "foo"; + yield return "./foo"; + yield return "../foo"; + // Rooted relative + yield return "/foo"; + // Rooted absolute + Path.Combine(Path.GetTempPath(), "foo"); + } + } + } + + internal static IEnumerable PathToTargetUncData + { + get + { + if (OperatingSystem.IsWindows()) + { + // UNC/Remote Share + yield return @"\\LOCALHOST\share\path"; + } + } + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs b/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs index fb3a74305bca2c..4e53a93a4e03a9 100644 --- a/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs +++ b/src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory.cs @@ -270,8 +270,10 @@ public void DirectoryLongerThanMaxLongPathWithExtendedSyntax_ThrowsException() { var paths = IOInputs.GetPathsLongerThanMaxLongPath(GetTestFilePath(), useExtendedSyntax: true); + // Ideally this should be PathTooLongException or DirectoryNotFoundException but on some machines + // windows gives us ERROR_INVALID_NAME, producing IOException. Assert.All(paths, path => - AssertExtensions.ThrowsAny(() => Create(path))); + AssertExtensions.ThrowsAny(() => Create(path))); } [ConditionalFact(nameof(LongPathsAreNotBlocked), nameof(UsingNewNormalization))] diff --git a/src/libraries/System.IO.FileSystem/tests/Directory/GetSetTimes.cs b/src/libraries/System.IO.FileSystem/tests/Directory/GetSetTimes.cs index 0a23d638c138af..1fc00ba74249d6 100644 --- a/src/libraries/System.IO.FileSystem/tests/Directory/GetSetTimes.cs +++ b/src/libraries/System.IO.FileSystem/tests/Directory/GetSetTimes.cs @@ -7,7 +7,9 @@ namespace System.IO.Tests { public class Directory_GetSetTimes : StaticGetSetTimes { - protected override string GetExistingItem() => Directory.CreateDirectory(GetTestFilePath()).FullName; + protected override bool CanBeReadOnly => false; + + protected override string GetExistingItem(bool _) => Directory.CreateDirectory(GetTestFilePath()).FullName; public override IEnumerable TimeFunctions(bool requiresRoundtripping = false) { diff --git a/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/GetSetTimes.cs b/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/GetSetTimes.cs index 2dad268a79a460..c45c6169ada958 100644 --- a/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/GetSetTimes.cs +++ b/src/libraries/System.IO.FileSystem/tests/DirectoryInfo/GetSetTimes.cs @@ -7,7 +7,9 @@ namespace System.IO.Tests { public class DirectoryInfo_GetSetTimes : InfoGetSetTimes { - protected override DirectoryInfo GetExistingItem() => Directory.CreateDirectory(GetTestFilePath()); + protected override bool CanBeReadOnly => false; + + protected override DirectoryInfo GetExistingItem(bool _) => Directory.CreateDirectory(GetTestFilePath()); protected override DirectoryInfo GetMissingItem() => new DirectoryInfo(GetTestFilePath()); diff --git a/src/libraries/System.IO.FileSystem/tests/Enumeration/SpecialDirectoryTests.cs b/src/libraries/System.IO.FileSystem/tests/Enumeration/SpecialDirectoryTests.cs index 39a747179481a8..12edab6601e803 100644 --- a/src/libraries/System.IO.FileSystem/tests/Enumeration/SpecialDirectoryTests.cs +++ b/src/libraries/System.IO.FileSystem/tests/Enumeration/SpecialDirectoryTests.cs @@ -60,7 +60,14 @@ public void SkippingHiddenFiles() { // Files that begin with periods are considered hidden on Unix string[] paths = GetNames(TestDirectory, new EnumerationOptions { ReturnSpecialDirectories = true, AttributesToSkip = 0 }); - Assert.Contains(".", paths); + + if (!PlatformDetection.IsWindows10Version22000OrGreater) + { + // Sometimes this is not returned - presumably an OS bug. + // This occurs often on Windows 11, very rarely otherwise. + Assert.Contains(".", paths); + } + Assert.Contains("..", paths); } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs new file mode 100644 index 00000000000000..015ba30b6ad7c1 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.Windows.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.XUnitExtensions; +using System.Diagnostics; +using System.Diagnostics.Eventing.Reader; +using System.Linq; +using System.Security; +using System.ServiceProcess; +using Xunit; +using Xunit.Abstractions; + +namespace System.IO.Tests +{ + public partial class EncryptDecrypt + { + partial void EnsureEFSServiceStarted() + { + try + { + using var sc = new ServiceController("EFS"); + _output.WriteLine($"EFS service is: {sc.Status}"); + if (sc.Status != ServiceControllerStatus.Running) + { + _output.WriteLine("Trying to start EFS service"); + sc.Start(); + _output.WriteLine($"EFS service is now: {sc.Status}"); + } + } + catch (Exception e) + { + _output.WriteLine(e.ToString()); + } + } + + partial void LogEFSDiagnostics() + { + int hours = 1; // how many hours to look backwards + string query = @$" + + + + + + + *[System[TimeCreated[timediff(@SystemTime) >= {hours * 60 * 60 * 1000L}]]] + + + "; + + var eventQuery = new EventLogQuery("System", PathType.LogName, query); + + using var eventReader = new EventLogReader(eventQuery); + + EventRecord record = eventReader.ReadEvent(); + var garbage = new string[] { "Background Intelligent", "Intel", "Defender", "Intune", "BITS", "NetBT"}; + + _output.WriteLine("===== Dumping recent relevant events: ====="); + while (record != null) + { + string description = ""; + try + { + description = record.FormatDescription(); + } + catch (EventLogException) { } + + if (!garbage.Any(term => description.Contains(term, StringComparison.OrdinalIgnoreCase))) + { + _output.WriteLine($"{record.TimeCreated} {record.ProviderName} [{record.LevelDisplayName} {record.Id}] {description.Replace("\r\n", " ")}"); + } + + record = eventReader.ReadEvent(); + } + + _output.WriteLine("==== Finished dumping ====="); + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs index 984afef972bc41..1dbac453e48297 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/EncryptDecrypt.cs @@ -1,17 +1,28 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.DotNet.XUnitExtensions; using System.Diagnostics; +using System.Diagnostics.Eventing.Reader; using System.Security; +using System.ServiceProcess; using Xunit; +using Xunit.Abstractions; namespace System.IO.Tests { [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - public class EncryptDecrypt : FileSystemTest + public partial class EncryptDecrypt : FileSystemTest { + private readonly ITestOutputHelper _output; + + public EncryptDecrypt(ITestOutputHelper output) + { + _output = output; + } + [Fact] - public static void NullArg_ThrowsException() + public void NullArg_ThrowsException() { AssertExtensions.Throws("path", () => File.Encrypt(null)); AssertExtensions.Throws("path", () => File.Decrypt(null)); @@ -19,7 +30,7 @@ public static void NullArg_ThrowsException() [SkipOnTargetFramework(TargetFrameworkMonikers.Netcoreapp)] [Fact] - public static void EncryptDecrypt_NotSupported() + public void EncryptDecrypt_NotSupported() { Assert.Throws(() => File.Encrypt("path")); Assert.Throws(() => File.Decrypt("path")); @@ -29,7 +40,8 @@ public static void EncryptDecrypt_NotSupported() // because EFS (Encrypted File System), its underlying technology, is not available on these operating systems. [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsHomeEdition))] [PlatformSpecific(TestPlatforms.Windows)] - public static void EncryptDecrypt_Read() + [OuterLoop] // Occasional failures: https://github.com/dotnet/runtime/issues/12339 + public void EncryptDecrypt_Read() { string tmpFileName = Path.GetTempFileName(); string textContentToEncrypt = "Content to encrypt"; @@ -39,14 +51,26 @@ public static void EncryptDecrypt_Read() string fileContentRead = File.ReadAllText(tmpFileName); Assert.Equal(textContentToEncrypt, fileContentRead); + EnsureEFSServiceStarted(); + try { File.Encrypt(tmpFileName); } - catch (IOException e) when (e.HResult == unchecked((int)0x80070490)) + catch (IOException e) when (e.HResult == unchecked((int)0x80070490) || + e.HResult == unchecked((int)0x80071776) || + e.HResult == unchecked((int)0x800701AE)) { // Ignore ERROR_NOT_FOUND 1168 (0x490). It is reported when EFS is disabled by domain policy. - return; + // Ignore ERROR_NO_USER_KEYS (0x1776). This occurs when no user key exists to encrypt with. + // Ignore ERROR_ENCRYPTION_DISABLED (0x1AE). This occurs when EFS is disabled by group policy on the volume. + throw new SkipTestException($"Encrypt not available. Error 0x{e.HResult:X}"); + } + catch (IOException e) + { + _output.WriteLine($"Encrypt failed with {e.Message} 0x{e.HResult:X}"); + LogEFSDiagnostics(); + throw; } Assert.Equal(fileContentRead, File.ReadAllText(tmpFileName)); @@ -61,5 +85,9 @@ public static void EncryptDecrypt_Read() File.Delete(tmpFileName); } } + + partial void EnsureEFSServiceStarted(); // no-op on Unix + + partial void LogEFSDiagnostics(); // no-op on Unix currently } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs b/src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs index 67a13bcf7df2b5..f27e79da3f565a 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/GetSetTimes.cs @@ -11,14 +11,22 @@ namespace System.IO.Tests { public class File_GetSetTimes : StaticGetSetTimes { + protected override bool CanBeReadOnly => true; + // OSX has the limitation of setting upto 2262-04-11T23:47:16 (long.Max) date. // 32bit Unix has time_t up to ~ 2038. private static bool SupportsLongMaxDateTime => PlatformDetection.IsWindows || (!PlatformDetection.Is32BitProcess && !PlatformDetection.IsOSXLike); - protected override string GetExistingItem() + protected override string GetExistingItem(bool readOnly = false) { string path = GetTestFilePath(); File.Create(path).Dispose(); + + if (readOnly) + { + File.SetAttributes(path, FileAttributes.ReadOnly); + } + return path; } diff --git a/src/libraries/System.IO.FileSystem/tests/File/Open.cs b/src/libraries/System.IO.FileSystem/tests/File/Open.cs index d014cf0efb94d8..bd9b38b121b886 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/Open.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/Open.cs @@ -42,15 +42,14 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA } } - public class File_Open_str_options_as : FileStream_ctor_options_as + public class File_Open_str_options : FileStream_ctor_options { protected override FileStream CreateFileStream(string path, FileMode mode) { return File.Open(path, new FileStreamOptions { Mode = mode, - Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, - PreallocationSize = PreallocationSize + Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite }); } @@ -59,12 +58,23 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA return File.Open(path, new FileStreamOptions { Mode = mode, - Access = access, - PreallocationSize = PreallocationSize + Access = access }); } protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) + { + return File.Open(path, + new FileStreamOptions { + Mode = mode, + Access = access, + Share = share, + Options = options, + BufferSize = bufferSize + }); + } + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) { return File.Open(path, new FileStreamOptions { @@ -73,7 +83,7 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA Share = share, Options = options, BufferSize = bufferSize, - PreallocationSize = PreallocationSize + PreallocationSize = preallocationSize }); } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/OpenHandle.cs b/src/libraries/System.IO.FileSystem/tests/File/OpenHandle.cs index a8b3619fb51cf7..120ed9aec222ef 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/OpenHandle.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/OpenHandle.cs @@ -7,28 +7,24 @@ namespace System.IO.Tests { // to avoid a lot of code duplication, we reuse FileStream tests - public class File_OpenHandle : FileStream_ctor_options_as + public class File_OpenHandle : FileStream_ctor_options { protected override string GetExpectedParamName(string paramName) => paramName; protected override FileStream CreateFileStream(string path, FileMode mode) { FileAccess access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite; - return new FileStream(File.OpenHandle(path, mode, access, preallocationSize: PreallocationSize), access); + return new FileStream(File.OpenHandle(path, mode, access), access); } protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) - => new FileStream(File.OpenHandle(path, mode, access, preallocationSize: PreallocationSize), access); + => new FileStream(File.OpenHandle(path, mode, access), access); protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) - => new FileStream(File.OpenHandle(path, mode, access, share, options, PreallocationSize), access, bufferSize, (options & FileOptions.Asynchronous) != 0); + => new FileStream(File.OpenHandle(path, mode, access, share, options), access, bufferSize, (options & FileOptions.Asynchronous) != 0); - [Fact] - public override void NegativePreallocationSizeThrows() - { - ArgumentOutOfRangeException ex = Assert.Throws( - () => File.OpenHandle("validPath", FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.None, preallocationSize: -1)); - } + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) + => new FileStream(File.OpenHandle(path, mode, access, share, options, preallocationSize), access, bufferSize, (options & FileOptions.Asynchronous) != 0); [ActiveIssue("https://github.com/dotnet/runtime/issues/53432")] [Theory, MemberData(nameof(StreamSpecifiers))] diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs index 54c76437663353..a7815dd40eb126 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytes.cs @@ -2,8 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text; +using System.Threading; using System.Threading.Tasks; using Xunit; +using System.IO.Pipes; +using Microsoft.DotNet.XUnitExtensions; namespace System.IO.Tests { @@ -54,21 +57,6 @@ public void ValidWrite(int size) File.Delete(path); } - [Fact] - [OuterLoop] - [ActiveIssue("https://github.com/dotnet/runtime/issues/45954", TestPlatforms.Browser)] - public void ReadFileOver2GB() - { - string path = GetTestFilePath(); - using (FileStream fs = File.Create(path)) - { - fs.SetLength(int.MaxValue + 1L); - } - - // File is too large for ReadAllBytes at once - Assert.Throws(() => File.ReadAllBytes(path)); - } - [Fact] public void Overwrite() { @@ -172,5 +160,30 @@ public void ProcFs_NotEmpty(string path) { Assert.InRange(File.ReadAllBytes(path).Length, 1, int.MaxValue); } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task ReadAllBytes_NonSeekableFileStream_InUnix() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + var contentBytes = new byte[] { 1, 2, 3 }; + + await Task.WhenAll( + Task.Run(() => + { + byte[] readBytes = File.ReadAllBytes(fifoPath); + Assert.Equal(contentBytes, readBytes); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + foreach (byte content in contentBytes) + { + fs.WriteByte(content); + } + })); + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs index 748c01dbffb8f6..c4f147cbb80092 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/ReadWriteAllBytesAsync.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using Xunit; +using System.IO.Pipes; namespace System.IO.Tests { @@ -68,21 +69,6 @@ public Task AlreadyCanceledAsync() async () => await File.WriteAllBytesAsync(path, new byte[0], token)); } - [Fact] - [OuterLoop] - [ActiveIssue("https://github.com/dotnet/runtime/issues/45954", TestPlatforms.Browser)] - public Task ReadFileOver2GBAsync() - { - string path = GetTestFilePath(); - using (FileStream fs = File.Create(path)) - { - fs.SetLength(int.MaxValue + 1L); - } - - // File is too large for ReadAllBytes at once - return Assert.ThrowsAsync(async () => await File.ReadAllBytesAsync(path)); - } - [Fact] public async Task OverwriteAsync() { @@ -186,5 +172,61 @@ public async Task ProcFs_NotEmpty(string path) { Assert.InRange((await File.ReadAllBytesAsync(path)).Length, 1, int.MaxValue); } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] // DOS device paths (\\.\ and \\?\) are a Windows concept + public async Task ReadAllBytesAsync_NonSeekableFileStream_InWindows() + { + string pipeName = FileSystemTest.GetNamedPipeServerStreamName(); + string pipePath = Path.GetFullPath($@"\\.\pipe\{pipeName}"); + + var namedPipeWriterStream = new NamedPipeServerStream(pipeName, PipeDirection.Out); + var contentBytes = new byte[] { 1, 2, 3 }; + + using (var cts = new CancellationTokenSource()) + { + Task writingServerTask = WaitConnectionAndWritePipeStreamAsync(namedPipeWriterStream, contentBytes, cts.Token); + Task readTask = File.ReadAllBytesAsync(pipePath, cts.Token); + cts.CancelAfter(TimeSpan.FromSeconds(50)); + + await writingServerTask; + byte[] readBytes = await readTask; + Assert.Equal(contentBytes, readBytes); + } + + static async Task WaitConnectionAndWritePipeStreamAsync(NamedPipeServerStream namedPipeWriterStream, byte[] contentBytes, CancellationToken cancellationToken) + { + await using (namedPipeWriterStream) + { + await namedPipeWriterStream.WaitForConnectionAsync(cancellationToken); + await namedPipeWriterStream.WriteAsync(contentBytes, cancellationToken); + } + } + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task ReadAllBytesAsync_NonSeekableFileStream_InUnix() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + var contentBytes = new byte[] { 1, 2, 3 }; + + await Task.WhenAll( + Task.Run(async () => + { + byte[] readBytes = await File.ReadAllBytesAsync(fifoPath); + Assert.Equal(contentBytes, readBytes); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + foreach (byte content in contentBytes) + { + fs.WriteByte(content); + } + })); + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/File/SymbolicLinks.cs b/src/libraries/System.IO.FileSystem/tests/File/SymbolicLinks.cs index 4c41fa7bb16576..e879cb353af73d 100644 --- a/src/libraries/System.IO.FileSystem/tests/File/SymbolicLinks.cs +++ b/src/libraries/System.IO.FileSystem/tests/File/SymbolicLinks.cs @@ -45,6 +45,21 @@ protected override void AssertLinkExists(FileSystemInfo link) => public void ResolveLinkTarget_Throws_NotExists() => ResolveLinkTarget_Throws_NotExists_Internal(); + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public void UnsupportedLink_ReturnsNull() + { + string unsupportedLinkPath = GetAppExecLinkPath(); + if (unsupportedLinkPath is null) + { + return; + } + + Assert.Null(File.ResolveLinkTarget(unsupportedLinkPath, false)); + Assert.Null(File.ResolveLinkTarget(unsupportedLinkPath, true)); + } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void CreateSymbolicLink_PathToTarget_RelativeToLinkPath() { diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs index d3b9764951cbfd..1ca30617292ebd 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetTimes.cs @@ -10,10 +10,18 @@ namespace System.IO.Tests { public class FileInfo_GetSetTimes : InfoGetSetTimes { - protected override FileInfo GetExistingItem() + protected override bool CanBeReadOnly => true; + + protected override FileInfo GetExistingItem(bool readOnly = false) { string path = GetTestFilePath(); File.Create(path).Dispose(); + + if (readOnly) + { + File.SetAttributes(path, FileAttributes.ReadOnly); + } + return new FileInfo(path); } diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs index 2324a92eafce4f..36fd39a6000564 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/Open.cs @@ -74,15 +74,14 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA } } - public class FileInfo_Open_options_as : FileStream_ctor_options_as + public class FileInfo_Open_options : FileStream_ctor_options { protected override FileStream CreateFileStream(string path, FileMode mode) { return new FileInfo(path).Open( new FileStreamOptions { Mode = mode, - Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, - PreallocationSize = PreallocationSize + Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite }); } @@ -91,12 +90,23 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA return new FileInfo(path).Open( new FileStreamOptions { Mode = mode, - Access = access, - PreallocationSize = PreallocationSize + Access = access }); } protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) + { + return new FileInfo(path).Open( + new FileStreamOptions { + Mode = mode, + Access = access, + Share = share, + Options = options, + BufferSize = bufferSize + }); + } + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) { return new FileInfo(path).Open( new FileStreamOptions { @@ -105,7 +115,7 @@ protected override FileStream CreateFileStream(string path, FileMode mode, FileA Share = share, Options = options, BufferSize = bufferSize, - PreallocationSize = PreallocationSize + PreallocationSize = preallocationSize }); } } diff --git a/src/libraries/System.IO.FileSystem/tests/FileInfo/SymbolicLinks.cs b/src/libraries/System.IO.FileSystem/tests/FileInfo/SymbolicLinks.cs index fa334dd1ca376d..914edd06a1ba65 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileInfo/SymbolicLinks.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileInfo/SymbolicLinks.cs @@ -41,6 +41,24 @@ protected override void AssertLinkExists(FileSystemInfo link) => public void ResolveLinkTarget_Throws_NotExists() => ResolveLinkTarget_Throws_NotExists_Internal(); + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + public void UnsupportedLink_ReturnsNull() + { + string unsupportedLinkPath = GetAppExecLinkPath(); + if (unsupportedLinkPath is null) + { + return; + } + + var info = new FileInfo(unsupportedLinkPath); + + Assert.Null(info.LinkTarget); + Assert.Null(info.ResolveLinkTarget(false)); + Assert.Null(info.ResolveLinkTarget(true)); + } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void CreateSymbolicLink_PathToTarget_RelativeToLinkPath() { diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/DevicesPipesAndSockets.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/DevicesPipesAndSockets.cs new file mode 100644 index 00000000000000..ede852c7305b3f --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/DevicesPipesAndSockets.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.XUnitExtensions; +using Microsoft.Win32.SafeHandles; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.IO.Tests +{ + [PlatformSpecific(TestPlatforms.AnyUnix)] + public class DevicesPipesAndSockets : FileSystemTest + { + [Theory] + [MemberData(nameof(DevicePath_FileOptions_TestData))] + public void CharacterDevice_FileStream_Write(string devicePath, FileOptions fileOptions) + { + FileStreamOptions options = new() { Options = fileOptions, Access = FileAccess.Write, Share = FileShare.Write }; + using FileStream fs = new(devicePath, options); + fs.Write(Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_FileOptions_TestData))] + public async Task CharacterDevice_FileStream_WriteAsync(string devicePath, FileOptions fileOptions) + { + FileStreamOptions options = new() { Options = fileOptions, Access = FileAccess.Write, Share = FileShare.Write }; + using FileStream fs = new(devicePath, options); + await fs.WriteAsync(Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public void CharacterDevice_WriteAllBytes(string devicePath) + { + File.WriteAllBytes(devicePath, Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public async Task CharacterDevice_WriteAllBytesAsync(string devicePath) + { + await File.WriteAllBytesAsync(devicePath, Encoding.UTF8.GetBytes("foo")); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public void CharacterDevice_WriteAllText(string devicePath) + { + File.WriteAllText(devicePath, "foo"); + } + + [Theory] + [MemberData(nameof(DevicePath_TestData))] + public async Task CharacterDevice_WriteAllTextAsync(string devicePath) + { + await File.WriteAllTextAsync(devicePath, "foo"); + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task NamedPipe_ReadWrite() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + await Task.WhenAll( + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + ReadByte(fs, 42); + }), + Task.Run(() => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + WriteByte(fs, 42); + })); + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public async Task NamedPipe_ReadWrite_Async() + { + string fifoPath = GetTestFilePath(); + Assert.Equal(0, mkfifo(fifoPath, 438 /* 666 in octal */ )); + + await Task.WhenAll( + Task.Run(async () => { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + await ReadByteAsync(fs, 42); + }), + Task.Run(async () => + { + using var fs = new FileStream(fifoPath, FileMode.Open, FileAccess.Write, FileShare.Read); + await WriteByteAsync(fs, 42); + })); + } + + private const int AF_UNIX = 1; + private const int SOCK_STREAM = 1; + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public unsafe void SocketPair_ReadWrite() + { + int* ptr = stackalloc int[2]; + Assert.Equal(0, socketpair(AF_UNIX, SOCK_STREAM, 0, ptr)); + + using var readFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[0], ownsHandle: true), FileAccess.Read); + using var writeFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[1], ownsHandle: true), FileAccess.Write); + + Task.WhenAll( + Task.Run(() => ReadByte(readFileStream, 42)), + Task.Run(() => WriteByte(writeFileStream, 42))).GetAwaiter().GetResult(); + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix & ~TestPlatforms.Browser)] + public void SocketPair_ReadWrite_Async() + { + unsafe + { + int* ptr = stackalloc int[2]; + Assert.Equal(0, socketpair(AF_UNIX, SOCK_STREAM, 0, ptr)); + + using var readFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[0], ownsHandle: true), FileAccess.Read); + using var writeFileStream = new FileStream(new SafeFileHandle((IntPtr)ptr[1], ownsHandle: true), FileAccess.Write); + + Task.WhenAll( + ReadByteAsync(readFileStream, 42), + WriteByteAsync(writeFileStream, 42)).GetAwaiter().GetResult(); + } + } + + private static void ReadByte(FileStream fs, byte expected) + { + var buffer = new byte[1]; + Assert.Equal(1, fs.Read(buffer)); + Assert.Equal(expected, buffer[0]); + } + + private static void WriteByte(FileStream fs, byte value) + { + fs.Write(new byte[] { value }); + fs.Flush(); + } + + private static async Task ReadByteAsync(FileStream fs, byte expected) + { + var buffer = new byte[1]; + Assert.Equal(1, await fs.ReadAsync(buffer)); + Assert.Equal(expected, buffer[0]); + } + + private static async Task WriteByteAsync(FileStream fs, byte value) + { + await fs.WriteAsync(new byte[] { value }); + await fs.FlushAsync(); + } + + private static Lazy> AvailableDevicePaths = new Lazy>(() => + { + List paths = new(); + FileStreamOptions options = new() { Access = FileAccess.Write, Share = FileShare.Write }; + + foreach (string devicePath in new[] { "/dev/tty", "/dev/console", "/dev/null", "/dev/zero" }) + { + if (!File.Exists(devicePath)) + { + continue; + } + + try + { + File.Open(devicePath, options).Dispose(); + } + catch (Exception ex) + { + if (ex is IOException || ex is UnauthorizedAccessException) + { + continue; + } + + throw; + } + + paths.Add(devicePath); + } + + return paths; + }); + + public static IEnumerable DevicePath_FileOptions_TestData() + { + foreach (string devicePath in AvailableDevicePaths.Value) + { + foreach (FileOptions options in new[] { FileOptions.None, FileOptions.Asynchronous }) + { + yield return new object[] { devicePath, options}; + } + } + } + + public static IEnumerable DevicePath_TestData() + { + foreach (string devicePath in AvailableDevicePaths.Value) + { + yield return new object[] { devicePath }; + } + } + + [DllImport("libc")] + private static unsafe extern int socketpair(int domain, int type, int protocol, int* ptr); + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs index 0740eed02f0d85..0c49a52abbcf1e 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/SafeFileHandle.cs @@ -78,6 +78,18 @@ public async Task ThrowWhenHandlePositionIsChanged_async() await ThrowWhenHandlePositionIsChanged(useAsync: true); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsFileLockingEnabled))] + public void DeleteOnClose_FailedShareDoesNotDeleteFile() + { + string fileName = GetTestFilePath(); + + using SafeFileHandle handle = File.OpenHandle(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None); + + Assert.Throws(() => File.OpenHandle(fileName, FileMode.Open, FileAccess.Write, FileShare.None, FileOptions.DeleteOnClose)); + + Assert.True(File.Exists(fileName)); + } + private async Task ThrowWhenHandlePositionIsChanged(bool useAsync) { string fileName = GetTestFilePath(); diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Browser.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Browser.cs new file mode 100644 index 00000000000000..45326d885c455d --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Browser.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO.Tests +{ + public partial class FileStream_ctor_options + { + private static long GetAllocatedSize(FileStream fileStream) + { + return 0; + } + + private static bool SupportsPreallocation => false; + + private static bool IsGetAllocatedSizeImplemented => false; + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Unix.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Unix.cs new file mode 100644 index 00000000000000..c33c56a1fa5706 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Unix.cs @@ -0,0 +1,36 @@ +// 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.Runtime.InteropServices; + +namespace System.IO.Tests +{ + public partial class FileStream_ctor_options + { + private static long GetAllocatedSize(FileStream fileStream) + { + bool isOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + // Call 'stat' to get the number of blocks, and size of blocks. + using var px = Process.Start(new ProcessStartInfo + { + FileName = "stat", + ArgumentList = { isOSX ? "-f" : "-c", + isOSX ? "%b %k" : "%b %B", + fileStream.Name }, + RedirectStandardOutput = true + }); + string stdout = px.StandardOutput.ReadToEnd(); + + string[] parts = stdout.Split(' '); + return long.Parse(parts[0]) * long.Parse(parts[1]); + } + + private static bool SupportsPreallocation => + RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || + RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + + // Mobile platforms don't support Process.Start. + private static bool IsGetAllocatedSizeImplemented => !PlatformDetection.IsMobile; + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Windows.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Windows.cs similarity index 71% rename from src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Windows.cs rename to src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Windows.cs index bde8cd5e4692a3..2dca6baf22bd07 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Windows.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.Windows.cs @@ -1,21 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO.Pipes; using System.Runtime.InteropServices; using System.Text; +using System.Threading.Tasks; using Xunit; namespace System.IO.Tests { - public partial class FileStream_ctor_options_as : FileStream_ctor_options_as_base + public partial class FileStream_ctor_options { - protected override long PreallocationSize => 10; - - protected override long InitialLength => 0; // Windows modifies AllocationSize, but not EndOfFile (file length) - - private long GetExpectedFileLength(long preallocationSize) => 0; // Windows modifies AllocationSize, but not EndOfFile (file length) - - private unsafe long GetActualPreallocationSize(FileStream fileStream) + private unsafe long GetAllocatedSize(FileStream fileStream) { Interop.Kernel32.FILE_STANDARD_INFO info; @@ -24,6 +20,10 @@ private unsafe long GetActualPreallocationSize(FileStream fileStream) return info.AllocationSize; } + private static bool SupportsPreallocation => true; + + private static bool IsGetAllocatedSizeImplemented => true; + [Theory] [InlineData(@"\\?\")] [InlineData(@"\??\")] @@ -32,26 +32,26 @@ public void ExtendedPathsAreSupported(string prefix) { const long preallocationSize = 123; - string filePath = prefix + Path.GetFullPath(GetPathToNonExistingFile()); + string filePath = prefix + Path.GetFullPath(GetTestFilePath()); - using (var fs = new FileStream(filePath, GetOptions(FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.None, preallocationSize))) + using (var fs = CreateFileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 4096, FileOptions.None, preallocationSize)) { - Assert.True(GetActualPreallocationSize(fs) >= preallocationSize, $"Provided {preallocationSize}, actual: {GetActualPreallocationSize(fs)}"); + Assert.Equal(0, fs.Length); + Assert.True(GetAllocatedSize(fs) >= preallocationSize); } } [ConditionalTheory(nameof(IsFat32))] [InlineData(FileMode.Create)] [InlineData(FileMode.CreateNew)] - [InlineData(FileMode.OpenOrCreate)] public void WhenFileIsTooLargeTheErrorMessageContainsAllDetails(FileMode mode) { const long tooMuch = uint.MaxValue + 1L; // more than FAT32 max size - string filePath = GetPathToNonExistingFile(); + string filePath = GetTestFilePath(); Assert.StartsWith(Path.GetTempPath(), filePath); // this is what IsFat32 method relies on - IOException ex = Assert.Throws(() => new FileStream(filePath, GetOptions(mode, FileAccess.Write, FileShare.None, FileOptions.None, tooMuch))); + IOException ex = Assert.Throws(() => CreateFileStream(filePath, mode, FileAccess.Write, FileShare.None, bufferSize: 4096, FileOptions.None, tooMuch)); Assert.Contains(filePath, ex.Message); Assert.Contains(tooMuch.ToString(), ex.Message); diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.cs new file mode 100644 index 00000000000000..5209d5ef76d427 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options.cs @@ -0,0 +1,172 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Security.Cryptography; +using Xunit; + +namespace System.IO.Tests +{ + // Don't run in parallel as the WhenDiskIsFullTheErrorMessageContainsAllDetails test + // consumes entire available free space on the disk (only on Linux, this is how fallocate works) + // and if we try to run other disk-writing test in the meantime we are going to get "No space left on device" exception. + [Collection("NoParallelTests")] + public partial class FileStream_ctor_options : FileStream_ctor_str_fm_fa_fs_buffer_fo + { + protected override string GetExpectedParamName(string paramName) => "value"; + + protected override FileStream CreateFileStream(string path, FileMode mode) + => new FileStream(path, + new FileStreamOptions + { + Mode = mode, + Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite + }); + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) + => new FileStream(path, + new FileStreamOptions + { + Mode = mode, + Access = access + }); + + protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) + => new FileStream(path, + new FileStreamOptions + { + Mode = mode, + Access = access, + Share = share, + BufferSize = bufferSize, + Options = options + }); + + protected virtual FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) + => new FileStream(path, + new FileStreamOptions + { + Mode = mode, + Access = access, + Share = share, + BufferSize = bufferSize, + Options = options, + PreallocationSize = preallocationSize + }); + + [Fact] + public virtual void NegativePreallocationSizeThrows() + { + string filePath = GetTestFilePath(); + ArgumentOutOfRangeException ex = Assert.Throws( + () => CreateFileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: -1)); + } + + [Theory] + [InlineData(FileMode.Append)] + [InlineData(FileMode.Open)] + [InlineData(FileMode.OpenOrCreate)] + [InlineData(FileMode.Truncate)] + public void PreallocationSizeThrowsForFileModesThatOpenExistingFiles(FileMode mode) + { + Assert.Throws( + () => CreateFileStream(GetTestFilePath(), mode, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 20)); + } + + [Theory] + [InlineData(FileMode.Create)] + [InlineData(FileMode.CreateNew)] + public void PreallocationSizeThrowsForReadOnlyAccess(FileMode mode) + { + Assert.Throws( + () => CreateFileStream(GetTestFilePath(), mode, FileAccess.Read, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 20)); + } + + [Theory] + [InlineData(FileMode.Create, false)] + [InlineData(FileMode.Create, true)] + [InlineData(FileMode.CreateNew, false)] + [InlineData(FileMode.Append, false)] + [InlineData(FileMode.Append, true)] + [InlineData(FileMode.Open, true)] + [InlineData(FileMode.OpenOrCreate, true)] + [InlineData(FileMode.OpenOrCreate, false)] + [InlineData(FileMode.Truncate, true)] + public void ZeroPreallocationSizeDoesNotAllocate(FileMode mode, bool createFile) + { + string filename = GetTestFilePath(); + + if (createFile) + { + File.WriteAllText(filename, ""); + } + + using (FileStream fs = CreateFileStream(filename, mode, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 0)) + { + Assert.Equal(0, fs.Length); + if (IsGetAllocatedSizeImplemented) + { + Assert.Equal(0, GetAllocatedSize(fs)); + } + Assert.Equal(0, fs.Position); + } + } + + [Theory] + [InlineData(FileAccess.Write, FileMode.Create)] + [InlineData(FileAccess.Write, FileMode.CreateNew)] + [InlineData(FileAccess.ReadWrite, FileMode.Create)] + [InlineData(FileAccess.ReadWrite, FileMode.CreateNew)] + public void PreallocationSize(FileAccess access, FileMode mode) + { + const long preallocationSize = 123; + + using (var fs = CreateFileStream(GetTestFilePath(), mode, access, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize)) + { + Assert.Equal(0, fs.Length); + if (IsGetAllocatedSizeImplemented) + { + if (SupportsPreallocation) + { + Assert.True(GetAllocatedSize(fs) >= preallocationSize); + } + else + { + Assert.Equal(0, GetAllocatedSize(fs)); + } + } + Assert.Equal(0, fs.Position); + } + } + + [OuterLoop("Might allocate 1 TB file if there is enough space on the disk")] + // macOS fcntl doc does not mention ENOSPC error: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html + // But depending on the OS version, it might actually return it. + // Since we don't want to have unstable tests, it's better to not run it on macOS at all. + [PlatformSpecific(TestPlatforms.Windows | TestPlatforms.Linux)] + [Theory] + [InlineData(FileMode.Create)] + [InlineData(FileMode.CreateNew)] + public void WhenDiskIsFullTheErrorMessageContainsAllDetails(FileMode mode) + { + const long TooMuch = 1024L * 1024L * 1024L * 1024L; // 1 TB + + string filePath = GetTestFilePath(); + + IOException ex = Assert.Throws(() => CreateFileStream(filePath, mode, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, TooMuch)); + Assert.Contains(filePath, ex.Message); + Assert.Contains(TooMuch.ToString(), ex.Message); + + // ensure it was NOT created + bool exists = File.Exists(filePath); + if (exists) + { + File.Delete(filePath); + } + Assert.False(exists); + } + } + + [CollectionDefinition("NoParallelTests", DisableParallelization = true)] + public partial class NoParallelTests { } +} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Browser.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Browser.cs deleted file mode 100644 index 3475c8999ca6f9..00000000000000 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Browser.cs +++ /dev/null @@ -1,16 +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.IO.Tests -{ - public partial class FileStream_ctor_options_as : FileStream_ctor_options_as_base - { - protected override long PreallocationSize => 10; - - protected override long InitialLength => 10; - - private long GetExpectedFileLength(long preallocationSize) => preallocationSize; - - private long GetActualPreallocationSize(FileStream fileStream) => fileStream.Length; - } -} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Unix.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Unix.cs deleted file mode 100644 index 12e8f1641bac00..00000000000000 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.Unix.cs +++ /dev/null @@ -1,21 +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.IO.Tests -{ - public partial class FileStream_ctor_options_as : FileStream_ctor_options_as_base - { - protected override long PreallocationSize => 10; - - protected override long InitialLength => 10; - - private long GetExpectedFileLength(long preallocationSize) => preallocationSize; - - private long GetActualPreallocationSize(FileStream fileStream) - { - // On Unix posix_fallocate modifies file length and we are using fstat to get it for verificaiton - Interop.Sys.FStat(fileStream.SafeFileHandle, out Interop.Sys.FileStatus fileStatus); - return fileStatus.Size; - } - } -} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.cs deleted file mode 100644 index f36e55ea16d2de..00000000000000 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_options_as.cs +++ /dev/null @@ -1,212 +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 Xunit; - -namespace System.IO.Tests -{ - public abstract class FileStream_ctor_options_as_base : FileStream_ctor_str_fm_fa_fs_buffer_fo - { - protected abstract long PreallocationSize { get; } - - protected override string GetExpectedParamName(string paramName) => "value"; - - protected override FileStream CreateFileStream(string path, FileMode mode) - => new FileStream(path, - new FileStreamOptions - { - Mode = mode, - Access = mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite, - PreallocationSize = PreallocationSize - }); - - protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access) - => new FileStream(path, - new FileStreamOptions - { - Mode = mode, - Access = access, - PreallocationSize = PreallocationSize - }); - - protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options) - => new FileStream(path, - new FileStreamOptions - { - Mode = mode, - Access = access, - Share = share, - BufferSize = bufferSize, - Options = options, - PreallocationSize = PreallocationSize - }); - - protected FileStreamOptions GetOptions(FileMode mode, FileAccess access, FileShare share, FileOptions options, long preAllocationSize) - => new FileStreamOptions - { - Mode = mode, - Access = access, - Share = share, - Options = options, - PreallocationSize = preAllocationSize - }; - } - - public class FileStream_ctor_options_as_zero : FileStream_ctor_options_as_base - { - protected override long PreallocationSize => 0; // specifying 0 should have no effect - - protected override long InitialLength => 0; - } - - [CollectionDefinition("NoParallelTests", DisableParallelization = true)] - public partial class NoParallelTests { } - - // Don't run in parallel as the WhenDiskIsFullTheErrorMessageContainsAllDetails test - // consumes entire available free space on the disk (only on Linux, this is how posix_fallocate works) - // and if we try to run other disk-writing test in the meantime we are going to get "No space left on device" exception. - [Collection("NoParallelTests")] - public partial class FileStream_ctor_options_as : FileStream_ctor_options_as_base - { - [Fact] - public virtual void NegativePreallocationSizeThrows() - { - string filePath = GetPathToNonExistingFile(); - ArgumentOutOfRangeException ex = Assert.Throws( - () => new FileStream(filePath, GetOptions(FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.None, -1))); - } - - [Theory] - [InlineData(FileMode.Create, 0L)] - [InlineData(FileMode.CreateNew, 0L)] - [InlineData(FileMode.OpenOrCreate, 0L)] - public void WhenFileIsCreatedWithoutPreallocationSizeSpecifiedThePreallocationSizeIsNotSet(FileMode mode, long preallocationSize) - { - using (var fs = new FileStream(GetPathToNonExistingFile(), GetOptions(mode, FileAccess.Write, FileShare.None, FileOptions.None, preallocationSize))) - { - Assert.Equal(0, GetActualPreallocationSize(fs)); - Assert.Equal(0, fs.Length); - Assert.Equal(0, fs.Position); - } - } - - [Theory] - [InlineData(FileMode.Open, 0L)] - [InlineData(FileMode.Open, 1L)] - [InlineData(FileMode.OpenOrCreate, 0L)] - [InlineData(FileMode.OpenOrCreate, 1L)] - [InlineData(FileMode.Append, 0L)] - [InlineData(FileMode.Append, 1L)] - public void WhenExistingFileIsBeingOpenedWithPreallocationSizeSpecifiedThePreallocationSizeIsNotChanged(FileMode mode, long preallocationSize) - { - const int initialSize = 1; - string filePath = GetPathToNonExistingFile(); - File.WriteAllBytes(filePath, new byte[initialSize]); - long initialPreallocationSize; - - using (var fs = new FileStream(filePath, GetOptions(mode, FileAccess.Write, FileShare.None, FileOptions.None, 0))) // preallocationSize NOT provided - { - initialPreallocationSize = GetActualPreallocationSize(fs); // just read it to ensure it's not being changed - } - - using (var fs = new FileStream(filePath, GetOptions(mode, FileAccess.Write, FileShare.None, FileOptions.None, preallocationSize))) - { - Assert.Equal(initialPreallocationSize, GetActualPreallocationSize(fs)); // it has NOT been changed - Assert.Equal(initialSize, fs.Length); - Assert.Equal(mode == FileMode.Append ? initialSize : 0, fs.Position); - } - } - - [Theory] - [InlineData(FileMode.Create)] - [InlineData(FileMode.CreateNew)] - [InlineData(FileMode.OpenOrCreate)] - public void WhenFileIsCreatedWithPreallocationSizeSpecifiedThePreallocationSizeIsSet(FileMode mode) - { - const long preallocationSize = 123; - - using (var fs = new FileStream(GetPathToNonExistingFile(), GetOptions(mode, FileAccess.Write, FileShare.None, FileOptions.None, preallocationSize))) - { - // OS might allocate MORE than we have requested - Assert.True(GetActualPreallocationSize(fs) >= preallocationSize, $"Provided {preallocationSize}, actual: {GetActualPreallocationSize(fs)}"); - Assert.Equal(GetExpectedFileLength(preallocationSize), fs.Length); - Assert.Equal(0, fs.Position); - } - } - - [OuterLoop("Might allocate 1 TB file if there is enough space on the disk")] - // macOS fcntl doc does not mention ENOSPC error: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fcntl.2.html - // But depending on the OS version, it might actually return it. - // Since we don't want to have unstable tests, it's better to not run it on macOS at all. - [PlatformSpecific(TestPlatforms.Windows | TestPlatforms.Linux)] - [Theory] - [InlineData(FileMode.Create)] - [InlineData(FileMode.CreateNew)] - [InlineData(FileMode.OpenOrCreate)] - public void WhenDiskIsFullTheErrorMessageContainsAllDetails(FileMode mode) - { - const long tooMuch = 1024L * 1024L * 1024L * 1024L; // 1 TB - - string filePath = GetPathToNonExistingFile(); - - IOException ex = Assert.Throws(() => new FileStream(filePath, GetOptions(mode, FileAccess.Write, FileShare.None, FileOptions.None, tooMuch))); - Assert.Contains(filePath, ex.Message); - Assert.Contains(tooMuch.ToString(), ex.Message); - - // ensure it was NOT created (provided OOTB by Windows, emulated on Unix) - bool exists = File.Exists(filePath); - if (exists) - { - File.Delete(filePath); - } - Assert.False(exists); - } - - [Fact] - public void WhenFileIsTruncatedWithoutPreallocationSizeSpecifiedThePreallocationSizeIsNotSet() - { - const int initialSize = 10_000; - - string filePath = GetPathToNonExistingFile(); - File.WriteAllBytes(filePath, new byte[initialSize]); - - using (var fs = new FileStream(filePath, GetOptions(FileMode.Truncate, FileAccess.Write, FileShare.None, FileOptions.None, 0))) - { - Assert.Equal(0, GetActualPreallocationSize(fs)); - Assert.Equal(0, fs.Length); - Assert.Equal(0, fs.Position); - } - } - - [Fact] - public void WhenFileIsTruncatedWithPreallocationSizeSpecifiedThePreallocationSizeIsSet() - { - const int initialSize = 10_000; // this must be more than 4kb which seems to be minimum allocation size on Windows - const long preallocationSize = 100; - - string filePath = GetPathToNonExistingFile(); - File.WriteAllBytes(filePath, new byte[initialSize]); - - using (var fs = new FileStream(filePath, GetOptions(FileMode.Truncate, FileAccess.Write, FileShare.None, FileOptions.None, preallocationSize))) - { - Assert.True(GetActualPreallocationSize(fs) >= preallocationSize, $"Provided {preallocationSize}, actual: {GetActualPreallocationSize(fs)}"); - // less than initial file size (file got truncated) - Assert.True(GetActualPreallocationSize(fs) < initialSize, $"initialSize {initialSize}, actual: {GetActualPreallocationSize(fs)}"); - Assert.Equal(GetExpectedFileLength(preallocationSize), fs.Length); - Assert.Equal(0, fs.Position); - } - } - - private string GetPathToNonExistingFile() - { - string filePath = GetTestFilePath(); - - if (File.Exists(filePath)) - { - File.Delete(filePath); - } - - return filePath; - } - } -} diff --git a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_str_fm.cs b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_str_fm.cs index 47e3b492373161..cd3b18da034228 100644 --- a/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_str_fm.cs +++ b/src/libraries/System.IO.FileSystem/tests/FileStream/ctor_str_fm.cs @@ -13,8 +13,6 @@ protected virtual FileStream CreateFileStream(string path, FileMode mode) return new FileStream(path, mode); } - protected virtual long InitialLength => 0; - protected virtual string GetExpectedParamName(string paramName) => paramName; [Fact] @@ -97,7 +95,7 @@ public void FileModeCreateExisting(string streamSpecifier) using (FileStream fs = CreateFileStream(fileName, FileMode.Create)) { // Ensure that the file was re-created - Assert.Equal(InitialLength, fs.Length); + Assert.Equal(0, fs.Length); Assert.Equal(0L, fs.Position); Assert.True(fs.CanRead); Assert.True(fs.CanWrite); @@ -148,7 +146,7 @@ public void FileModeOpenExisting(string streamSpecifier) using (FileStream fs = CreateFileStream(fileName, FileMode.Open)) { // Ensure that the file was re-opened - Assert.Equal(Math.Max(1L, InitialLength), fs.Length); + Assert.Equal(1, fs.Length); Assert.Equal(0L, fs.Position); Assert.True(fs.CanRead); Assert.True(fs.CanWrite); @@ -177,7 +175,7 @@ public void FileModeOpenOrCreateExisting(string streamSpecifier) using (FileStream fs = CreateFileStream(fileName, FileMode.OpenOrCreate)) { // Ensure that the file was re-opened - Assert.Equal(Math.Max(1L, InitialLength), fs.Length); + Assert.Equal(1, fs.Length); Assert.Equal(0L, fs.Position); Assert.True(fs.CanRead); Assert.True(fs.CanWrite); @@ -204,7 +202,7 @@ public void FileModeTruncateExisting(string streamSpecifier) using (FileStream fs = CreateFileStream(fileName, FileMode.Truncate)) { // Ensure that the file was re-opened and truncated - Assert.Equal(InitialLength, fs.Length); + Assert.Equal(0, fs.Length); Assert.Equal(0L, fs.Position); Assert.True(fs.CanRead); Assert.True(fs.CanWrite); @@ -246,7 +244,7 @@ public virtual void FileModeAppendExisting(string streamSpecifier) using (FileStream fs = CreateFileStream(fileName, FileMode.Append)) { // Ensure that the file was re-opened and position set to end - Assert.Equal(Math.Max(1L, InitialLength), fs.Length); + Assert.Equal(1, fs.Length); long position = fs.Position; Assert.Equal(fs.Length, position); diff --git a/src/libraries/System.IO.FileSystem/tests/Junctions.Windows.cs b/src/libraries/System.IO.FileSystem/tests/Junctions.Windows.cs new file mode 100644 index 00000000000000..c280008148977a --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/Junctions.Windows.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.IO.Tests +{ + [PlatformSpecific(TestPlatforms.Windows)] + public class Junctions : BaseSymbolicLinks + { + private DirectoryInfo CreateJunction(string junctionPath, string targetPath) + { + Assert.True(MountHelper.CreateJunction(junctionPath, targetPath)); + DirectoryInfo junctionInfo = new(junctionPath); + return junctionInfo; + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Junction_ResolveLinkTarget(bool returnFinalTarget) + { + string junctionPath = GetRandomLinkPath(); + string targetPath = GetRandomDirPath(); + + Directory.CreateDirectory(targetPath); + DirectoryInfo junctionInfo = CreateJunction(junctionPath, targetPath); + + FileSystemInfo? targetFromDirectoryInfo = junctionInfo.ResolveLinkTarget(returnFinalTarget); + FileSystemInfo? targetFromDirectory = Directory.ResolveLinkTarget(junctionPath, returnFinalTarget); + + Assert.True(targetFromDirectoryInfo is DirectoryInfo); + Assert.True(targetFromDirectory is DirectoryInfo); + + Assert.Equal(targetPath, junctionInfo.LinkTarget); + + Assert.Equal(targetPath, targetFromDirectoryInfo.FullName); + Assert.Equal(targetPath, targetFromDirectory.FullName); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void Junction_ResolveLinkTarget_WithIndirection(bool returnFinalTarget) + { + string firstJunctionPath = GetRandomLinkPath(); + string middleJunctionPath = GetRandomLinkPath(); + string targetPath = GetRandomDirPath(); + + Directory.CreateDirectory(targetPath); + CreateJunction(middleJunctionPath, targetPath); + DirectoryInfo firstJunctionInfo = CreateJunction(firstJunctionPath, middleJunctionPath); + + string expectedTargetPath = returnFinalTarget ? targetPath : middleJunctionPath; + + FileSystemInfo? targetFromDirectoryInfo = firstJunctionInfo.ResolveLinkTarget(returnFinalTarget); + FileSystemInfo? targetFromDirectory = Directory.ResolveLinkTarget(firstJunctionPath, returnFinalTarget); + + Assert.True(targetFromDirectoryInfo is DirectoryInfo); + Assert.True(targetFromDirectory is DirectoryInfo); + + // Always the immediate target + Assert.Equal(middleJunctionPath, firstJunctionInfo.LinkTarget); + + Assert.Equal(expectedTargetPath, targetFromDirectoryInfo.FullName); + Assert.Equal(expectedTargetPath, targetFromDirectory.FullName); + } + + [Theory] + [MemberData(nameof(Junction_ResolveLinkTarget_PathToTarget_Data))] + public void Junction_ResolveLinkTarget_Succeeds(string pathToTarget, bool returnFinalTarget) + { + string linkPath = GetRandomLinkPath(); + FileSystemInfo linkInfo = CreateJunction(linkPath, pathToTarget); + + // Junctions are always created with absolute targets, even if a relative path is passed. + string expectedTarget = Path.GetFullPath(pathToTarget); + + Assert.True(linkInfo.Exists); + Assert.IsType(linkInfo); + Assert.True(linkInfo.Attributes.HasFlag(FileAttributes.Directory)); + Assert.Equal(expectedTarget, linkInfo.LinkTarget); + + FileSystemInfo? targetFromDirectoryInfo = linkInfo.ResolveLinkTarget(returnFinalTarget); + FileSystemInfo? targetFromDirectory = Directory.ResolveLinkTarget(linkPath, returnFinalTarget); + + Assert.NotNull(targetFromDirectoryInfo); + Assert.NotNull(targetFromDirectory); + + Assert.False(targetFromDirectoryInfo.Exists); + Assert.False(targetFromDirectory.Exists); + + + Assert.Equal(expectedTarget, targetFromDirectoryInfo.FullName); + Assert.Equal(expectedTarget, targetFromDirectory.FullName); + } + + [Theory] + [MemberData(nameof(Junction_LinkTarget_PathToTarget_Data))] + public void Junction_LinkTarget_Succeeds(string pathToTarget) + { + FileSystemInfo linkInfo = CreateJunction(GetRandomLinkPath(), pathToTarget); + Assert.True(linkInfo.Exists); + Assert.Equal(Path.GetFullPath(pathToTarget), linkInfo.LinkTarget); + } + } +} diff --git a/src/libraries/System.IO.FileSystem/tests/LargeFileTests.cs b/src/libraries/System.IO.FileSystem/tests/LargeFileTests.cs new file mode 100644 index 00000000000000..c8158f8b97784a --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/LargeFileTests.cs @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO.Tests; +using System.Threading.Tasks; +using Xunit; + +namespace System.IO.FileSystem.Tests +{ + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/45954", TestPlatforms.Browser)] + [Collection(nameof(NoParallelTests))] // don't create multiple large files at the same time + public class LargeFileTests : FileSystemTest + { + [Fact] + public async Task ReadAllBytesOverLimit() + { + using FileStream fs = new (GetTestFilePath(), FileMode.Create, FileAccess.Write, FileShare.Read, 4096, FileOptions.DeleteOnClose); + + foreach (long lengthOverLimit in new long[] { int.MaxValue + 1L }) + { + fs.SetLength(lengthOverLimit); + + Assert.Throws(() => File.ReadAllBytes(fs.Name)); + await Assert.ThrowsAsync(async () => await File.ReadAllBytesAsync(fs.Name)); + } + } + + [Fact] + public void NoInt32OverflowInTheBufferingLogic() + { + const long position1 = 10; + const long position2 = (1L << 32) + position1; + + string filePath = GetTestFilePath(); + byte[] data1 = new byte[] { 1, 2, 3, 4, 5 }; + byte[] data2 = new byte[] { 6, 7, 8, 9, 10 }; + byte[] buffer = new byte[5]; + + using (FileStream stream = File.Create(filePath)) + { + stream.Seek(position1, SeekOrigin.Begin); + stream.Write(data1); + + stream.Seek(position2, SeekOrigin.Begin); + stream.Write(data2); + } + + using (FileStream stream = new (filePath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose)) + { + stream.Seek(position1, SeekOrigin.Begin); + Assert.Equal(buffer.Length, stream.Read(buffer)); + Assert.Equal(data1, buffer); + + stream.Seek(position2, SeekOrigin.Begin); + Assert.Equal(buffer.Length, stream.Read(buffer)); + Assert.Equal(data2, buffer); + } + } + } + + [CollectionDefinition(nameof(NoParallelTests), DisableParallelization = true)] + public partial class NoParallelTests { } +} diff --git a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj index 745ff60368b2ef..385c3afb569c49 100644 --- a/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/Net5CompatTests/System.IO.FileSystem.Net5Compat.Tests.csproj @@ -1,4 +1,4 @@ - + true true @@ -14,7 +14,6 @@ - @@ -33,6 +32,7 @@ + diff --git a/src/libraries/System.IO.FileSystem/tests/PortedCommon/ReparsePointUtilities.cs b/src/libraries/System.IO.FileSystem/tests/PortedCommon/ReparsePointUtilities.cs index 5423bda6814b3b..8c7f3608d35ce2 100644 --- a/src/libraries/System.IO.FileSystem/tests/PortedCommon/ReparsePointUtilities.cs +++ b/src/libraries/System.IO.FileSystem/tests/PortedCommon/ReparsePointUtilities.cs @@ -10,14 +10,14 @@ #define DEBUG using System; -using System.IO; -using System.Text; -using System.Diagnostics; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; using System.Runtime.InteropServices; -using System.ComponentModel; -using System.Threading; +using System.Text; using System.Threading.Tasks; + public static class MountHelper { [DllImport("kernel32.dll", EntryPoint = "GetVolumeNameForVolumeMountPointW", CharSet = CharSet.Unicode, BestFitMapping = false, SetLastError = true)] @@ -28,9 +28,7 @@ public static class MountHelper [DllImport("kernel32.dll", EntryPoint = "DeleteVolumeMountPointW", CharSet = CharSet.Unicode, BestFitMapping = false, SetLastError = true)] private static extern bool DeleteVolumeMountPoint(string mountPoint); - /// Creates a symbolic link using command line tools - /// The existing file - /// + /// Creates a symbolic link using command line tools. public static bool CreateSymbolicLink(string linkPath, string targetPath, bool isDirectory) { Process symLinkProcess = new Process(); @@ -48,20 +46,78 @@ public static bool CreateSymbolicLink(string linkPath, string targetPath, bool i symLinkProcess.StartInfo.RedirectStandardOutput = true; symLinkProcess.Start(); - if (symLinkProcess != null) + symLinkProcess.WaitForExit(); + return symLinkProcess.ExitCode == 0; + } + + /// On Windows, creates a junction using command line tools. + public static bool CreateJunction(string junctionPath, string targetPath) + { + if (!OperatingSystem.IsWindows()) { - symLinkProcess.WaitForExit(); - return (0 == symLinkProcess.ExitCode); + throw new PlatformNotSupportedException(); } - else + + return RunProcess(CreateProcessStartInfo("cmd", "/c", "mklink", "/J", junctionPath, targetPath)); + } + + /// + /// On Windows, mounts a folder to an assigned virtual drive letter using the subst command. + /// subst is not available in Windows Nano. + /// + public static char CreateVirtualDrive(string targetDir) + { + if (!OperatingSystem.IsWindows()) + { + throw new PlatformNotSupportedException(); + } + + char driveLetter = GetNextAvailableDriveLetter(); + bool success = RunProcess(CreateProcessStartInfo("cmd", "/c", SubstPath, $"{driveLetter}:", targetDir)); + if (!success || !DriveInfo.GetDrives().Any(x => x.Name[0] == driveLetter)) + { + throw new InvalidOperationException($"Could not create virtual drive {driveLetter}: with subst"); + } + return driveLetter; + + // Finds the next unused drive letter and returns it. + char GetNextAvailableDriveLetter() { - return false; + List existingDrives = DriveInfo.GetDrives().Select(x => x.Name[0]).ToList(); + + // A,B are reserved, C is usually reserved + IEnumerable range = Enumerable.Range('D', 'Z' - 'D'); + IEnumerable castRange = range.Select(x => Convert.ToChar(x)); + IEnumerable allDrivesLetters = castRange.Except(existingDrives); + + if (!allDrivesLetters.Any()) + { + throw new ArgumentOutOfRangeException("No drive letters available"); + } + + return allDrivesLetters.First(); } } - public static void Mount(string volumeName, string mountPoint) + /// + /// On Windows, unassigns the specified virtual drive letter from its mounted folder. + /// + public static void DeleteVirtualDrive(char driveLetter) { + if (!OperatingSystem.IsWindows()) + { + throw new PlatformNotSupportedException(); + } + bool success = RunProcess(CreateProcessStartInfo("cmd", "/c", SubstPath, "/d", $"{driveLetter}:")); + if (!success || DriveInfo.GetDrives().Any(x => x.Name[0] == driveLetter)) + { + throw new InvalidOperationException($"Could not delete virtual drive {driveLetter}: with subst"); + } + } + + public static void Mount(string volumeName, string mountPoint) + { if (volumeName[volumeName.Length - 1] != Path.DirectorySeparatorChar) volumeName += Path.DirectorySeparatorChar; if (mountPoint[mountPoint.Length - 1] != Path.DirectorySeparatorChar) @@ -93,8 +149,47 @@ public static void Unmount(string mountPoint) throw new Exception(string.Format("Win32 error: {0}", Marshal.GetLastPInvokeError())); } + private static ProcessStartInfo CreateProcessStartInfo(string fileName, params string[] arguments) + { + var info = new ProcessStartInfo + { + FileName = fileName, + UseShellExecute = false, + RedirectStandardOutput = true + }; + + foreach (var argument in arguments) + { + info.ArgumentList.Add(argument); + } + + return info; + } + + private static bool RunProcess(ProcessStartInfo startInfo) + { + var process = Process.Start(startInfo); + process.WaitForExit(); + return process.ExitCode == 0; + } + + private static string SubstPath + { + get + { + if (!OperatingSystem.IsWindows()) + { + throw new PlatformNotSupportedException(); + } + + string systemRoot = Environment.GetEnvironmentVariable("SystemRoot") ?? @"C:\Windows"; + string system32 = Path.Join(systemRoot, "System32"); + return Path.Join(system32, "subst.exe"); + } + } + /// For standalone debugging help. Change Main0 to Main - public static void Main0(string[] args) + public static void Main0(string[] args) { try { diff --git a/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs b/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs index d897cc7b8be25b..bde3863d5b1df9 100644 --- a/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs +++ b/src/libraries/System.IO.FileSystem/tests/RandomAccess/NoBuffering.Windows.cs @@ -176,5 +176,47 @@ public async Task WriteAsyncUsingMultipleBuffers(bool async) Assert.Equal(content, File.ReadAllBytes(filePath)); } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ReadWriteAsyncUsingMultipleBuffers(bool memoryPageSized) + { + string filePath = GetTestFilePath(); + // We test with buffers both one and two memory pages long. In the former case, + // the I/O operations will issue one scatter/gather API call, and in the latter + // case they will issue multiple calls; one per buffer. The buffers must still + // be aligned to comply with FILE_FLAG_NO_BUFFERING's requirements. + int bufferSize = Environment.SystemPageSize * (memoryPageSized ? 1 : 2); + int fileSize = bufferSize * 2; + byte[] content = RandomNumberGenerator.GetBytes(fileSize); + + using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering)) + using (SectorAlignedMemory buffer = SectorAlignedMemory.Allocate(fileSize)) + { + Memory firstHalf = buffer.Memory.Slice(0, bufferSize); + Memory secondHalf = buffer.Memory.Slice(bufferSize); + + content.AsSpan().CopyTo(buffer.GetSpan()); + await RandomAccess.WriteAsync(handle, new ReadOnlyMemory[] { firstHalf, secondHalf }, 0); + + buffer.GetSpan().Clear(); + long nRead = await RandomAccess.ReadAsync(handle, new Memory[] { firstHalf, secondHalf }, 0); + + Assert.Equal(buffer.GetSpan().Length, nRead); + AssertExtensions.SequenceEqual(buffer.GetSpan(), content.AsSpan()); + } + } + + [Fact] + public async Task ReadWriteAsyncUsingEmptyBuffers() + { + string filePath = GetTestFilePath(); + using SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering); + + long nRead = await RandomAccess.ReadAsync(handle, Array.Empty>(), 0); + Assert.Equal(0, nRead); + await RandomAccess.WriteAsync(handle, Array.Empty>(), 0); + } } } diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 736d3b1ee5654b..4c8fa1c23be5b8 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -1,4 +1,4 @@ - + true true @@ -24,7 +24,7 @@ - + @@ -55,6 +55,7 @@ + @@ -70,19 +71,21 @@ - - + + - + + + @@ -101,7 +104,7 @@ - + @@ -117,6 +120,7 @@ + @@ -211,8 +215,7 @@ - + diff --git a/src/libraries/System.IO.FileSystem/tests/VirtualDriveSymbolicLinks.Windows.cs b/src/libraries/System.IO.FileSystem/tests/VirtualDriveSymbolicLinks.Windows.cs new file mode 100644 index 00000000000000..d88425086b7024 --- /dev/null +++ b/src/libraries/System.IO.FileSystem/tests/VirtualDriveSymbolicLinks.Windows.cs @@ -0,0 +1,247 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.IO.Tests +{ + // Need to reuse the same virtual drive for all the test methods. + // Creating and disposing one virtual drive per class achieves this. + [PlatformSpecific(TestPlatforms.Windows)] + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsSubstAvailable))] + public class VirtualDrive_SymbolicLinks : BaseSymbolicLinks + { + protected override void Dispose(bool disposing) + { + try + { + if (VirtualDriveLetter != default) + { + MountHelper.DeleteVirtualDrive(VirtualDriveLetter); + Directory.Delete(VirtualDriveTargetDir, recursive: true); + } + } + catch { } // avoid exceptions on dispose + base.Dispose(disposing); + } + + [Theory] + // false, false, false, false // Target is not in virtual drive + // false, false, true, false // Target is not in virtual drive + [InlineData(false, true, false, true)] // Immediate target expected, target is in virtual drive + [InlineData(false, true, true, false)] // Final target expected, target is in virtual drive + // true, false, false, false // Target is not in virtual drive + // true, false, true, false // Target is not in virtual drive + [InlineData(true, true, false, true)] // Immediate target expected, target is in virtual drive + [InlineData(true, true, true, false)] // Final target expected, target is in virtual drive + public void VirtualDrive_SymbolicLinks_LinkAndTarget( + bool isLinkInVirtualDrive, + bool isTargetInVirtualDrive, + bool returnFinalTarget, + bool isExpectedTargetPathVirtual) + { + string linkExpectedFolderPath = GetVirtualOrRealPath(isLinkInVirtualDrive); + // File link + string fileLinkName = GetRandomLinkName(); + string fileLinkPath = Path.Join(linkExpectedFolderPath, fileLinkName); + // Directory link + string dirLinkName = GetRandomLinkName(); + string dirLinkPath = Path.Join(linkExpectedFolderPath, dirLinkName); + + string targetExpectedFolderPath = GetVirtualOrRealPath(isTargetInVirtualDrive); + // File target + string fileTargetFileName = GetRandomFileName(); + string fileTargetPath = Path.Join(targetExpectedFolderPath, fileTargetFileName); + // Directory target + string dirTargetFileName = GetRandomDirName(); + string dirTargetPath = Path.Join(targetExpectedFolderPath, dirTargetFileName); + + // Create targets + File.Create(fileTargetPath).Dispose(); + Directory.CreateDirectory(dirTargetPath); + + // Create links + FileInfo fileLinkInfo = new FileInfo(fileLinkPath); + fileLinkInfo.CreateAsSymbolicLink(fileTargetPath); + DirectoryInfo dirLinkInfo = new DirectoryInfo(dirLinkPath); + dirLinkInfo.CreateAsSymbolicLink(dirTargetPath); + + // The expected results depend on the target location and the value of returnFinalTarget + + // LinkTarget always retrieves the immediate target, so the expected value + // is always the path that was provided by the user for the target + + // Verify the LinkTarget values of the link infos + Assert.Equal(fileTargetPath, fileLinkInfo.LinkTarget); + Assert.Equal(dirTargetPath, dirLinkInfo.LinkTarget); + + // When the target is in a virtual drive, and returnFinalTarget is true, + // the expected target path is the real path, not the virtual path + string expectedTargetPath = GetVirtualOrRealPath(isExpectedTargetPathVirtual); + + string expectedTargetFileInfoFullName = Path.Join(expectedTargetPath, fileTargetFileName); + string expectedTargetDirectoryInfoFullName = Path.Join(expectedTargetPath, dirTargetFileName); + + // Verify target infos from link info instances + FileSystemInfo? targetFileInfoFromFileInfoLink = fileLinkInfo.ResolveLinkTarget(returnFinalTarget); + FileSystemInfo? targetDirInfoFromDirInfoLink = dirLinkInfo.ResolveLinkTarget(returnFinalTarget); + + Assert.True(targetFileInfoFromFileInfoLink is FileInfo); + Assert.True(targetDirInfoFromDirInfoLink is DirectoryInfo); + + Assert.Equal(expectedTargetFileInfoFullName, targetFileInfoFromFileInfoLink.FullName); + Assert.Equal(expectedTargetDirectoryInfoFullName, targetDirInfoFromDirInfoLink.FullName); + + // Verify targets infos via static methods + FileSystemInfo? targetFileInfoFromFile = File.ResolveLinkTarget(fileLinkPath, returnFinalTarget); + FileSystemInfo? targetFileInfoFromDirectory = Directory.ResolveLinkTarget(dirLinkPath, returnFinalTarget); + + Assert.True(targetFileInfoFromFile is FileInfo); + Assert.True(targetFileInfoFromDirectory is DirectoryInfo); + + Assert.Equal(expectedTargetFileInfoFullName, targetFileInfoFromFile.FullName); + Assert.Equal(expectedTargetDirectoryInfoFullName, targetFileInfoFromDirectory.FullName); + } + + + [Theory] + // false, false, false, false, false // Target is not in virtual drive + // false, false, false, true, false // Target is not in virtual drive + [InlineData(false, false, true, false, false)] // Immediate target expected, middle link is NOT in virtual drive + [InlineData(false, false, true, true, false)] // Final target expected, target is in virtual drive + // false, true, false, false, false // Target is not in virtual drive + // false, true, false, true, false // Target is not in virtual drive + [InlineData(false, true, true, false, true)] // Immediate target expected, target is in virtual drive + [InlineData(false, true, true, true, false)] // Final target expected, target is in virtual drive + // true, false, false, false, false // Target is not in virtual drive + // true, false, false, true, false // Target is not in virtual drive + [InlineData(true, false, true, false, false)] // Immediate target expected, middle link is NOT in virtual drive + [InlineData(true, false, true, true, false)] // Final target expected, target is in virtual drive + // true, true, false, false, false // Target is not in virtual drive + // true, true, false, true, false // Target is not in virtual drive + [InlineData(true, true, true, false, true)] // Immediate target expected, target is in virtual drive + [InlineData(true, true, true, true, false)] // Final target expected, target is in virtual drive + public void VirtualDrive_SymbolicLinks_WithIndirection( + bool isFirstLinkInVirtualDrive, + bool isMiddleLinkInVirtualDrive, + bool isTargetInVirtualDrive, + bool returnFinalTarget, + bool isExpectedTargetPathVirtual) + { + string firstLinkExpectedFolderPath = GetVirtualOrRealPath(isFirstLinkInVirtualDrive); + // File link + string fileLinkPath = Path.Join(firstLinkExpectedFolderPath, GetRandomLinkName()); + // Directory link + string dirLinkPath = Path.Join(firstLinkExpectedFolderPath, GetRandomLinkName()); + + string middleLinkExpectedFolderPath = GetVirtualOrRealPath(isMiddleLinkInVirtualDrive); + // File middle link + string fileMiddleLinkFileName = GetRandomLinkName(); + string fileMiddleLinkPath = Path.Join(middleLinkExpectedFolderPath, fileMiddleLinkFileName); + // Directory middle link + string dirMiddleLinkFileName = GetRandomLinkName(); + string dirMiddleLinkPath = Path.Join(middleLinkExpectedFolderPath, dirMiddleLinkFileName); + + string targetExpectedFolderPath = GetVirtualOrRealPath(isTargetInVirtualDrive); + // File final target + string fileFinalTargetFileName = GetRandomFileName(); + string fileFinalTargetPath = Path.Join(targetExpectedFolderPath, fileFinalTargetFileName); + // Directory final target + string dirFinalTargetFileName = GetRandomDirName(); + string dirFinalTargetPath = Path.Join(targetExpectedFolderPath, dirFinalTargetFileName); + + // Create targets + File.Create(fileFinalTargetPath).Dispose(); + Directory.CreateDirectory(dirFinalTargetPath); + + // Create initial links + FileInfo fileLinkInfo = new FileInfo(fileLinkPath); + fileLinkInfo.CreateAsSymbolicLink(fileMiddleLinkPath); + + DirectoryInfo dirLinkInfo = new DirectoryInfo(dirLinkPath); + dirLinkInfo.CreateAsSymbolicLink(dirMiddleLinkPath); + + // Create middle links + FileInfo fileMiddleLinkInfo = new FileInfo(fileMiddleLinkPath); + fileMiddleLinkInfo.CreateAsSymbolicLink(fileFinalTargetPath); + + DirectoryInfo dirMiddleLinkInfo = new DirectoryInfo(dirMiddleLinkPath); + dirMiddleLinkInfo.CreateAsSymbolicLink(dirFinalTargetPath); + + // The expected results depend on the target location and the value of returnFinalTarget + + // LinkTarget always retrieves the immediate target, so the expected value + // is always the path that was provided by the user for the middle link + + // Verify the LinkTarget values of the link infos + Assert.Equal(fileMiddleLinkPath, fileLinkInfo.LinkTarget); + Assert.Equal(dirMiddleLinkPath, dirLinkInfo.LinkTarget); + + // When the target is in a virtual drive, + // the expected target path is the real path, not the virtual path + // When returnFinalTarget is true, the expected target path is the + // resolved path from the final target in the chain of links + string expectedTargetPath = GetVirtualOrRealPath(isExpectedTargetPathVirtual); + + string expectedTargetFileInfoFullName = Path.Join(expectedTargetPath, + returnFinalTarget ? fileFinalTargetFileName : fileMiddleLinkFileName); + + string expectedTargetDirectoryInfoFullName = Path.Join(expectedTargetPath, + returnFinalTarget ? dirFinalTargetFileName : dirMiddleLinkFileName); + + // Verify target infos from link info instances + FileSystemInfo? targetFileInfoFromFileInfoLink = fileLinkInfo.ResolveLinkTarget(returnFinalTarget); + FileSystemInfo? targetDirInfoFromDirInfoLink = dirLinkInfo.ResolveLinkTarget(returnFinalTarget); + + Assert.True(targetFileInfoFromFileInfoLink is FileInfo); + Assert.True(targetDirInfoFromDirInfoLink is DirectoryInfo); + + Assert.Equal(expectedTargetFileInfoFullName, targetFileInfoFromFileInfoLink.FullName); + Assert.Equal(expectedTargetDirectoryInfoFullName, targetDirInfoFromDirInfoLink.FullName); + + // Verify targets infos via static methods + FileSystemInfo? targetFileInfoFromFile = File.ResolveLinkTarget(fileLinkPath, returnFinalTarget); + FileSystemInfo? targetFileInfoFromDirectory = Directory.ResolveLinkTarget(dirLinkPath, returnFinalTarget); + + Assert.True(targetFileInfoFromFile is FileInfo); + Assert.True(targetFileInfoFromDirectory is DirectoryInfo); + + Assert.Equal(expectedTargetFileInfoFullName, targetFileInfoFromFile.FullName); + Assert.Equal(expectedTargetDirectoryInfoFullName, targetFileInfoFromDirectory.FullName); + } + + private string GetVirtualOrRealPath(bool condition) => condition ? $"{VirtualDriveLetter}:" : VirtualDriveTargetDir; + + // Temporary Windows directory that can be mounted to a drive letter using the subst command + private string? _virtualDriveTargetDir = null; + private string VirtualDriveTargetDir + { + get + { + if (_virtualDriveTargetDir == null) + { + // Create a folder inside the temp directory so that it can be mounted to a drive letter with subst + _virtualDriveTargetDir = Path.Join(Path.GetTempPath(), GetRandomDirName()); + Directory.CreateDirectory(_virtualDriveTargetDir); + } + + return _virtualDriveTargetDir; + } + } + + // Windows drive letter that points to a mounted directory using the subst command + private char _virtualDriveLetter = default; + private char VirtualDriveLetter + { + get + { + if (_virtualDriveLetter == default) + { + // Mount the folder to a drive letter + _virtualDriveLetter = MountHelper.CreateVirtualDrive(VirtualDriveTargetDir); + } + return _virtualDriveLetter; + } + } + } +} diff --git a/src/libraries/System.IO.Hashing/src/System.IO.Hashing.csproj b/src/libraries/System.IO.Hashing/src/System.IO.Hashing.csproj index acfa86bb798d87..acdb05bb3e424b 100644 --- a/src/libraries/System.IO.Hashing/src/System.IO.Hashing.csproj +++ b/src/libraries/System.IO.Hashing/src/System.IO.Hashing.csproj @@ -4,8 +4,7 @@ enable $(NetCoreAppCurrent);netstandard2.0;net461 true - - true + 1 Provides non-cryptographic hash algorithms, such as CRC-32. Commonly Used Types: diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs index d6db9bae19b2e3..792a5bbbffb8df 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash32.cs @@ -215,7 +215,7 @@ private static int StaticHash(ReadOnlySpan source, Span destination, int totalLength = source.Length; State state = new State((uint)seed); - while (source.Length > StripeSize) + while (source.Length >= StripeSize) { state.ProcessStripe(source); source = source.Slice(StripeSize); diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs index 990ed77d64de27..367c6213c25fe3 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHash64.cs @@ -215,7 +215,7 @@ private static int StaticHash(ReadOnlySpan source, Span destination, int totalLength = source.Length; State state = new State((ulong)seed); - while (source.Length > StripeSize) + while (source.Length >= StripeSize) { state.ProcessStripe(source); source = source.Slice(StripeSize); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs index eed5aec365b3eb..9ec9262dd1c5d8 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.007.cs @@ -36,6 +36,8 @@ public static IEnumerable TestCases private const string DotNetHashesThis3 = DotNetHashesThis + DotNetHashesThis + DotNetHashesThis; private const string DotNetNCHashing = ".NET now has non-crypto hashing"; private const string DotNetNCHashing3 = DotNetNCHashing + DotNetNCHashing + DotNetNCHashing; + private const string SixteenBytes = ".NET Hashes This"; + private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -77,6 +79,11 @@ public static IEnumerable TestCases $"{DotNetNCHashing} (x3)", Encoding.ASCII.GetBytes(DotNetNCHashing3), "CABC8ABD"), + // stripe size + new TestCase( + $"{SixteenBytes} (x3)", + Encoding.ASCII.GetBytes(SixteenBytes3), + "AD98EBD3") }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(Seed); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs index f9dccad0294028..abd77d8c22f97d 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.cs @@ -34,6 +34,8 @@ public static IEnumerable TestCases private const string DotNetHashesThis3 = DotNetHashesThis + DotNetHashesThis + DotNetHashesThis; private const string DotNetNCHashing = ".NET now has non-crypto hashing"; private const string DotNetNCHashing3 = DotNetNCHashing + DotNetNCHashing + DotNetNCHashing; + private const string SixteenBytes = ".NET Hashes This"; + private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -90,6 +92,11 @@ public static IEnumerable TestCases $"{DotNetNCHashing} (x3)", Encoding.ASCII.GetBytes(DotNetNCHashing3), "65242024"), + // stripe size + new TestCase( + $"{SixteenBytes} (x3)", + Encoding.ASCII.GetBytes(SixteenBytes3), + "29DA7472") }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs index 5171e62f8ca562..4a116bc50354e0 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash32Tests.f00d.cs @@ -36,6 +36,8 @@ public static IEnumerable TestCases private const string DotNetHashesThis3 = DotNetHashesThis + DotNetHashesThis + DotNetHashesThis; private const string DotNetNCHashing = ".NET now has non-crypto hashing"; private const string DotNetNCHashing3 = DotNetNCHashing + DotNetNCHashing + DotNetNCHashing; + private const string SixteenBytes = ".NET Hashes This"; + private const string SixteenBytes3 = SixteenBytes + SixteenBytes + SixteenBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -77,6 +79,11 @@ public static IEnumerable TestCases $"{DotNetNCHashing} (x3)", Encoding.ASCII.GetBytes(DotNetNCHashing3), "5A513E6D"), + // stripe size + new TestCase( + $"{SixteenBytes} (x3)", + Encoding.ASCII.GetBytes(SixteenBytes3), + "B38A9A45") }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash32(Seed); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs index 5c2e575377870d..836b29230f3e67 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.007.cs @@ -38,6 +38,8 @@ public static IEnumerable TestCases private const string DotNetNCHashing = ".NET now has non-crypto hashing"; private const string SixtyThreeBytes = "A sixty-three byte test input requires substantial forethought!"; private const string SixtyThreeBytes3 = SixtyThreeBytes + SixtyThreeBytes + SixtyThreeBytes; + private const string ThirtyTwoBytes = "This string has 32 ASCII bytes.."; + private const string ThirtyTwoBytes3 = ThirtyTwoBytes + ThirtyTwoBytes + ThirtyTwoBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -87,6 +89,11 @@ public static IEnumerable TestCases $"{SixtyThreeBytes} (x3)", Encoding.ASCII.GetBytes(SixtyThreeBytes3), "D6095B93EB10BEDA"), + // stripe size + new TestCase( + $"{ThirtyTwoBytes} (x3)", + Encoding.ASCII.GetBytes(ThirtyTwoBytes3), + "45116421CF932B1F") }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(Seed); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs index 973d108fc93778..213e6f91c252cf 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.cs @@ -36,6 +36,8 @@ public static IEnumerable TestCases private const string DotNetNCHashing = ".NET now has non-crypto hashing"; private const string SixtyThreeBytes = "A sixty-three byte test input requires substantial forethought!"; private const string SixtyThreeBytes3 = SixtyThreeBytes + SixtyThreeBytes + SixtyThreeBytes; + private const string ThirtyTwoBytes = "This string has 32 ASCII bytes.."; + private const string ThirtyTwoBytes3 = ThirtyTwoBytes + ThirtyTwoBytes + ThirtyTwoBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -103,6 +105,11 @@ public static IEnumerable TestCases $"{SixtyThreeBytes} (x3)", Encoding.ASCII.GetBytes(SixtyThreeBytes3), "239C7B3A85BD22B3"), + // stripe size + new TestCase( + $"{ThirtyTwoBytes} (x3)", + Encoding.ASCII.GetBytes(ThirtyTwoBytes3), + "975E3E6FE7E67FBC") }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(); diff --git a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs index 23006a571627b3..75fc4f514aca9a 100644 --- a/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs +++ b/src/libraries/System.IO.Hashing/tests/XxHash64Tests.f00d.cs @@ -38,6 +38,8 @@ public static IEnumerable TestCases private const string DotNetNCHashing = ".NET now has non-crypto hashing"; private const string SixtyThreeBytes = "A sixty-three byte test input requires substantial forethought!"; private const string SixtyThreeBytes3 = SixtyThreeBytes + SixtyThreeBytes + SixtyThreeBytes; + private const string ThirtyTwoBytes = "This string has 32 ASCII bytes.."; + private const string ThirtyTwoBytes3 = ThirtyTwoBytes + ThirtyTwoBytes + ThirtyTwoBytes; protected static IEnumerable TestCaseDefinitions { get; } = new[] @@ -87,6 +89,11 @@ public static IEnumerable TestCases $"{SixtyThreeBytes} (x3)", Encoding.ASCII.GetBytes(SixtyThreeBytes3), "6F1C62EB48EA2FEC"), + // stripe size + new TestCase( + $"{ThirtyTwoBytes} (x3)", + Encoding.ASCII.GetBytes(ThirtyTwoBytes3), + "B358EB96B8E3E7AD") }; protected override NonCryptographicHashAlgorithm CreateInstance() => new XxHash64(Seed); diff --git a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs index 389ab072d9a6c9..6882527cecc8de 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedFile.Unix.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; using Microsoft.Win32.SafeHandles; namespace System.IO.MemoryMappedFiles @@ -173,9 +174,6 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt private static FileStream? CreateSharedBackingObjectUsingMemory( Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability) { - // The POSIX shared memory object name must begin with '/'. After that we just want something short and unique. - string mapName = string.Create(null, stackalloc char[128], $"/corefx_map_{Guid.NewGuid():N}"); - // Determine the flags to use when creating the shared memory object Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ? Interop.Sys.OpenFlags.O_RDWR : @@ -191,22 +189,32 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0) perms |= Interop.Sys.Permissions.S_IXUSR; - // Create the shared memory object. - SafeFileHandle fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms); - if (fd.IsInvalid) + string mapName; + SafeFileHandle fd; + + do { - Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); - if (errorInfo.Error == Interop.Error.ENOTSUP) + mapName = GenerateMapName(); + fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms); // Create the shared memory object. + + if (fd.IsInvalid) { - // If ShmOpen is not supported, fall back to file backing object. - // Note that the System.Native shim will force this failure on platforms where - // the result of native shm_open does not work well with our subsequent call - // to mmap. - return null; - } + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + fd.Dispose(); - throw Interop.GetExceptionForIoErrno(errorInfo); - } + if (errorInfo.Error == Interop.Error.ENOTSUP) + { + // If ShmOpen is not supported, fall back to file backing object. + // Note that the System.Native shim will force this failure on platforms where + // the result of native shm_open does not work well with our subsequent call to mmap. + return null; + } + else if (errorInfo.Error != Interop.Error.EEXIST) // map with same name already existed + { + throw Interop.GetExceptionForIoErrno(errorInfo); + } + } + } while (fd.IsInvalid); try { @@ -236,6 +244,18 @@ private static FileStream CreateSharedBackingObject(Interop.Sys.MemoryMappedProt fd.Dispose(); throw; } + + static string GenerateMapName() + { + const int MaxSharedMemoryObjectNameLength = 32; // SHM_NAME_MAX on OSX ARM64, on other systems it's equal PATH_MAX (250) + // The POSIX shared memory object name must begin with '/'. After that we just want something short (32) and unique. + return string.Create(MaxSharedMemoryObjectNameLength, 0, (span, state) => + { + Guid.NewGuid().TryFormat(span, out int charsWritten, "N"); + Debug.Assert(charsWritten == MaxSharedMemoryObjectNameLength); + "/dotnet_".CopyTo(span); + }); + } } private static FileStream CreateSharedBackingObjectUsingFile(Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability) diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs index e7c5ee2f80c3a6..70b82398301d56 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedFile.CreateNew.Tests.cs @@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests /// /// Tests for MemoryMappedFile.CreateNew. /// - [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class MemoryMappedFileTests_CreateNew : MemoryMappedFilesTestBase { /// diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs index 8f7e2fae576eb0..8fe35396ae8044 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewAccessor.Tests.cs @@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests /// /// Tests for MemoryMappedViewAccessor. /// - [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class MemoryMappedViewAccessorTests : MemoryMappedFilesTestBase { /// @@ -91,10 +90,10 @@ public void ValidAccessLevelCombinations(MemoryMappedFileAccess mapAccess, Memor } catch (UnauthorizedAccessException) { - if ((OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst() || PlatformDetection.IsInContainer) && + if ((OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS() || PlatformDetection.IsInContainer) && (viewAccess == MemoryMappedFileAccess.ReadExecute || viewAccess == MemoryMappedFileAccess.ReadWriteExecute)) { - // Containers and OSX with SIP enabled do not have execute permissions by default. + // Containers and OSXlike platforms with SIP enabled do not have execute permissions by default. throw new SkipTestException("Insufficient execute permission."); } diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs index d77a24ae0ddfa6..f279b8c33f98f7 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStream.Tests.cs @@ -11,7 +11,6 @@ namespace System.IO.MemoryMappedFiles.Tests /// /// Tests for MemoryMappedViewStream. /// - [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class MemoryMappedViewStreamTests : MemoryMappedFilesTestBase { /// @@ -91,10 +90,10 @@ public void ValidAccessLevelCombinations(MemoryMappedFileAccess mapAccess, Memor } catch (UnauthorizedAccessException) { - if ((OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst() || PlatformDetection.IsInContainer) && + if ((OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst() || OperatingSystem.IsIOS() || OperatingSystem.IsTvOS() || PlatformDetection.IsInContainer) && (viewAccess == MemoryMappedFileAccess.ReadExecute || viewAccess == MemoryMappedFileAccess.ReadWriteExecute)) { - // Containers and OSX with SIP enabled do not have execute permissions by default. + // Containers and OSXlike platforms with SIP enabled do not have execute permissions by default. throw new SkipTestException("Insufficient execute permission."); } diff --git a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs index e84a86a91f20cc..c190d329a00fe6 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/tests/MemoryMappedViewStreamConformanceTests.cs @@ -45,7 +45,6 @@ private Task CreateStream(byte[] initialData, FileAccess access) } } - [ActiveIssue("https://github.com/dotnet/runtime/issues/49104", typeof(PlatformDetection), nameof(PlatformDetection.IsMacOsAppleSilicon))] public class AnonymousMemoryMappedViewStreamConformanceTests : MemoryMappedViewStreamConformanceTests { protected override MemoryMappedFile CreateFile(int length) => diff --git a/src/libraries/System.IO.Packaging/src/CompatibilitySuppressions.xml b/src/libraries/System.IO.Packaging/src/CompatibilitySuppressions.xml index ca7554cc926e6c..c4a6f07ed08c6a 100644 --- a/src/libraries/System.IO.Packaging/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.IO.Packaging/src/CompatibilitySuppressions.xml @@ -1,10 +1,5 @@  - - CP0001 - lib/netstandard2.0/System.IO.Packaging.dll - lib/net461/System.IO.Packaging.dll - PKV006 .NETFramework,Version=v4.6 diff --git a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj index 34f79827374acc..ec9632c4d1f25f 100644 --- a/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj +++ b/src/libraries/System.IO.Pipelines/src/System.IO.Pipelines.csproj @@ -9,6 +9,7 @@ Commonly Used Types: System.IO.Pipelines.Pipe System.IO.Pipelines.PipeWriter System.IO.Pipelines.PipeReader + 2 source) } // We filled the segment - _writingHead.End += writable; + _writingHead.End += _writingHeadBytesBuffered; _writingHeadBytesBuffered = 0; // This is optimized to use pooled memory. That's why we pass 0 instead of diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs index fb25780a3fab46..aba52f13e96469 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/PipeAwaitable.cs @@ -47,16 +47,33 @@ public void BeginOperation(CancellationToken cancellationToken, Action { cancellationToken.ThrowIfCancellationRequested(); - _awaitableState |= AwaitableState.Running; - // Don't register if already completed, we would immediately unregistered in ObserveCancellation if (cancellationToken.CanBeCanceled && !IsCompleted) { +#if DEBUG + var previousAwaitableState = _awaitableState; +#endif + + _cancellationTokenRegistration = cancellationToken.UnsafeRegister(callback, state); + + // If we get back the default CancellationTokenRegistration then it means the + // callback synchronously and we can throw inline. This is safe because we haven't changed + // the state of the awaitable as yet. + if (_cancellationTokenRegistration == default(CancellationTokenRegistration)) + { +#if DEBUG + Debug.Assert(previousAwaitableState == _awaitableState, "The awaitable state changed!"); +#endif + + cancellationToken.ThrowIfCancellationRequested(); + } + #if (NETSTANDARD2_0 || NETFRAMEWORK) _cancellationToken = cancellationToken; #endif - _cancellationTokenRegistration = cancellationToken.UnsafeRegister(callback, state); } + + _awaitableState |= AwaitableState.Running; } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs index 7b33539b540b33..cc457bf9bf2bff 100644 --- a/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs +++ b/src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs @@ -383,11 +383,13 @@ public override async Task CopyToAsync(PipeWriter destination, CancellationToken try { BufferSegment? segment = _readHead; + int segmentIndex = _readIndex; + try { while (segment != null) { - FlushResult flushResult = await destination.WriteAsync(segment.Memory, tokenSource.Token).ConfigureAwait(false); + FlushResult flushResult = await destination.WriteAsync(segment.Memory.Slice(segmentIndex), tokenSource.Token).ConfigureAwait(false); if (flushResult.IsCanceled) { @@ -395,6 +397,7 @@ public override async Task CopyToAsync(PipeWriter destination, CancellationToken } segment = segment.NextSegment; + segmentIndex = 0; if (flushResult.IsCompleted) { @@ -451,13 +454,16 @@ public override async Task CopyToAsync(Stream destination, CancellationToken can try { BufferSegment? segment = _readHead; + int segmentIndex = _readIndex; + try { while (segment != null) { - await destination.WriteAsync(segment.Memory, tokenSource.Token).ConfigureAwait(false); + await destination.WriteAsync(segment.Memory.Slice(segmentIndex), tokenSource.Token).ConfigureAwait(false); segment = segment.NextSegment; + segmentIndex = 0; } } finally diff --git a/src/libraries/System.IO.Pipelines/tests/PipeLengthTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeLengthTests.cs index fcf9d7af55b053..fd9fc83833a8b1 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeLengthTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeLengthTests.cs @@ -277,5 +277,19 @@ public async Task NullExaminedAndConsumedNoops() ReadResult result = await _pipe.Reader.ReadAsync(); _pipe.Reader.AdvanceTo(default, default); } + + [Fact] + public async Task AdvanceFollowedByWriteAsyncTest() + { + Memory buffer = new byte[26]; + Pipe pipe = new(new PipeOptions(minimumSegmentSize: 1)); + + var mem = pipe.Writer.GetMemory(14)[..14]; + buffer[..14].CopyTo(mem); + pipe.Writer.Advance(14); + await pipe.Writer.WriteAsync(buffer[14..]); + ReadResult res = await pipe.Reader.ReadAsync(); + Assert.Equal(res.Buffer.Length, buffer.Length); + } } } diff --git a/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs b/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs index e58e5af4e70598..adf547a3c452bf 100644 --- a/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs +++ b/src/libraries/System.IO.Pipelines/tests/PipeReaderCopyToAsyncTests.cs @@ -286,5 +286,41 @@ public async Task ThrowingFromStreamCallsAdvanceToWithStartOfLastReadResult(int Assert.True(startPosition.Equals(wrappedPipeReader.LastConsumed)); Assert.True(startPosition.Equals(wrappedPipeReader.LastExamined)); } + + [Fact] + public async Task CopyToAsyncStreamCopiesRemainderAfterReadingSome() + { + var buffer = Encoding.UTF8.GetBytes("Hello World"); + await Pipe.Writer.WriteAsync(buffer); + Pipe.Writer.Complete(); + + var result = await PipeReader.ReadAsync(); + Assert.Equal(result.Buffer.ToArray(), buffer); + // Consume Hello + PipeReader.AdvanceTo(result.Buffer.GetPosition(5)); + + var ms = new MemoryStream(); + await PipeReader.CopyToAsync(ms); + + Assert.Equal(buffer.AsMemory(5).ToArray(), ms.ToArray()); + } + + [Fact] + public async Task CopyToAsyncPipeWriterCopiesRemainderAfterReadingSome() + { + var buffer = Encoding.UTF8.GetBytes("Hello World"); + await Pipe.Writer.WriteAsync(buffer); + Pipe.Writer.Complete(); + + var result = await PipeReader.ReadAsync(); + Assert.Equal(result.Buffer.ToArray(), buffer); + // Consume Hello + PipeReader.AdvanceTo(result.Buffer.GetPosition(5)); + + var ms = new MemoryStream(); + await PipeReader.CopyToAsync(PipeWriter.Create(ms)); + + Assert.Equal(buffer.AsMemory(5).ToArray(), ms.ToArray()); + } } } diff --git a/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj b/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj index 86043b1f0aa51a..ff96f2f4fca135 100644 --- a/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj +++ b/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.proj @@ -6,6 +6,8 @@ false $(NoWarn);NU5128 + + false diff --git a/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.props b/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.props index 557c2231228086..4824f36ff0a4bf 100644 --- a/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.props +++ b/src/libraries/System.IO.Ports/pkg/runtime.native.System.IO.Ports.props @@ -8,10 +8,13 @@ none true $(SymbolsSuffix) - $(TargetsForTfmSpecificDebugSymbolsInPackage);AddRuntimeSpecificNativeSymbolToPackage + + $(TargetsForTfmSpecificDebugSymbolsInPackage);AddRuntimeSpecificNativeSymbolToPackage true $(NoWarn);NU5128 + + false diff --git a/src/libraries/System.IO.Ports/pkg/runtime.osx-arm64.runtime.native.System.IO.Ports.proj b/src/libraries/System.IO.Ports/pkg/runtime.osx-arm64.runtime.native.System.IO.Ports.proj new file mode 100644 index 00000000000000..f93b313169e79c --- /dev/null +++ b/src/libraries/System.IO.Ports/pkg/runtime.osx-arm64.runtime.native.System.IO.Ports.proj @@ -0,0 +1,7 @@ + + + + + true + + \ No newline at end of file diff --git a/src/libraries/System.IO.Ports/src/CompatibilitySuppressions.xml b/src/libraries/System.IO.Ports/src/CompatibilitySuppressions.xml deleted file mode 100644 index 3d3afe95121eaa..00000000000000 --- a/src/libraries/System.IO.Ports/src/CompatibilitySuppressions.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - CP0001 - lib/netstandard2.0/System.IO.Ports.dll - lib/net461/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.Handshake - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.Parity - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialData - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialDataReceivedEventArgs - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialDataReceivedEventHandler - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialError - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialErrorReceivedEventArgs - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialErrorReceivedEventHandler - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialPinChange - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialPinChangedEventArgs - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialPinChangedEventHandler - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.SerialPort - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - - CP0001 - T:System.IO.Ports.StopBits - lib/net461/System.IO.Ports.dll - runtimes/unix/lib/netstandard2.0/System.IO.Ports.dll - - \ No newline at end of file diff --git a/src/libraries/System.IO.Ports/tests/SerialPort/DosDevices.cs b/src/libraries/System.IO.Ports/tests/SerialPort/DosDevices.cs index 3fe9493c0a30e5..2d74327f97eb0d 100644 --- a/src/libraries/System.IO.Ports/tests/SerialPort/DosDevices.cs +++ b/src/libraries/System.IO.Ports/tests/SerialPort/DosDevices.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Runtime.InteropServices; namespace System.IO.Ports.Tests @@ -127,14 +128,20 @@ private static char[] CallQueryDosDevice(string name, out int dataSize) buffer = new char[buffer.Length * 2]; dataSize = QueryDosDevice(null, buffer, buffer.Length); } + else if (lastError == ERROR_ACCESS_DENIED) // Access denied eg for "MSSECFLTSYS" - just skip + { + dataSize = 0; + break; + } else { - throw new Exception("Unknown Win32 Error: " + lastError); + throw new Exception($"Error {lastError} calling QueryDosDevice for '{name}' with buffer size {buffer.Length}. {new Win32Exception((int)lastError).Message}"); } } return buffer; } + public const int ERROR_ACCESS_DENIED = 5; public const int ERROR_INSUFFICIENT_BUFFER = 122; public const int ERROR_MORE_DATA = 234; diff --git a/src/libraries/System.IO/tests/BufferedStream/BufferedStreamTests.cs b/src/libraries/System.IO/tests/BufferedStream/BufferedStreamTests.cs index 08268755202054..8d11c80336711a 100644 --- a/src/libraries/System.IO/tests/BufferedStream/BufferedStreamTests.cs +++ b/src/libraries/System.IO/tests/BufferedStream/BufferedStreamTests.cs @@ -323,6 +323,40 @@ public async Task CopyToTest_ReadBeforeCopy_CopiesAllData(bool copyAsynchronousl Array.Copy(data, 1, expected, 0, expected.Length); Assert.Equal(expected, dst.ToArray()); } + + [Fact] + [OuterLoop] + [ActiveIssue("https://github.com/dotnet/runtime/issues/45954", TestPlatforms.Browser)] + public void NoInt32OverflowInTheBufferingLogic() + { + const long position1 = 10; + const long position2 = (1L << 32) + position1; + + string filePath = Path.GetTempFileName(); + byte[] data1 = new byte[] { 1, 2, 3, 4, 5 }; + byte[] data2 = new byte[] { 6, 7, 8, 9, 10 }; + byte[] buffer = new byte[5]; + + using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) + { + stream.Seek(position1, SeekOrigin.Begin); + stream.Write(data1); + + stream.Seek(position2, SeekOrigin.Begin); + stream.Write(data2); + } + + using (var stream = new BufferedStream(new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None, bufferSize: 0, FileOptions.DeleteOnClose))) + { + stream.Seek(position1, SeekOrigin.Begin); + Assert.Equal(buffer.Length, stream.Read(buffer)); + Assert.Equal(data1, buffer); + + stream.Seek(position2, SeekOrigin.Begin); + Assert.Equal(buffer.Length, stream.Read(buffer)); + Assert.Equal(data2, buffer); + } + } } public class BufferedStream_TestLeaveOpen : TestLeaveOpen diff --git a/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj b/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj index 321e2f485088b8..c07749abe26b08 100644 --- a/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj +++ b/src/libraries/System.IO/tests/Net5CompatTests/System.IO.Net5Compat.Tests.csproj @@ -4,8 +4,7 @@ true true true - - $(NetCoreAppCurrent)-windows + $(NetCoreAppCurrent) diff --git a/src/libraries/System.Memory.Data/System.Memory.Data.sln b/src/libraries/System.Memory.Data/System.Memory.Data.sln index 5878d08ab4271f..3c371f8d59a503 100644 --- a/src/libraries/System.Memory.Data/System.Memory.Data.sln +++ b/src/libraries/System.Memory.Data/System.Memory.Data.sln @@ -17,8 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{0DE5E7DA-0AE0-4CF2-95AB-1E476FD68C5C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{9F2EC2C8-6E28-404A-8087-7A0518624EC6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{6A2B5C68-14C3-4989-8530-D51A138C72AE}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{2BD73108-47D7-40E6-BFCB-169E6AD42A81}" @@ -65,10 +63,6 @@ Global {B9162F6C-4CD1-4D33-BA4A-42830A1B1C66}.Debug|Any CPU.Build.0 = Debug|Any CPU {B9162F6C-4CD1-4D33-BA4A-42830A1B1C66}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9162F6C-4CD1-4D33-BA4A-42830A1B1C66}.Release|Any CPU.Build.0 = Release|Any CPU - {9F2EC2C8-6E28-404A-8087-7A0518624EC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9F2EC2C8-6E28-404A-8087-7A0518624EC6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9F2EC2C8-6E28-404A-8087-7A0518624EC6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9F2EC2C8-6E28-404A-8087-7A0518624EC6}.Release|Any CPU.Build.0 = Release|Any CPU {0DE5E7DA-0AE0-4CF2-95AB-1E476FD68C5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0DE5E7DA-0AE0-4CF2-95AB-1E476FD68C5C}.Debug|Any CPU.Build.0 = Debug|Any CPU {0DE5E7DA-0AE0-4CF2-95AB-1E476FD68C5C}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -90,7 +84,6 @@ Global {ACDB56AF-7B9F-4762-9764-D6FF09118D09} = {D908DCBE-EFA4-4CCA-9A1C-AEB48D59C504} {6A2B5C68-14C3-4989-8530-D51A138C72AE} = {D908DCBE-EFA4-4CCA-9A1C-AEB48D59C504} {E17B915A-81CA-44D8-818E-512B65609475} = {D908DCBE-EFA4-4CCA-9A1C-AEB48D59C504} - {9F2EC2C8-6E28-404A-8087-7A0518624EC6} = {D908DCBE-EFA4-4CCA-9A1C-AEB48D59C504} {0DE5E7DA-0AE0-4CF2-95AB-1E476FD68C5C} = {D908DCBE-EFA4-4CCA-9A1C-AEB48D59C504} {1D866ECD-FD46-4FCA-9408-D1E3E9CB1F43} = {D908DCBE-EFA4-4CCA-9A1C-AEB48D59C504} EndGlobalSection diff --git a/src/libraries/System.Memory/tests/ArrayBufferWriter/ArrayBufferWriterTests.T.cs b/src/libraries/System.Memory/tests/ArrayBufferWriter/ArrayBufferWriterTests.T.cs index 656918e5fe6e7d..b1a6c293aef32c 100644 --- a/src/libraries/System.Memory/tests/ArrayBufferWriter/ArrayBufferWriterTests.T.cs +++ b/src/libraries/System.Memory/tests/ArrayBufferWriter/ArrayBufferWriterTests.T.cs @@ -65,7 +65,6 @@ public void Clear() } [Fact] - [SkipOnCoreClr("https://github.com/dotnet/runtime/issues/42517", RuntimeConfiguration.Checked)] public void Advance() { { diff --git a/src/libraries/System.Net.Http.Json/System.Net.Http.Json.sln b/src/libraries/System.Net.Http.Json/System.Net.Http.Json.sln index e7575d6b03568b..73280ee3f28c5c 100644 --- a/src/libraries/System.Net.Http.Json/System.Net.Http.Json.sln +++ b/src/libraries/System.Net.Http.Json/System.Net.Http.Json.sln @@ -21,8 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{FEBE9C47-A00B-40B2-A85B-74ECE2F8B80A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{D120D5A7-69D9-44A2-B7F7-EE0E48CC0238}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{BC7D3412-DBCB-4863-8BF8-41899E32608C}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{945B0700-C720-4775-B9E4-6A27DAA90190}" @@ -57,10 +55,6 @@ Global {3AD3D600-C391-492D-B3D6-0F6C03DA5C27}.Debug|Any CPU.Build.0 = Debug|Any CPU {3AD3D600-C391-492D-B3D6-0F6C03DA5C27}.Release|Any CPU.ActiveCfg = Release|Any CPU {3AD3D600-C391-492D-B3D6-0F6C03DA5C27}.Release|Any CPU.Build.0 = Release|Any CPU - {D120D5A7-69D9-44A2-B7F7-EE0E48CC0238}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D120D5A7-69D9-44A2-B7F7-EE0E48CC0238}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D120D5A7-69D9-44A2-B7F7-EE0E48CC0238}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D120D5A7-69D9-44A2-B7F7-EE0E48CC0238}.Release|Any CPU.Build.0 = Release|Any CPU {BC7D3412-DBCB-4863-8BF8-41899E32608C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BC7D3412-DBCB-4863-8BF8-41899E32608C}.Debug|Any CPU.Build.0 = Debug|Any CPU {BC7D3412-DBCB-4863-8BF8-41899E32608C}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -102,7 +96,6 @@ Global {1D6F4698-E7FA-4AE3-A7A4-98939E40D08D} = {A75027EA-199E-4C86-A636-AE9AE0F0756C} {3AD3D600-C391-492D-B3D6-0F6C03DA5C27} = {A75027EA-199E-4C86-A636-AE9AE0F0756C} {7DC969DA-8BD3-4E64-88E8-26AFE65BFF7E} = {2A66925D-3658-46BE-A730-5BF70D8D5B90} - {D120D5A7-69D9-44A2-B7F7-EE0E48CC0238} = {2A66925D-3658-46BE-A730-5BF70D8D5B90} {BC7D3412-DBCB-4863-8BF8-41899E32608C} = {2A66925D-3658-46BE-A730-5BF70D8D5B90} {3EEB6FCC-2592-4879-ADDD-0FDC7AEB7BC1} = {2A66925D-3658-46BE-A730-5BF70D8D5B90} {4FB629CD-5FFC-47AC-9670-A2A8AFEE8926} = {2A66925D-3658-46BE-A730-5BF70D8D5B90} diff --git a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/System.Net.Http.Json.Functional.Tests.csproj b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/System.Net.Http.Json.Functional.Tests.csproj index 9fe7bbb28a73ba..40ae1eb7e9b284 100644 --- a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/System.Net.Http.Json.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/System.Net.Http.Json.Functional.Tests.csproj @@ -27,6 +27,6 @@ - + diff --git a/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.sln b/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.sln index d6d95c23aa12a0..7c181ccbde038f 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.sln +++ b/src/libraries/System.Net.Http.WinHttpHandler/System.Net.Http.WinHttpHandler.sln @@ -27,8 +27,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{BACC5257-6CA8-45C7-970F-C8D501DA59AB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "..\System.Text.Json\gen\System.Text.Json.SourceGeneration.csproj", "{302F00AD-85F1-4DE9-B100-41F8EAB93B7C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "..\System.Text.Json\src\System.Text.Json.csproj", "{E470810A-BAF2-4B3C-92CB-72007B7F1B6A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{2F9A243D-B060-4BB2-A9E1-A9CB861328D9}" @@ -95,10 +93,6 @@ Global {BACC5257-6CA8-45C7-970F-C8D501DA59AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {BACC5257-6CA8-45C7-970F-C8D501DA59AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {BACC5257-6CA8-45C7-970F-C8D501DA59AB}.Release|Any CPU.Build.0 = Release|Any CPU - {302F00AD-85F1-4DE9-B100-41F8EAB93B7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {302F00AD-85F1-4DE9-B100-41F8EAB93B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {302F00AD-85F1-4DE9-B100-41F8EAB93B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {302F00AD-85F1-4DE9-B100-41F8EAB93B7C}.Release|Any CPU.Build.0 = Release|Any CPU {4BA25EC1-B76B-4410-AF2D-A54B90FAB404}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4BA25EC1-B76B-4410-AF2D-A54B90FAB404}.Debug|Any CPU.Build.0 = Debug|Any CPU {4BA25EC1-B76B-4410-AF2D-A54B90FAB404}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -123,7 +117,6 @@ Global {E6A8B90B-69CD-4B0D-8A33-F208A3169674} = {49E09973-383D-4AD6-9D88-B93A02031607} {E470810A-BAF2-4B3C-92CB-72007B7F1B6A} = {49E09973-383D-4AD6-9D88-B93A02031607} {BACC5257-6CA8-45C7-970F-C8D501DA59AB} = {49E09973-383D-4AD6-9D88-B93A02031607} - {302F00AD-85F1-4DE9-B100-41F8EAB93B7C} = {49E09973-383D-4AD6-9D88-B93A02031607} {4BA25EC1-B76B-4410-AF2D-A54B90FAB404} = {49E09973-383D-4AD6-9D88-B93A02031607} {090BA6CA-F661-4BDE-9663-65F8231DDB1D} = {6C66589E-2DB3-4635-BADA-9B6452327239} {E9D5AB56-2597-42E0-BE81-C00CC63D1FB3} = {6C66589E-2DB3-4635-BADA-9B6452327239} diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs index 8173084e53c5e3..07133b2667c229 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpHandler.cs @@ -44,6 +44,7 @@ public class WinHttpHandler : HttpMessageHandler private static readonly StringWithQualityHeaderValue s_gzipHeaderValue = new StringWithQualityHeaderValue("gzip"); private static readonly StringWithQualityHeaderValue s_deflateHeaderValue = new StringWithQualityHeaderValue("deflate"); + private static readonly Lazy s_supportsTls13 = new Lazy(() => CheckTls13Support()); [ThreadStatic] private static StringBuilder? t_requestHeadersBuilder; @@ -1119,6 +1120,7 @@ private void SetSessionHandleOptions(SafeWinHttpHandle sessionHandle) SetSessionHandleTimeoutOptions(sessionHandle); SetDisableHttp2StreamQueue(sessionHandle); SetTcpKeepalive(sessionHandle); + SetRequireStreamEnd(sessionHandle); } private unsafe void SetTcpKeepalive(SafeWinHttpHandle sessionHandle) @@ -1144,6 +1146,27 @@ private unsafe void SetTcpKeepalive(SafeWinHttpHandle sessionHandle) } } + private void SetRequireStreamEnd(SafeWinHttpHandle sessionHandle) + { + if (WinHttpTrailersHelper.OsSupportsTrailers) + { + // Setting WINHTTP_OPTION_REQUIRE_STREAM_END to TRUE is needed for WinHttp to read trailing headers + // in case the response has Content-Lenght defined. + // According to the WinHttp team, the feature-detection logic in WinHttpTrailersHelper.OsSupportsTrailers + // should also indicate the support of WINHTTP_OPTION_REQUIRE_STREAM_END. + // WINHTTP_OPTION_REQUIRE_STREAM_END doesn't have effect on HTTP 1.1 requests, therefore it's safe to set it on + // the session handle so it is inhereted by all request handles. + uint optionData = 1; + if (!Interop.WinHttp.WinHttpSetOption(sessionHandle, Interop.WinHttp.WINHTTP_OPTION_REQUIRE_STREAM_END, ref optionData)) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, "Failed to enable WINHTTP_OPTION_REQUIRE_STREAM_END error code: " + Marshal.GetLastWin32Error()); + } + } + } + } + private void SetSessionHandleConnectionOptions(SafeWinHttpHandle sessionHandle) { uint optionData = (uint)_maxConnectionsPerServer; @@ -1153,6 +1176,7 @@ private void SetSessionHandleConnectionOptions(SafeWinHttpHandle sessionHandle) private void SetSessionHandleTlsOptions(SafeWinHttpHandle sessionHandle) { + const SslProtocols Tls13 = (SslProtocols)12288; // enum is missing in .NET Standard uint optionData = 0; SslProtocols sslProtocols = (_sslProtocols == SslProtocols.None) ? SecurityProtocol.DefaultSecurityProtocols : _sslProtocols; @@ -1184,10 +1208,13 @@ private void SetSessionHandleTlsOptions(SafeWinHttpHandle sessionHandle) optionData |= Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2; } - // As of Win10RS5 there's no public constant for WinHTTP + TLS 1.3 - // This library builds against netstandard, which doesn't define the Tls13 enum field. + // Set this only if supported by WinHttp version. + if (s_supportsTls13.Value && (sslProtocols & Tls13) != 0) + { + optionData |= Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3; + } - // If only unknown values (e.g. TLS 1.3) were asked for, report ERROR_INVALID_PARAMETER. + // If only unknown values were asked for, report ERROR_INVALID_PARAMETER. if (optionData == 0) { throw WinHttpException.CreateExceptionUsingError( @@ -1198,6 +1225,30 @@ private void SetSessionHandleTlsOptions(SafeWinHttpHandle sessionHandle) SetWinHttpOption(sessionHandle, Interop.WinHttp.WINHTTP_OPTION_SECURE_PROTOCOLS, ref optionData); } + private static bool CheckTls13Support() + { + try + { + using (var handler = new WinHttpHandler()) + using (SafeWinHttpHandle sessionHandle = Interop.WinHttp.WinHttpOpen( + IntPtr.Zero, + Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, + Interop.WinHttp.WINHTTP_NO_PROXY_NAME, + Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, + (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC)) + { + uint optionData = Interop.WinHttp.WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3; + + handler.SetWinHttpOption(sessionHandle, Interop.WinHttp.WINHTTP_OPTION_SECURE_PROTOCOLS, ref optionData); + return true; + } + } + catch + { + return false; + } + } + private void SetSessionHandleTimeoutOptions(SafeWinHttpHandle sessionHandle) { if (!Interop.WinHttp.WinHttpSetTimeouts( diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs index cef52465524dcf..5ac753c266ee0a 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/FunctionalTests/TrailingHeadersTest.cs @@ -67,8 +67,10 @@ public async Task Http2GetAsync_NoTrailingHeaders_EmptyCollection() } } - [ConditionalFact(nameof(TestsEnabled))] - public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted() + [InlineData(false)] + [InlineData(true)] + [ConditionalTheory(nameof(TestsEnabled))] + public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted(bool responseHasContentLength) { using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) using (HttpClient client = CreateHttpClient()) @@ -80,7 +82,14 @@ public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted() int streamId = await connection.ReadRequestHeaderAsync(); // Response header. - await connection.SendDefaultResponseHeadersAsync(streamId); + if (responseHasContentLength) + { + await connection.SendResponseHeadersAsync(streamId, endStream: false, headers: new[] { new HttpHeaderData("Content-Length", DataBytes.Length.ToString()) }); + } + else + { + await connection.SendDefaultResponseHeadersAsync(streamId); + } // Response data, missing Trailers. await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); @@ -98,8 +107,10 @@ public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted() } } - [ConditionalFact(nameof(TestsEnabled))] - public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Available() + [InlineData(false)] + [InlineData(true)] + [ConditionalTheory(nameof(TestsEnabled))] + public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Available(bool responseHasContentLength) { using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) using (HttpClient client = CreateHttpClient()) @@ -111,7 +122,14 @@ public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Availab int streamId = await connection.ReadRequestHeaderAsync(); // Response header. - await connection.SendDefaultResponseHeadersAsync(streamId); + if (responseHasContentLength) + { + await connection.SendResponseHeadersAsync(streamId, endStream: false, headers: new[] { new HttpHeaderData("Content-Length", DataBytes.Length.ToString()) }); + } + else + { + await connection.SendDefaultResponseHeadersAsync(streamId); + } // Response data, missing Trailers. await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); diff --git a/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.mobile.xml b/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.mobile.xml index 5b705abeb24bda..208bba9a30af6c 100644 --- a/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.mobile.xml +++ b/src/libraries/System.Net.Http/src/ILLink/ILLink.Substitutions.mobile.xml @@ -2,6 +2,7 @@ + diff --git a/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.Mobile.LibraryBuild.xml similarity index 96% rename from src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.LibraryBuild.xml rename to src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.Mobile.LibraryBuild.xml index a6af29a8085c3e..d6f428f20d4e6d 100644 --- a/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.LibraryBuild.xml +++ b/src/libraries/System.Net.Http/src/ILLink/ILLink.Suppressions.Mobile.LibraryBuild.xml @@ -141,6 +141,18 @@ M:System.Net.Http.HttpClientHandler.SetMaxAutomaticRedirections(System.Int32) The Xamarin.iOS and Mono.Android libraries are not present when running the trimmer analysis during our build. A consuming application will get a warning if these libraries aren't present when trimming the full app. + + ILLink + IL2035 + member + M:System.Net.Http.HttpClientHandler.GetServerCertificateCustomValidationCallback + + + ILLink + IL2035 + member + M:System.Net.Http.HttpClientHandler.SetServerCertificateCustomValidationCallback(System.Func{System.Net.Http.HttpRequestMessage,System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean}) + ILLink IL2035 diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 28de4bb4bb00d3..2897f5fb1505fc 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -12,6 +12,18 @@ $(DefineConstants);TARGET_MOBILE + + $(DefineConstants);TARGET_ANDROID + + + $(DefineConstants);TARGET_IOS + + + $(DefineConstants);TARGET_MACCATALYST + + + $(DefineConstants);TARGET_TVOS + $(DefineConstants);TARGET_BROWSER @@ -23,6 +35,7 @@ + @@ -41,10 +54,8 @@ - - - - + diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs index c31e628159db0e..ee53b9e626c751 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeaders.cs @@ -1051,7 +1051,7 @@ private HeaderDescriptor GetHeaderDescriptor(string name) throw new InvalidOperationException(SR.Format(SR.net_http_headers_not_allowed_header_name, name)); } - private bool TryGetHeaderDescriptor(string name, out HeaderDescriptor descriptor) + internal bool TryGetHeaderDescriptor(string name, out HeaderDescriptor descriptor) { if (string.IsNullOrEmpty(name)) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs index ad1a1850ea83c4..5e67476d116a99 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/HttpHeadersNonValidated.cs @@ -32,7 +32,7 @@ namespace System.Net.Http.Headers /// true if the collection contains the header; otherwise, false. public bool Contains(string headerName) => _headers is HttpHeaders headers && - HeaderDescriptor.TryGet(headerName, out HeaderDescriptor descriptor) && + headers.TryGetHeaderDescriptor(headerName, out HeaderDescriptor descriptor) && headers.TryGetHeaderValue(descriptor, out _); /// Gets the values for the specified header name. @@ -62,7 +62,7 @@ public HeaderStringValues this[string headerName] public bool TryGetValues(string headerName, out HeaderStringValues values) { if (_headers is HttpHeaders headers && - HeaderDescriptor.TryGet(headerName, out HeaderDescriptor descriptor) && + headers.TryGetHeaderDescriptor(headerName, out HeaderDescriptor descriptor) && headers.TryGetHeaderValue(descriptor, out object? info)) { HttpHeaders.GetStoreValuesAsStringOrStringArray(descriptor, info, out string? singleValue, out string[]? multiValue); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ObjectCollection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ObjectCollection.cs index e7b3c4e9522389..2486c55638697c 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ObjectCollection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/Headers/ObjectCollection.cs @@ -94,8 +94,9 @@ public void Clear() } public bool Contains(T item) => - ReferenceEquals(item, _items) || - (_size != 0 && _items is T[] items && Array.IndexOf(items, item, 0, _size) != -1); + _size <= 0 ? false : + _items is T o ? o.Equals(item) : + _items is T[] items && Array.IndexOf(items, item, 0, _size) != -1; public void CopyTo(T[] array, int arrayIndex) { @@ -120,14 +121,16 @@ public void CopyTo(T[] array, int arrayIndex) public bool Remove(T item) { - if (ReferenceEquals(_items, item)) + if (_items is T o) { - _items = null; - _size = 0; - return true; + if (o.Equals(item)) + { + _items = null; + _size = 0; + return true; + } } - - if (_items is T[] items) + else if (_items is T[] items) { int index = Array.IndexOf(items, item, 0, _size); if (index != -1) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.Android.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.Android.cs deleted file mode 100644 index 95face9fcdc1bb..00000000000000 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.Android.cs +++ /dev/null @@ -1,138 +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; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Security; -using System.Reflection; -using System.Runtime.Versioning; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; - -namespace System.Net.Http -{ - public partial class HttpClientHandler : HttpMessageHandler - { - private static MethodInfo? _nativeHandlerMethod; - - private const string NativeHandlerType = "Xamarin.Android.Net.AndroidMessageHandler"; - private const string AssemblyName = "Mono.Android"; - - [DynamicDependency("get_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] - private ICredentials? GetDefaultProxyCredentials() => (ICredentials?)InvokeNativeHandlerMethod("get_DefaultProxyCredentials"); - - [DynamicDependency("set_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] - private void SetDefaultProxyCredentials(ICredentials? value) => InvokeNativeHandlerMethod("set_DefaultProxyCredentials", value); - - [DynamicDependency("get_MaxConnectionsPerServer", NativeHandlerType, AssemblyName)] - private int GetMaxConnectionsPerServer() => (int)InvokeNativeHandlerMethod("get_MaxConnectionsPerServer"); - - [DynamicDependency("set_MaxConnectionsPerServer", NativeHandlerType, AssemblyName)] - private void SetMaxConnectionsPerServer(int value) => InvokeNativeHandlerMethod("set_MaxConnectionsPerServer", value); - - [DynamicDependency("get_MaxResponseHeadersLength", NativeHandlerType, AssemblyName)] - private int GetMaxResponseHeadersLength() => (int)InvokeNativeHandlerMethod("get_MaxResponseHeadersLength"); - - [DynamicDependency("set_MaxResponseHeadersLength", NativeHandlerType, AssemblyName)] - private void SetMaxResponseHeadersLength(int value) => InvokeNativeHandlerMethod("set_MaxResponseHeadersLength", value); - - [DynamicDependency("get_ClientCertificateOptions", NativeHandlerType, AssemblyName)] - private ClientCertificateOption GetClientCertificateOptions() => (ClientCertificateOption)InvokeNativeHandlerMethod("get_ClientCertificateOptions"); - - [DynamicDependency("set_ClientCertificateOptions", NativeHandlerType, AssemblyName)] - private void SetClientCertificateOptions(ClientCertificateOption value) => InvokeNativeHandlerMethod("set_ClientCertificateOptions", value); - - [DynamicDependency("get_ClientCertificates", NativeHandlerType, AssemblyName)] - private X509CertificateCollection GetClientCertificates() => (X509CertificateCollection)InvokeNativeHandlerMethod("get_ClientCertificates"); - - [DynamicDependency("get_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] - private bool GetCheckCertificateRevocationList() => (bool)InvokeNativeHandlerMethod("get_CheckCertificateRevocationList"); - - [DynamicDependency("set_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] - private void SetCheckCertificateRevocationList(bool value) => InvokeNativeHandlerMethod("set_CheckCertificateRevocationList", value); - - [DynamicDependency("get_SslProtocols", NativeHandlerType, AssemblyName)] - private SslProtocols GetSslProtocols() => (SslProtocols)InvokeNativeHandlerMethod("get_SslProtocols"); - - [DynamicDependency("set_SslProtocols", NativeHandlerType, AssemblyName)] - private void SetSslProtocols(SslProtocols value) => InvokeNativeHandlerMethod("set_SslProtocols", value); - - [DynamicDependency("get_Properties", NativeHandlerType, AssemblyName)] - private IDictionary GetProperties() => (IDictionary)InvokeNativeHandlerMethod("get_Properties"); - - [DynamicDependency("get_SupportsAutomaticDecompression", NativeHandlerType, AssemblyName)] - private bool GetSupportsAutomaticDecompression() => (bool)InvokeNativeHandlerMethod("get_SupportsAutomaticDecompression"); - - [DynamicDependency("get_SupportsProxy", NativeHandlerType, AssemblyName)] - private bool GetSupportsProxy() => (bool)InvokeNativeHandlerMethod("get_SupportsProxy"); - - [DynamicDependency("get_SupportsRedirectConfiguration", NativeHandlerType, AssemblyName)] - private bool GetSupportsRedirectConfiguration() => (bool)InvokeNativeHandlerMethod("get_SupportsRedirectConfiguration"); - - [DynamicDependency("get_MaxAutomaticRedirections", NativeHandlerType, AssemblyName)] - private int GetMaxAutomaticRedirections() => (int)InvokeNativeHandlerMethod("get_MaxAutomaticRedirections"); - - [DynamicDependency("set_MaxAutomaticRedirections", NativeHandlerType, AssemblyName)] - private void SetMaxAutomaticRedirections(int value) => InvokeNativeHandlerMethod("set_MaxAutomaticRedirections", value); - - [DynamicDependency("get_PreAuthenticate", NativeHandlerType, AssemblyName)] - private bool GetPreAuthenticate() => (bool)InvokeNativeHandlerMethod("get_PreAuthenticate"); - - [DynamicDependency("set_PreAuthenticate", NativeHandlerType, AssemblyName)] - private void SetPreAuthenticate(bool value) => InvokeNativeHandlerMethod("set_PreAuthenticate", value); - - [DynamicDependency("get_UseProxy", NativeHandlerType, AssemblyName)] - private bool GetUseProxy() => (bool)InvokeNativeHandlerMethod("get_UseProxy"); - - [DynamicDependency("set_UseProxy", NativeHandlerType, AssemblyName)] - private void SetUseProxy(bool value) => InvokeNativeHandlerMethod("set_UseProxy", value); - - [DynamicDependency("get_Proxy", NativeHandlerType, AssemblyName)] - private IWebProxy GetProxy() => (IWebProxy)InvokeNativeHandlerMethod("get_Proxy"); - - [DynamicDependency("set_Proxy", NativeHandlerType, AssemblyName)] - private void SetProxy(IWebProxy value) => InvokeNativeHandlerMethod("set_Proxy", value); - - [DynamicDependency("get_AutomaticDecompression", NativeHandlerType, AssemblyName)] - private DecompressionMethods GetAutomaticDecompression() => (DecompressionMethods)InvokeNativeHandlerMethod("get_AutomaticDecompression"); - - [DynamicDependency("set_AutomaticDecompression", NativeHandlerType, AssemblyName)] - private void SetAutomaticDecompression(DecompressionMethods value) => InvokeNativeHandlerMethod("set_AutomaticDecompression", value); - - [DynamicDependency("get_UseCookies", NativeHandlerType, AssemblyName)] - private bool GetUseCookies() => (bool)InvokeNativeHandlerMethod("get_UseCookies"); - - [DynamicDependency("set_UseCookies", NativeHandlerType, AssemblyName)] - private void SetUseCookies(bool value) => InvokeNativeHandlerMethod("set_UseCookies", value); - - [DynamicDependency("get_CookieContainer", NativeHandlerType, AssemblyName)] - private CookieContainer GetCookieContainer() => (CookieContainer)InvokeNativeHandlerMethod("get_CookieContainer"); - - [DynamicDependency("set_CookieContainer", NativeHandlerType, AssemblyName)] - private void SetCookieContainer(CookieContainer value) => InvokeNativeHandlerMethod("set_CookieContainer", value); - - [DynamicDependency("get_AllowAutoRedirect", NativeHandlerType, AssemblyName)] - private bool GetAllowAutoRedirect() => (bool)InvokeNativeHandlerMethod("get_AllowAutoRedirect"); - - [DynamicDependency("set_AllowAutoRedirect", NativeHandlerType, AssemblyName)] - private void SetAllowAutoRedirect(bool value) => InvokeNativeHandlerMethod("set_AllowAutoRedirect", value); - - [DynamicDependency("get_Credentials", NativeHandlerType, AssemblyName)] - private ICredentials GetCredentials() => (ICredentials)InvokeNativeHandlerMethod("get_Credentials"); - - [DynamicDependency("set_Credentials", NativeHandlerType, AssemblyName)] - private void SetCredentials(ICredentials? value) => InvokeNativeHandlerMethod("set_Credentials", value); - - private HttpMessageHandler CreateNativeHandler() - { - if (_nativeHandlerMethod == null) - { - Type? androidEnv = Type.GetType("Android.Runtime.AndroidEnvironment, Mono.Android"); - _nativeHandlerMethod = androidEnv!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - } - - return (HttpMessageHandler)_nativeHandlerMethod!.Invoke(null, null)!; - } - } -} \ No newline at end of file diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.tvOS.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs similarity index 81% rename from src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.tvOS.cs rename to src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs index 8add42ba9752ae..d14bbbf2799cfa 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.tvOS.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.InvokeNativeHandler.cs @@ -15,8 +15,25 @@ public partial class HttpClientHandler : HttpMessageHandler { private static MethodInfo? _nativeHandlerMethod; +#if TARGET_ANDROID + private const string NativeHandlerType = "Xamarin.Android.Net.AndroidMessageHandler"; + private const string AssemblyName = "Mono.Android"; + private const string GetHttpMessageHandlerType = "Android.Runtime.AndroidEnvironment, Mono.Android"; +#elif TARGET_IOS private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.TVOS"; + private const string AssemblyName = "Microsoft.iOS"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.iOS"; +#elif TARGET_MACCATALYST + private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; + private const string AssemblyName = "Microsoft.MacCatalyst"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.MacCatalyst"; +#elif TARGET_TVOS + private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; + private const string AssemblyName = "Microsoft.tvOS"; + private const string GetHttpMessageHandlerType = "ObjCRuntime.RuntimeOptions, Microsoft.tvOS"; +#else +#error Unknown target +#endif [DynamicDependency("get_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] private ICredentials? GetDefaultProxyCredentials() => (ICredentials?)InvokeNativeHandlerMethod("get_DefaultProxyCredentials"); @@ -45,6 +62,12 @@ public partial class HttpClientHandler : HttpMessageHandler [DynamicDependency("get_ClientCertificates", NativeHandlerType, AssemblyName)] private X509CertificateCollection GetClientCertificates() => (X509CertificateCollection)InvokeNativeHandlerMethod("get_ClientCertificates"); + [DynamicDependency("get_ServerCertificateCustomValidationCallback", NativeHandlerType, AssemblyName)] + private Func GetServerCertificateCustomValidationCallback() => (Func)InvokeNativeHandlerMethod("get_ServerCertificateCustomValidationCallback"); + + [DynamicDependency("set_ServerCertificateCustomValidationCallback", NativeHandlerType, AssemblyName)] + private void SetServerCertificateCustomValidationCallback(Func? value) => InvokeNativeHandlerMethod("set_ServerCertificateCustomValidationCallback", value); + [DynamicDependency("get_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] private bool GetCheckCertificateRevocationList() => (bool)InvokeNativeHandlerMethod("get_CheckCertificateRevocationList"); @@ -127,7 +150,7 @@ private HttpMessageHandler CreateNativeHandler() { if (_nativeHandlerMethod == null) { - Type? runtimeOptions = Type.GetType("ObjCRuntime.RuntimeOptions, Xamarin.TVOS"); + Type? runtimeOptions = Type.GetType(GetHttpMessageHandlerType); _nativeHandlerMethod = runtimeOptions!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs index e6168b48190ba6..2284b33b80a719 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.AnyMobile.cs @@ -426,7 +426,7 @@ public X509CertificateCollection ClientCertificates { if (IsNativeHandlerEnabled) { - throw new PlatformNotSupportedException(); + return GetServerCertificateCustomValidationCallback(); } else { @@ -437,7 +437,7 @@ public X509CertificateCollection ClientCertificates { if (IsNativeHandlerEnabled) { - throw new PlatformNotSupportedException(); + SetServerCertificateCustomValidationCallback(value); } else { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.MacCatalyst.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.MacCatalyst.cs deleted file mode 100644 index 182c6b041ec909..00000000000000 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.MacCatalyst.cs +++ /dev/null @@ -1,137 +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; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Security; -using System.Reflection; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; - -namespace System.Net.Http -{ - public partial class HttpClientHandler : HttpMessageHandler - { - private static MethodInfo? _nativeHandlerMethod; - - private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.MacCatalyst"; - - [DynamicDependency("get_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] - private ICredentials? GetDefaultProxyCredentials() => (ICredentials?)InvokeNativeHandlerMethod("get_DefaultProxyCredentials"); - - [DynamicDependency("set_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] - private void SetDefaultProxyCredentials(ICredentials? value) => InvokeNativeHandlerMethod("set_DefaultProxyCredentials", value); - - [DynamicDependency("get_MaxConnectionsPerServer", NativeHandlerType, AssemblyName)] - private int GetMaxConnectionsPerServer() => (int)InvokeNativeHandlerMethod("get_MaxConnectionsPerServer"); - - [DynamicDependency("set_MaxConnectionsPerServer", NativeHandlerType, AssemblyName)] - private void SetMaxConnectionsPerServer(int value) => InvokeNativeHandlerMethod("set_MaxConnectionsPerServer", value); - - [DynamicDependency("get_MaxResponseHeadersLength", NativeHandlerType, AssemblyName)] - private int GetMaxResponseHeadersLength() => (int)InvokeNativeHandlerMethod("get_MaxResponseHeadersLength"); - - [DynamicDependency("set_MaxResponseHeadersLength", NativeHandlerType, AssemblyName)] - private void SetMaxResponseHeadersLength(int value) => InvokeNativeHandlerMethod("set_MaxResponseHeadersLength", value); - - [DynamicDependency("get_ClientCertificateOptions", NativeHandlerType, AssemblyName)] - private ClientCertificateOption GetClientCertificateOptions() => (ClientCertificateOption)InvokeNativeHandlerMethod("get_ClientCertificateOptions"); - - [DynamicDependency("set_ClientCertificateOptions", NativeHandlerType, AssemblyName)] - private void SetClientCertificateOptions(ClientCertificateOption value) => InvokeNativeHandlerMethod("set_ClientCertificateOptions", value); - - [DynamicDependency("get_ClientCertificates", NativeHandlerType, AssemblyName)] - private X509CertificateCollection GetClientCertificates() => (X509CertificateCollection)InvokeNativeHandlerMethod("get_ClientCertificates"); - - [DynamicDependency("get_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] - private bool GetCheckCertificateRevocationList() => (bool)InvokeNativeHandlerMethod("get_CheckCertificateRevocationList"); - - [DynamicDependency("set_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] - private void SetCheckCertificateRevocationList(bool value) => InvokeNativeHandlerMethod("set_CheckCertificateRevocationList", value); - - [DynamicDependency("get_SslProtocols", NativeHandlerType, AssemblyName)] - private SslProtocols GetSslProtocols() => (SslProtocols)InvokeNativeHandlerMethod("get_SslProtocols"); - - [DynamicDependency("set_SslProtocols", NativeHandlerType, AssemblyName)] - private void SetSslProtocols(SslProtocols value) => InvokeNativeHandlerMethod("set_SslProtocols", value); - - [DynamicDependency("get_Properties", NativeHandlerType, AssemblyName)] - private IDictionary GetProperties() => (IDictionary)InvokeNativeHandlerMethod("get_Properties"); - - [DynamicDependency("get_SupportsAutomaticDecompression", NativeHandlerType, AssemblyName)] - private bool GetSupportsAutomaticDecompression() => (bool)InvokeNativeHandlerMethod("get_SupportsAutomaticDecompression"); - - [DynamicDependency("get_SupportsProxy", NativeHandlerType, AssemblyName)] - private bool GetSupportsProxy() => (bool)InvokeNativeHandlerMethod("get_SupportsProxy"); - - [DynamicDependency("get_SupportsRedirectConfiguration", NativeHandlerType, AssemblyName)] - private bool GetSupportsRedirectConfiguration() => (bool)InvokeNativeHandlerMethod("get_SupportsRedirectConfiguration"); - - [DynamicDependency("get_AutomaticDecompression", NativeHandlerType, AssemblyName)] - private DecompressionMethods GetAutomaticDecompression() => (DecompressionMethods)InvokeNativeHandlerMethod("get_AutomaticDecompression"); - - [DynamicDependency("set_AutomaticDecompression", NativeHandlerType, AssemblyName)] - private void SetAutomaticDecompression(DecompressionMethods value) => InvokeNativeHandlerMethod("set_AutomaticDecompression", value); - - [DynamicDependency("get_UseProxy", NativeHandlerType, AssemblyName)] - private bool GetUseProxy() => (bool)InvokeNativeHandlerMethod("get_UseProxy"); - - [DynamicDependency("set_UseProxy", NativeHandlerType, AssemblyName)] - private void SetUseProxy(bool value) => InvokeNativeHandlerMethod("set_UseProxy", value); - - [DynamicDependency("get_Proxy", NativeHandlerType, AssemblyName)] - private IWebProxy GetProxy() => (IWebProxy)InvokeNativeHandlerMethod("get_Proxy"); - - [DynamicDependency("set_Proxy", NativeHandlerType, AssemblyName)] - private void SetProxy(IWebProxy value) => InvokeNativeHandlerMethod("set_Proxy", value); - - [DynamicDependency("get_PreAuthenticate", NativeHandlerType, AssemblyName)] - private bool GetPreAuthenticate() => (bool)InvokeNativeHandlerMethod("get_PreAuthenticate"); - - [DynamicDependency("set_PreAuthenticate", NativeHandlerType, AssemblyName)] - private void SetPreAuthenticate(bool value) => InvokeNativeHandlerMethod("set_PreAuthenticate", value); - - [DynamicDependency("get_MaxAutomaticRedirections", NativeHandlerType, AssemblyName)] - private int GetMaxAutomaticRedirections() => (int)InvokeNativeHandlerMethod("get_MaxAutomaticRedirections"); - - [DynamicDependency("set_MaxAutomaticRedirections", NativeHandlerType, AssemblyName)] - private void SetMaxAutomaticRedirections(int value) => InvokeNativeHandlerMethod("set_MaxAutomaticRedirections", value); - - [DynamicDependency("get_UseCookies", NativeHandlerType, AssemblyName)] - private bool GetUseCookies() => (bool)InvokeNativeHandlerMethod("get_UseCookies"); - - [DynamicDependency("set_UseCookies", NativeHandlerType, AssemblyName)] - private void SetUseCookies(bool value) => InvokeNativeHandlerMethod("set_UseCookies", value); - - [DynamicDependency("get_CookieContainer", NativeHandlerType, AssemblyName)] - private CookieContainer GetCookieContainer() => (CookieContainer)InvokeNativeHandlerMethod("get_CookieContainer"); - - [DynamicDependency("set_CookieContainer", NativeHandlerType, AssemblyName)] - private void SetCookieContainer(CookieContainer value) => InvokeNativeHandlerMethod("set_CookieContainer", value); - - [DynamicDependency("get_AllowAutoRedirect", NativeHandlerType, AssemblyName)] - private bool GetAllowAutoRedirect() => (bool)InvokeNativeHandlerMethod("get_AllowAutoRedirect"); - - [DynamicDependency("set_AllowAutoRedirect", NativeHandlerType, AssemblyName)] - private void SetAllowAutoRedirect(bool value) => InvokeNativeHandlerMethod("set_AllowAutoRedirect", value); - - [DynamicDependency("get_Credentials", NativeHandlerType, AssemblyName)] - private ICredentials GetCredentials() => (ICredentials)InvokeNativeHandlerMethod("get_Credentials"); - - [DynamicDependency("set_Credentials", NativeHandlerType, AssemblyName)] - private void SetCredentials(ICredentials? value) => InvokeNativeHandlerMethod("set_Credentials", value); - - private HttpMessageHandler CreateNativeHandler() - { - if (_nativeHandlerMethod == null) - { - Type? runtimeOptions = Type.GetType("ObjCRuntime.RuntimeOptions, Xamarin.MacCatalyst"); - _nativeHandlerMethod = runtimeOptions!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - } - - return (HttpMessageHandler)_nativeHandlerMethod!.Invoke(null, null)!; - } - } -} \ No newline at end of file diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.iOS.cs b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.iOS.cs deleted file mode 100644 index 915c1c99ec6104..00000000000000 --- a/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.iOS.cs +++ /dev/null @@ -1,137 +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; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Security; -using System.Reflection; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; - -namespace System.Net.Http -{ - public partial class HttpClientHandler : HttpMessageHandler - { - private static MethodInfo? _nativeHandlerMethod; - - private const string NativeHandlerType = "System.Net.Http.NSUrlSessionHandler"; - private const string AssemblyName = "Xamarin.iOS"; - - [DynamicDependency("get_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] - private ICredentials? GetDefaultProxyCredentials() => (ICredentials?)InvokeNativeHandlerMethod("get_DefaultProxyCredentials"); - - [DynamicDependency("set_DefaultProxyCredentials", NativeHandlerType, AssemblyName)] - private void SetDefaultProxyCredentials(ICredentials? value) => InvokeNativeHandlerMethod("set_DefaultProxyCredentials", value); - - [DynamicDependency("get_MaxConnectionsPerServer", NativeHandlerType, AssemblyName)] - private int GetMaxConnectionsPerServer() => (int)InvokeNativeHandlerMethod("get_MaxConnectionsPerServer"); - - [DynamicDependency("set_MaxConnectionsPerServer", NativeHandlerType, AssemblyName)] - private void SetMaxConnectionsPerServer(int value) => InvokeNativeHandlerMethod("set_MaxConnectionsPerServer", value); - - [DynamicDependency("get_MaxResponseHeadersLength", NativeHandlerType, AssemblyName)] - private int GetMaxResponseHeadersLength() => (int)InvokeNativeHandlerMethod("get_MaxResponseHeadersLength"); - - [DynamicDependency("set_MaxResponseHeadersLength", NativeHandlerType, AssemblyName)] - private void SetMaxResponseHeadersLength(int value) => InvokeNativeHandlerMethod("set_MaxResponseHeadersLength", value); - - [DynamicDependency("get_ClientCertificateOptions", NativeHandlerType, AssemblyName)] - private ClientCertificateOption GetClientCertificateOptions() => (ClientCertificateOption)InvokeNativeHandlerMethod("get_ClientCertificateOptions"); - - [DynamicDependency("set_ClientCertificateOptions", NativeHandlerType, AssemblyName)] - private void SetClientCertificateOptions(ClientCertificateOption value) => InvokeNativeHandlerMethod("set_ClientCertificateOptions", value); - - [DynamicDependency("get_ClientCertificates", NativeHandlerType, AssemblyName)] - private X509CertificateCollection GetClientCertificates() => (X509CertificateCollection)InvokeNativeHandlerMethod("get_ClientCertificates"); - - [DynamicDependency("get_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] - private bool GetCheckCertificateRevocationList() => (bool)InvokeNativeHandlerMethod("get_CheckCertificateRevocationList"); - - [DynamicDependency("set_CheckCertificateRevocationList", NativeHandlerType, AssemblyName)] - private void SetCheckCertificateRevocationList(bool value) => InvokeNativeHandlerMethod("set_CheckCertificateRevocationList", value); - - [DynamicDependency("get_SslProtocols", NativeHandlerType, AssemblyName)] - private SslProtocols GetSslProtocols() => (SslProtocols)InvokeNativeHandlerMethod("get_SslProtocols"); - - [DynamicDependency("set_SslProtocols", NativeHandlerType, AssemblyName)] - private void SetSslProtocols(SslProtocols value) => InvokeNativeHandlerMethod("set_SslProtocols", value); - - [DynamicDependency("get_Properties", NativeHandlerType, AssemblyName)] - private IDictionary GetProperties() => (IDictionary)InvokeNativeHandlerMethod("get_Properties"); - - [DynamicDependency("get_SupportsAutomaticDecompression", NativeHandlerType, AssemblyName)] - private bool GetSupportsAutomaticDecompression() => (bool)InvokeNativeHandlerMethod("get_SupportsAutomaticDecompression"); - - [DynamicDependency("get_SupportsProxy", NativeHandlerType, AssemblyName)] - private bool GetSupportsProxy() => (bool)InvokeNativeHandlerMethod("get_SupportsProxy"); - - [DynamicDependency("get_AutomaticDecompression", NativeHandlerType, AssemblyName)] - private DecompressionMethods GetAutomaticDecompression() => (DecompressionMethods)InvokeNativeHandlerMethod("get_AutomaticDecompression"); - - [DynamicDependency("set_AutomaticDecompression", NativeHandlerType, AssemblyName)] - private void SetAutomaticDecompression(DecompressionMethods value) => InvokeNativeHandlerMethod("set_AutomaticDecompression", value); - - [DynamicDependency("get_UseProxy", NativeHandlerType, AssemblyName)] - private bool GetUseProxy() => (bool)InvokeNativeHandlerMethod("get_UseProxy"); - - [DynamicDependency("set_UseProxy", NativeHandlerType, AssemblyName)] - private void SetUseProxy(bool value) => InvokeNativeHandlerMethod("set_UseProxy", value); - - [DynamicDependency("get_Proxy", NativeHandlerType, AssemblyName)] - private IWebProxy GetProxy() => (IWebProxy)InvokeNativeHandlerMethod("get_Proxy"); - - [DynamicDependency("set_Proxy", NativeHandlerType, AssemblyName)] - private void SetProxy(IWebProxy value) => InvokeNativeHandlerMethod("set_Proxy", value); - - [DynamicDependency("get_PreAuthenticate", NativeHandlerType, AssemblyName)] - private bool GetPreAuthenticate() => (bool)InvokeNativeHandlerMethod("get_PreAuthenticate"); - - [DynamicDependency("set_PreAuthenticate", NativeHandlerType, AssemblyName)] - private void SetPreAuthenticate(bool value) => InvokeNativeHandlerMethod("set_PreAuthenticate", value); - - [DynamicDependency("get_MaxAutomaticRedirections", NativeHandlerType, AssemblyName)] - private int GetMaxAutomaticRedirections() => (int)InvokeNativeHandlerMethod("get_MaxAutomaticRedirections"); - - [DynamicDependency("set_MaxAutomaticRedirections", NativeHandlerType, AssemblyName)] - private void SetMaxAutomaticRedirections(int value) => InvokeNativeHandlerMethod("set_MaxAutomaticRedirections", value); - - [DynamicDependency("get_UseCookies", NativeHandlerType, AssemblyName)] - private bool GetUseCookies() => (bool)InvokeNativeHandlerMethod("get_UseCookies"); - - [DynamicDependency("get_SupportsRedirectConfiguration", NativeHandlerType, AssemblyName)] - private bool GetSupportsRedirectConfiguration() => (bool)InvokeNativeHandlerMethod("get_SupportsRedirectConfiguration"); - - [DynamicDependency("set_UseCookies", NativeHandlerType, AssemblyName)] - private void SetUseCookies(bool value) => InvokeNativeHandlerMethod("set_UseCookies", value); - - [DynamicDependency("get_CookieContainer", NativeHandlerType, AssemblyName)] - private CookieContainer GetCookieContainer() => (CookieContainer)InvokeNativeHandlerMethod("get_CookieContainer"); - - [DynamicDependency("set_CookieContainer", NativeHandlerType, AssemblyName)] - private void SetCookieContainer(CookieContainer value) => InvokeNativeHandlerMethod("set_CookieContainer", value); - - [DynamicDependency("get_AllowAutoRedirect", NativeHandlerType, AssemblyName)] - private bool GetAllowAutoRedirect() => (bool)InvokeNativeHandlerMethod("get_AllowAutoRedirect"); - - [DynamicDependency("set_AllowAutoRedirect", NativeHandlerType, AssemblyName)] - private void SetAllowAutoRedirect(bool value) => InvokeNativeHandlerMethod("set_AllowAutoRedirect", value); - - [DynamicDependency("get_Credentials", NativeHandlerType, AssemblyName)] - private ICredentials GetCredentials() => (ICredentials)InvokeNativeHandlerMethod("get_Credentials"); - - [DynamicDependency("set_Credentials", NativeHandlerType, AssemblyName)] - private void SetCredentials(ICredentials? value) => InvokeNativeHandlerMethod("set_Credentials", value); - - private HttpMessageHandler CreateNativeHandler() - { - if (_nativeHandlerMethod == null) - { - Type? runtimeOptions = Type.GetType("ObjCRuntime.RuntimeOptions, Xamarin.iOS"); - _nativeHandlerMethod = runtimeOptions!.GetMethod("GetHttpMessageHandler", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); - } - - return (HttpMessageHandler)_nativeHandlerMethod!.Invoke(null, null)!; - } - } -} \ No newline at end of file diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs index 88b3f64d0ec7a9..639e0367ba5aa7 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.cs @@ -206,7 +206,7 @@ private static async ValueTask TrySetDigestAuthToken(HttpRequestMessage re private static ValueTask InnerSendAsync(HttpRequestMessage request, bool async, bool isProxyAuth, bool doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken) { return isProxyAuth ? - pool.SendWithRetryAsync(request, async, doRequestAuth, cancellationToken) : + pool.SendWithVersionDetectionAndRetryAsync(request, async, doRequestAuth, cancellationToken) : pool.SendWithProxyAuthAsync(request, async, doRequestAuth, cancellationToken); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs index 0e354ff30cb0f3..939a29e06f393e 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/DecompressionHandler.cs @@ -6,7 +6,6 @@ using System.IO; using System.IO.Compression; using System.Net.Http.Headers; -using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -224,12 +223,203 @@ public DeflateDecompressedContent(HttpContent originalContent) { } protected override Stream GetDecompressedStream(Stream originalStream) => - // As described in RFC 2616, the deflate content-coding is actually - // the "zlib" format (RFC 1950) in combination with the "deflate" - // compression algrithm (RFC 1951). So while potentially - // counterintuitive based on naming, this needs to use ZLibStream - // rather than DeflateStream. - new ZLibStream(originalStream, CompressionMode.Decompress); + new ZLibOrDeflateStream(originalStream); + + /// Stream that wraps either or for decompression. + private sealed class ZLibOrDeflateStream : HttpBaseStream + { + // As described in RFC 2616, the deflate content-coding is the "zlib" format (RFC 1950) in combination with + // the "deflate" compression algrithm (RFC 1951). Thus, the right stream to use here is ZLibStream. However, + // some servers incorrectly interpret "deflate" to mean the raw, unwrapped deflate protocol. To account for + // that, this switches between using ZLibStream (correct) and DeflateStream (incorrect) in order to maximize + // compatibility with servers. + + private readonly PeekFirstByteReadStream _stream; + private Stream? _decompressionStream; + + public ZLibOrDeflateStream(Stream stream) => _stream = new PeekFirstByteReadStream(stream); + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _decompressionStream?.Dispose(); + _stream.Dispose(); + } + base.Dispose(disposing); + } + + public override bool CanRead => true; + public override bool CanWrite => false; + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) => throw new NotSupportedException(); + + // On the first read request, peek at the first nibble of the response. If it's an 8, use ZLibStream, otherwise + // use DeflateStream. This heuristic works because we're deciding only between raw deflate and zlib wrapped around + // deflate, in which case the first nibble will always be 8 for zlib and never be 8 for deflate. + // https://stackoverflow.com/a/37528114 provides an explanation for why. + + public override int Read(Span buffer) + { + if (_decompressionStream is null) + { + int firstByte = _stream.PeekFirstByte(); + _decompressionStream = CreateDecompressionStream(firstByte, _stream); + } + + return _decompressionStream.Read(buffer); + } + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) + { + if (_decompressionStream is null) + { + return CreateAndReadAsync(this, buffer, cancellationToken); + + static async ValueTask CreateAndReadAsync(ZLibOrDeflateStream thisRef, Memory buffer, CancellationToken cancellationToken) + { + int firstByte = await thisRef._stream.PeekFirstByteAsync(cancellationToken).ConfigureAwait(false); + thisRef._decompressionStream = CreateDecompressionStream(firstByte, thisRef._stream); + return await thisRef._decompressionStream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); + } + } + + return _decompressionStream.ReadAsync(buffer, cancellationToken); + } + + public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) + { + ValidateCopyToArguments(destination, bufferSize); + return Core(destination, bufferSize, cancellationToken); + async Task Core(Stream destination, int bufferSize, CancellationToken cancellationToken) + { + if (_decompressionStream is null) + { + int firstByte = await _stream.PeekFirstByteAsync(cancellationToken).ConfigureAwait(false); + _decompressionStream = CreateDecompressionStream(firstByte, _stream); + } + + await _decompressionStream.CopyToAsync(destination, bufferSize, cancellationToken).ConfigureAwait(false); + } + } + + private static Stream CreateDecompressionStream(int firstByte, Stream stream) => + (firstByte & 0xF) == 8 ? + new ZLibStream(stream, CompressionMode.Decompress) : + new DeflateStream(stream, CompressionMode.Decompress); + + private sealed class PeekFirstByteReadStream : HttpBaseStream + { + private readonly Stream _stream; + private byte _firstByte; + private FirstByteStatus _firstByteStatus; + + public PeekFirstByteReadStream(Stream stream) => _stream = stream; + + protected override void Dispose(bool disposing) + { + if (disposing) + { + _stream.Dispose(); + } + base.Dispose(disposing); + } + + public override bool CanRead => true; + public override bool CanWrite => false; + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken) => throw new NotSupportedException(); + + public int PeekFirstByte() + { + Debug.Assert(_firstByteStatus == FirstByteStatus.None); + + int value = _stream.ReadByte(); + if (value == -1) + { + _firstByteStatus = FirstByteStatus.Consumed; + return -1; + } + + _firstByte = (byte)value; + _firstByteStatus = FirstByteStatus.Available; + return value; + } + + public async ValueTask PeekFirstByteAsync(CancellationToken cancellationToken) + { + Debug.Assert(_firstByteStatus == FirstByteStatus.None); + + var buffer = new byte[1]; + + int bytesRead = await _stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); + if (bytesRead == 0) + { + _firstByteStatus = FirstByteStatus.Consumed; + return -1; + } + + _firstByte = buffer[0]; + _firstByteStatus = FirstByteStatus.Available; + return buffer[0]; + } + + public override int Read(Span buffer) + { + if (_firstByteStatus == FirstByteStatus.Available) + { + if (buffer.Length != 0) + { + buffer[0] = _firstByte; + _firstByteStatus = FirstByteStatus.Consumed; + return 1; + } + + return 0; + } + + Debug.Assert(_firstByteStatus == FirstByteStatus.Consumed); + return _stream.Read(buffer); + } + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken) + { + if (_firstByteStatus == FirstByteStatus.Available) + { + if (buffer.Length != 0) + { + buffer.Span[0] = _firstByte; + _firstByteStatus = FirstByteStatus.Consumed; + return new ValueTask(1); + } + + return new ValueTask(0); + } + + Debug.Assert(_firstByteStatus == FirstByteStatus.Consumed); + return _stream.ReadAsync(buffer, cancellationToken); + } + + public override async Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) + { + Debug.Assert(_firstByteStatus != FirstByteStatus.None); + + ValidateCopyToArguments(destination, bufferSize); + if (_firstByteStatus == FirstByteStatus.Available) + { + await destination.WriteAsync(new byte[] { _firstByte }, cancellationToken).ConfigureAwait(false); + _firstByteStatus = FirstByteStatus.Consumed; + } + + await _stream.CopyToAsync(destination, bufferSize, cancellationToken).ConfigureAwait(false); + } + + private enum FirstByteStatus : byte + { + None = 0, + Available = 1, + Consumed = 2 + } + } + } } private sealed class BrotliDecompressedContent : DecompressedContent diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index b6a33b2f28012a..b632761f1688c1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -915,6 +915,8 @@ private void ProcessPingFrame(FrameHeader frameHeader) ReadOnlySpan pingContent = _incomingBuffer.ActiveSpan.Slice(0, FrameHeader.PingLength); long pingContentLong = BinaryPrimitives.ReadInt64BigEndian(pingContent); + if (NetEventSource.Log.IsEnabled()) Trace($"Received PING frame, content:{pingContentLong} ack: {frameHeader.AckFlag}"); + if (frameHeader.AckFlag) { ProcessPingAck(pingContentLong); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamWindowManager.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamWindowManager.cs index 4a1f7ee6b568a2..a9314d14ab174d 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamWindowManager.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2StreamWindowManager.cs @@ -213,6 +213,7 @@ internal void OnDataOrHeadersReceived(Http2Connection connection) // Send a PING _pingCounter--; + if (NetEventSource.Log.IsEnabled()) connection.Trace($"[FlowControl] Sending RTT PING with payload {_pingCounter}"); connection.LogExceptions(connection.SendPingAsync(_pingCounter, isAck: false)); _pingSentTimestamp = now; _state = State.PingSent; @@ -223,6 +224,7 @@ internal void OnPingAckReceived(long payload, Http2Connection connection) { if (_state != State.PingSent && _state != State.TerminatingMayReceivePingAck) { + if (NetEventSource.Log.IsEnabled()) connection.Trace($"[FlowControl] Unexpected PING ACK in state {_state}"); ThrowProtocolError(); } @@ -236,7 +238,10 @@ internal void OnPingAckReceived(long payload, Http2Connection connection) Debug.Assert(payload < 0); if (_pingCounter != payload) + { + if (NetEventSource.Log.IsEnabled()) connection.Trace($"[FlowControl] Unexpected RTT PING ACK payload {payload}, should be {_pingCounter}."); ThrowProtocolError(); + } RefreshRtt(connection); _state = State.Waiting; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index aa5f7541ba841b..f2beed2030f2f5 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -84,6 +84,7 @@ public void Dispose() if (!_disposed) { _disposed = true; + AbortStream(); _stream.Dispose(); DisposeSyncHelper(); } @@ -94,6 +95,7 @@ public async ValueTask DisposeAsync() if (!_disposed) { _disposed = true; + AbortStream(); await _stream.DisposeAsync().ConfigureAwait(false); DisposeSyncHelper(); } @@ -365,6 +367,9 @@ private async Task SendContentAsync(HttpContent content, CancellationToken cance await content.CopyToAsync(writeStream, null, cancellationToken).ConfigureAwait(false); } + // Set to 0 to recognize that the whole request body has been sent and therefore there's no need to abort write side in case of a premature disposal. + _requestContentLengthRemaining = 0; + if (_sendBuffer.ActiveLength != 0) { // Our initial send buffer, which has our headers, is normally sent out on the first write to the Http3WriteStream. @@ -1046,6 +1051,14 @@ private int ReadResponseContent(HttpResponseMessage response, Span buffer) _responseDataPayloadRemaining -= copyLen; _recvBuffer.Discard(copyLen); buffer = buffer.Slice(copyLen); + + // Stop, if we've reached the end of a data frame and start of the next data frame is not buffered yet + // Waiting for the next data frame may cause a hang, e.g. in echo scenario + // TODO: this is inefficient if data is already available in transport + if (_responseDataPayloadRemaining == 0 && _recvBuffer.ActiveLength == 0) + { + break; + } } else { @@ -1063,10 +1076,9 @@ private int ReadResponseContent(HttpResponseMessage response, Span buffer) _responseDataPayloadRemaining -= bytesRead; buffer = buffer.Slice(bytesRead); - if (_responseDataPayloadRemaining == 0) - { - break; - } + // Stop, even if we are in the middle of a data frame. Waiting for the next data may cause a hang + // TODO: this is inefficient if data is already available in transport + break; } } @@ -1108,6 +1120,14 @@ private async ValueTask ReadResponseContentAsync(HttpResponseMessage respon _responseDataPayloadRemaining -= copyLen; _recvBuffer.Discard(copyLen); buffer = buffer.Slice(copyLen); + + // Stop, if we've reached the end of a data frame and start of the next data frame is not buffered yet + // Waiting for the next data frame may cause a hang, e.g. in echo scenario + // TODO: this is inefficient if data is already available in transport + if (_responseDataPayloadRemaining == 0 && _recvBuffer.ActiveLength == 0) + { + break; + } } else { @@ -1125,10 +1145,9 @@ private async ValueTask ReadResponseContentAsync(HttpResponseMessage respon _responseDataPayloadRemaining -= bytesRead; buffer = buffer.Slice(bytesRead); - if (_responseDataPayloadRemaining == 0) - { - break; - } + // Stop, even if we are in the middle of a data frame. Waiting for the next data may cause a hang + // TODO: this is inefficient if data is already available in transport + break; } } @@ -1217,6 +1236,20 @@ private async ValueTask ReadNextDataFrameAsync(HttpResponseMessage respons public void Trace(string message, [CallerMemberName] string? memberName = null) => _connection.Trace(StreamId, message, memberName); + private void AbortStream() + { + // If the request body isn't completed, cancel it now. + if (_requestContentLengthRemaining != 0) // 0 is used for the end of content writing, -1 is used for unknown Content-Length + { + _stream.AbortWrite((long)Http3ErrorCode.RequestCancelled); + } + // If the response body isn't completed, cancel it now. + if (_responseDataPayloadRemaining != -1) // -1 is used for EOF, 0 for consumed DATA frame payload before the next read + { + _stream.AbortRead((long)Http3ErrorCode.RequestCancelled); + } + } + // TODO: it may be possible for Http3RequestStream to implement Stream directly and avoid this allocation. private sealed class Http3ReadStream : HttpBaseStream { @@ -1240,36 +1273,42 @@ public Http3ReadStream(Http3RequestStream stream) protected override void Dispose(bool disposing) { - if (_stream != null) + Http3RequestStream? stream = Interlocked.Exchange(ref _stream, null); + if (stream is null) { - if (disposing) - { - // This will remove the stream from the connection properly. - _stream.Dispose(); - } - else - { - // We shouldn't be using a managed instance here, but don't have much choice -- we - // need to remove the stream from the connection's GOAWAY collection. - _stream._connection.RemoveStream(_stream._stream); - _stream._connection = null!; - } + return; + } - _stream = null; - _response = null; + if (disposing) + { + // This will remove the stream from the connection properly. + stream.Dispose(); + } + else + { + // We shouldn't be using a managed instance here, but don't have much choice -- we + // need to remove the stream from the connection's GOAWAY collection. + stream._connection.RemoveStream(stream._stream); + stream._connection = null!; } + _response = null; + base.Dispose(disposing); } public override async ValueTask DisposeAsync() { - if (_stream != null) + Http3RequestStream? stream = Interlocked.Exchange(ref _stream, null); + if (stream is null) { - await _stream.DisposeAsync().ConfigureAwait(false); - _stream = null!; + return; } + await stream.DisposeAsync().ConfigureAwait(false); + + _response = null; + await base.DisposeAsync().ConfigureAwait(false); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs index 787b89c8bd7a29..c51adc80d5c301 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs @@ -413,11 +413,12 @@ private object SyncObj // we will remove it from the list of available connections, if it is present there. // If not, then it must be unavailable at the moment; we will detect this and ensure it is not added back to the available pool. - private static HttpRequestException GetVersionException(HttpRequestMessage request, int desiredVersion) + [DoesNotReturn] + private static void ThrowGetVersionException(HttpRequestMessage request, int desiredVersion) { Debug.Assert(desiredVersion == 2 || desiredVersion == 3); - return new HttpRequestException(SR.Format(SR.net_http_requested_version_cannot_establish, request.Version, request.VersionPolicy, desiredVersion)); + throw new HttpRequestException(SR.Format(SR.net_http_requested_version_cannot_establish, request.Version, request.VersionPolicy, desiredVersion)); } private bool CheckExpirationOnGet(HttpConnectionBase connection) @@ -887,144 +888,118 @@ private async ValueTask GetHttp3ConnectionAsync(HttpRequestMess [SupportedOSPlatform("windows")] [SupportedOSPlatform("linux")] [SupportedOSPlatform("macos")] - private async ValueTask TrySendUsingHttp3Async(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + private async ValueTask TrySendUsingHttp3Async(HttpRequestMessage request, bool async, CancellationToken cancellationToken) { - if (_http3Enabled && (request.Version.Major >= 3 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure))) + // Loop in case we get a 421 and need to send the request to a different authority. + while (true) { - // Loop in case we get a 421 and need to send the request to a different authority. - while (true) - { - HttpAuthority? authority = _http3Authority; - - // If H3 is explicitly requested, assume prenegotiated H3. - if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - authority = authority ?? _originAuthority; - } + HttpAuthority? authority = _http3Authority; - if (authority == null) - { - break; - } - - if (IsAltSvcBlocked(authority)) - { - throw GetVersionException(request, 3); - } - - Http3Connection connection = await GetHttp3ConnectionAsync(request, authority, cancellationToken).ConfigureAwait(false); - HttpResponseMessage response = await connection.SendAsync(request, async, cancellationToken).ConfigureAwait(false); - - // If an Alt-Svc authority returns 421, it means it can't actually handle the request. - // An authority is supposed to be able to handle ALL requests to the origin, so this is a server bug. - // In this case, we blocklist the authority and retry the request at the origin. - if (response.StatusCode == HttpStatusCode.MisdirectedRequest && connection.Authority != _originAuthority) - { - response.Dispose(); - BlocklistAuthority(connection.Authority); - continue; - } - - return response; + // If H3 is explicitly requested, assume prenegotiated H3. + if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + authority ??= _originAuthority; } - } - - return null; - } - // Returns null if HTTP2 cannot be used. - private async ValueTask TrySendUsingHttp2Async(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - // Send using HTTP/2 if we can. - if (_http2Enabled && (request.Version.Major >= 2 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) && - // If the connection is not secured and downgrade is possible, prefer HTTP/1.1. - (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower || IsSecure)) - { - Http2Connection? connection = await GetHttp2ConnectionAsync(request, async, cancellationToken).ConfigureAwait(false); - if (connection is null) + if (authority == null) { - Debug.Assert(!_http2Enabled); return null; } - return await connection.SendAsync(request, async, cancellationToken).ConfigureAwait(false); - } - - return null; - } - - private async ValueTask SendUsingHttp11Async(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - HttpConnection connection = await GetHttp11ConnectionAsync(request, async, cancellationToken).ConfigureAwait(false); - - // In case we are doing Windows (i.e. connection-based) auth, we need to ensure that we hold on to this specific connection while auth is underway. - connection.Acquire(); - try - { - return await SendWithNtConnectionAuthAsync(connection, request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); - } - finally - { - connection.Release(); - } - } + if (IsAltSvcBlocked(authority)) + { + ThrowGetVersionException(request, 3); + } - private async ValueTask DetermineVersionAndSendAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) - { - HttpResponseMessage? response; + Http3Connection connection = await GetHttp3ConnectionAsync(request, authority, cancellationToken).ConfigureAwait(false); + HttpResponseMessage response = await connection.SendAsync(request, async, cancellationToken).ConfigureAwait(false); - if (IsHttp3Supported()) - { - response = await TrySendUsingHttp3Async(request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); - if (response is not null) + // If an Alt-Svc authority returns 421, it means it can't actually handle the request. + // An authority is supposed to be able to handle ALL requests to the origin, so this is a server bug. + // In this case, we blocklist the authority and retry the request at the origin. + if (response.StatusCode == HttpStatusCode.MisdirectedRequest && connection.Authority != _originAuthority) { - return response; + response.Dispose(); + BlocklistAuthority(connection.Authority); + continue; } - } - - // We cannot use HTTP/3. Do not continue if downgrade is not allowed. - if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - throw GetVersionException(request, 3); - } - response = await TrySendUsingHttp2Async(request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); - if (response is not null) - { return response; } - - // We cannot use HTTP/2. Do not continue if downgrade is not allowed. - if (request.Version.Major >= 2 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) - { - throw GetVersionException(request, 2); - } - - return await SendUsingHttp11Async(request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); } - private async ValueTask SendAndProcessAltSvcAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + /// Check for the Alt-Svc header, to upgrade to HTTP/3. + private void ProcessAltSvc(HttpResponseMessage response) { - HttpResponseMessage response = await DetermineVersionAndSendAsync(request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); - - // Check for the Alt-Svc header, to upgrade to HTTP/3. if (_altSvcEnabled && response.Headers.TryGetValues(KnownHeaders.AltSvc.Descriptor, out IEnumerable? altSvcHeaderValues)) { HandleAltSvc(altSvcHeaderValues, response.Headers.Age); } - - return response; } - public async ValueTask SendWithRetryAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) + public async ValueTask SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) { + // Loop on connection failures (or other problems like version downgrade) and retry if possible. int retryCount = 0; while (true) { - // Loop on connection failures (or other problems like version downgrade) and retry if possible. try { - return await SendAndProcessAltSvcAsync(request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); + HttpResponseMessage? response = null; + + // Use HTTP/3 if possible. + if (IsHttp3Supported() && // guard to enable trimming HTTP/3 support + _http3Enabled && + (request.Version.Major >= 3 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure))) + { + response = await TrySendUsingHttp3Async(request, async, cancellationToken).ConfigureAwait(false); + } + + if (response is null) + { + // We could not use HTTP/3. Do not continue if downgrade is not allowed. + if (request.Version.Major >= 3 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + ThrowGetVersionException(request, 3); + } + + // Use HTTP/2 if possible. + if (_http2Enabled && + (request.Version.Major >= 2 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) && + (request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower || IsSecure)) // prefer HTTP/1.1 if connection is not secured and downgrade is possible + { + Http2Connection? connection = await GetHttp2ConnectionAsync(request, async, cancellationToken).ConfigureAwait(false); + Debug.Assert(connection is not null || !_http2Enabled); + if (connection is not null) + { + response = await connection.SendAsync(request, async, cancellationToken).ConfigureAwait(false); + } + } + + if (response is null) + { + // We could not use HTTP/2. Do not continue if downgrade is not allowed. + if (request.Version.Major >= 2 && request.VersionPolicy != HttpVersionPolicy.RequestVersionOrLower) + { + ThrowGetVersionException(request, 2); + } + + // Use HTTP/1.x. + HttpConnection connection = await GetHttp11ConnectionAsync(request, async, cancellationToken).ConfigureAwait(false); + connection.Acquire(); // In case we are doing Windows (i.e. connection-based) auth, we need to ensure that we hold on to this specific connection while auth is underway. + try + { + response = await SendWithNtConnectionAuthAsync(connection, request, async, doRequestAuth, cancellationToken).ConfigureAwait(false); + } + finally + { + connection.Release(); + } + } + } + + ProcessAltSvc(response); + return response; } catch (HttpRequestException e) when (e.AllowRetry == RequestRetryType.RetryOnConnectionFailure) { @@ -1332,7 +1307,7 @@ public ValueTask SendWithProxyAuthAsync(HttpRequestMessage return AuthenticationHelper.SendWithProxyAuthAsync(request, _proxyUri!, async, ProxyCredentials, doRequestAuth, this, cancellationToken); } - return SendWithRetryAsync(request, async, doRequestAuth, cancellationToken); + return SendWithVersionDetectionAndRetryAsync(request, async, doRequestAuth, cancellationToken); } public ValueTask SendAsync(HttpRequestMessage request, bool async, bool doRequestAuth, CancellationToken cancellationToken) @@ -2004,7 +1979,12 @@ public bool CleanCacheAndDisposeIfUnused() } // Dispose the stale connections outside the pool lock, to avoid holding the lock too long. - toDispose?.ForEach(c => c.Dispose()); + // Dispose them asynchronously to not to block the caller on closing the SslStream or NetworkStream. + if (toDispose is not null) + { + Task.Factory.StartNew(static s => ((List)s!).ForEach(c => c.Dispose()), toDispose, + CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + } // Pool is active. Should not be removed. return false; @@ -2024,7 +2004,8 @@ static int ScavengeConnectionList(List list, ref List? if (freeIndex < list.Count) { // We know the connection at freeIndex is unusable, so dispose of it. - toDispose ??= new List { list[freeIndex] }; + toDispose ??= new List(); + toDispose.Add(list[freeIndex]); // Find the first item after the one to be removed that should be kept. int current = freeIndex + 1; diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs index e257cb4c3e692f..f118d151c692ae 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs @@ -462,7 +462,7 @@ private void SetCleaningTimer(TimeSpan timeout) { try { - _cleaningTimer!.Change(timeout, timeout); + _cleaningTimer!.Change(timeout, Timeout.InfiniteTimeSpan); _timerIsRunning = timeout != Timeout.InfiniteTimeSpan; } catch (ObjectDisposedException) @@ -492,13 +492,10 @@ private void RemoveStalePools() } } - // Stop running the timer if we don't have any pools to clean up. + // Restart the timer if we have any pools to clean up. lock (SyncObj) { - if (_pools.IsEmpty) - { - SetCleaningTimer(Timeout.InfiniteTimeSpan); - } + SetCleaningTimer(!_pools.IsEmpty ? _cleanPoolTimeout : Timeout.InfiniteTimeSpan); } // NOTE: There is a possible race condition with regards to a pool getting cleaned up at the same diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs index 410acc16b69ad4..64476aa0286631 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionSettings.cs @@ -75,8 +75,6 @@ public HttpConnectionSettings() allowHttp3 && allowHttp2 ? HttpVersion.Version30 : allowHttp2 ? HttpVersion.Version20 : HttpVersion.Version11; - _defaultCredentialsUsedForProxy = _proxy != null && (_proxy.Credentials == CredentialCache.DefaultCredentials || _defaultProxyCredentials == CredentialCache.DefaultCredentials); - _defaultCredentialsUsedForServer = _credentials == CredentialCache.DefaultCredentials; } /// Creates a copy of the settings but with some values normalized to suit the implementation. @@ -96,8 +94,6 @@ public HttpConnectionSettings CloneAndNormalize() _connectTimeout = _connectTimeout, _credentials = _credentials, _defaultProxyCredentials = _defaultProxyCredentials, - _defaultCredentialsUsedForProxy = _defaultCredentialsUsedForProxy, - _defaultCredentialsUsedForServer = _defaultCredentialsUsedForServer, _expect100ContinueTimeout = _expect100ContinueTimeout, _maxAutomaticRedirections = _maxAutomaticRedirections, _maxConnectionsPerServer = _maxConnectionsPerServer, @@ -123,6 +119,8 @@ public HttpConnectionSettings CloneAndNormalize() _plaintextStreamFilter = _plaintextStreamFilter, _initialHttp2StreamWindowSize = _initialHttp2StreamWindowSize, _activityHeadersPropagator = _activityHeadersPropagator, + _defaultCredentialsUsedForProxy = _proxy != null && (_proxy.Credentials == CredentialCache.DefaultCredentials || _defaultProxyCredentials == CredentialCache.DefaultCredentials), + _defaultCredentialsUsedForServer = _credentials == CredentialCache.DefaultCredentials, }; // TODO: Remove if/when QuicImplementationProvider is removed from System.Net.Quic. diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs index 547f91d3e9143b..2299a5af6840b0 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http3.cs @@ -319,6 +319,119 @@ public async Task ReservedFrameType_Throws() await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); } + [Fact] + public async Task RequestSentResponseDisposed_ThrowsOnServer() + { + byte[] data = Encoding.UTF8.GetBytes(new string('a', 1024)); + + using Http3LoopbackServer server = CreateHttp3LoopbackServer(); + + Task serverTask = Task.Run(async () => + { + using Http3LoopbackConnection connection = (Http3LoopbackConnection)await server.EstablishGenericConnectionAsync(); + using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); + HttpRequestData request = await stream.ReadRequestDataAsync(); + await stream.SendResponseHeadersAsync(); + + Stopwatch sw = Stopwatch.StartNew(); + bool hasFailed = false; + while (sw.Elapsed < TimeSpan.FromSeconds(15)) + { + try + { + await stream.SendResponseBodyAsync(data, isFinal: false); + } + catch (QuicStreamAbortedException) + { + hasFailed = true; + break; + } + } + Assert.True(hasFailed, $"Expected {nameof(QuicStreamAbortedException)}, instead ran successfully for {sw.Elapsed}"); + }); + + Task clientTask = Task.Run(async () => + { + using HttpClient client = CreateHttpClient(); + using HttpRequestMessage request = new() + { + Method = HttpMethod.Get, + RequestUri = server.Address, + Version = HttpVersion30, + VersionPolicy = HttpVersionPolicy.RequestVersionExact + }; + + var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + var stream = await response.Content.ReadAsStreamAsync(); + byte[] buffer = new byte[512]; + for (int i = 0; i < 5; ++i) + { + var count = await stream.ReadAsync(buffer); + } + + // We haven't finished reading the whole respose, but we're disposing it, which should turn into an exception on the server-side. + response.Dispose(); + await serverTask; + }); + + await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); + } + + [Fact] + public async Task RequestSendingResponseDisposed_ThrowsOnServer() + { + byte[] data = Encoding.UTF8.GetBytes(new string('a', 1024)); + + using Http3LoopbackServer server = CreateHttp3LoopbackServer(); + + Task serverTask = Task.Run(async () => + { + using Http3LoopbackConnection connection = (Http3LoopbackConnection)await server.EstablishGenericConnectionAsync(); + using Http3LoopbackStream stream = await connection.AcceptRequestStreamAsync(); + HttpRequestData request = await stream.ReadRequestDataAsync(false); + await stream.SendResponseHeadersAsync(); + + Stopwatch sw = Stopwatch.StartNew(); + bool hasFailed = false; + while (sw.Elapsed < TimeSpan.FromSeconds(15)) + { + try + { + var (frameType, payload) = await stream.ReadFrameAsync(); + Assert.Equal(Http3LoopbackStream.DataFrame, frameType); + } + catch (QuicStreamAbortedException) + { + hasFailed = true; + break; + } + } + Assert.True(hasFailed, $"Expected {nameof(QuicStreamAbortedException)}, instead ran successfully for {sw.Elapsed}"); + }); + + Task clientTask = Task.Run(async () => + { + using HttpClient client = CreateHttpClient(); + using HttpRequestMessage request = new() + { + Method = HttpMethod.Get, + RequestUri = server.Address, + Version = HttpVersion30, + VersionPolicy = HttpVersionPolicy.RequestVersionExact, + Content = new ByteAtATimeContent(60*4, Task.CompletedTask, new TaskCompletionSource(), 250) + }; + + var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + var stream = await response.Content.ReadAsStreamAsync(); + + // We haven't finished sending the whole request, but we're disposing the response, which should turn into an exception on the server-side. + response.Dispose(); + await serverTask; + }); + + await new[] { clientTask, serverTask }.WhenAllOrAnyFailed(20_000); + } + [Fact] public async Task ServerCertificateCustomValidationCallback_Succeeds() { @@ -885,7 +998,7 @@ public async Task StatusCodes_ReceiveSuccess(HttpStatusCode statusCode, bool qpa VersionPolicy = HttpVersionPolicy.RequestVersionExact }; HttpResponseMessage response = await client.SendAsync(request).WaitAsync(TimeSpan.FromSeconds(10)); - + Assert.Equal(statusCode, response.StatusCode); await serverTask; @@ -893,6 +1006,90 @@ public async Task StatusCodes_ReceiveSuccess(HttpStatusCode statusCode, bool qpa connection.Dispose(); } + [Theory] + [InlineData(1)] // frame fits into Http3RequestStream buffer + [InlineData(10)] + [InlineData(100)] // frame doesn't fit into Http3RequestStream buffer + [InlineData(1000)] + public async Task EchoServerStreaming_DifferentMessageSize_Success(int messageSize) + { + int iters = 5; + var message = new byte[messageSize]; + var readBuffer = new byte[5 * messageSize]; // bigger than message + var random = new Random(0); + + using Http3LoopbackServer server = CreateHttp3LoopbackServer(); + Http3LoopbackConnection connection = null; + Http3LoopbackStream serverStream = null; + + Task serverTask = Task.Run(async () => + { + connection = (Http3LoopbackConnection)await server.EstablishGenericConnectionAsync(); + serverStream = await connection.AcceptRequestStreamAsync(); + + HttpRequestData requestData = await serverStream.ReadRequestDataAsync(readBody: false).WaitAsync(TimeSpan.FromSeconds(30)); + + await serverStream.SendResponseHeadersAsync().ConfigureAwait(false); + + while (true) + { + (long? frameType, byte[] payload) = await serverStream.ReadFrameAsync(); + if (frameType == null) + { + // EOS + break; + } + // echo back + await serverStream.SendDataFrameAsync(payload).WaitAsync(TimeSpan.FromSeconds(30)); + } + // send FIN + await serverStream.SendResponseBodyAsync(Array.Empty(), isFinal: true); + }); + + StreamingHttpContent requestContent = new StreamingHttpContent(); + + using HttpClient client = CreateHttpClient(); + using HttpRequestMessage request = new() + { + Method = HttpMethod.Post, + RequestUri = server.Address, + Version = HttpVersion30, + VersionPolicy = HttpVersionPolicy.RequestVersionExact, + Content = requestContent + }; + + var responseTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).WaitAsync(TimeSpan.FromSeconds(10)); + + Stream requestStream = await requestContent.GetStreamAsync(); + // Send headers + await requestStream.FlushAsync(); + + using HttpResponseMessage response = await responseTask; + + var responseStream = await response.Content.ReadAsStreamAsync(); + + for (int i = 0; i < iters; ++i) + { + random.NextBytes(message); + await requestStream.WriteAsync(message).AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + await requestStream.FlushAsync(); + + int bytesRead = await responseStream.ReadAsync(readBuffer).AsTask().WaitAsync(TimeSpan.FromSeconds(10)); + Assert.Equal(bytesRead, messageSize); + Assert.Equal(message, readBuffer[..bytesRead]); + } + // Send FIN + requestContent.CompleteStream(); + // Receive FIN + Assert.Equal(0, await responseStream.ReadAsync(readBuffer).AsTask().WaitAsync(TimeSpan.FromSeconds(10))); + + await serverTask.WaitAsync(TimeSpan.FromSeconds(60)); + + serverStream.Dispose(); + Assert.NotNull(connection); + connection.Dispose(); + } + public static TheoryData StatusCodesTestData() { var statuses = Enum.GetValues(typeof(HttpStatusCode)).Cast().Where(s => s >= HttpStatusCode.OK); // exclude informational diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/ImpersonatedAuthTests.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/ImpersonatedAuthTests.cs new file mode 100644 index 00000000000000..32f44d5e00f705 --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/ImpersonatedAuthTests.cs @@ -0,0 +1,93 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Net.Security; +using System.Net.Test.Common; +using System.Security.Principal; +using System.Threading.Tasks; + +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.Http.Functional.Tests +{ + public class ImpersonatedAuthTests: IClassFixture + { + private readonly WindowsIdentityFixture _fixture; + private readonly ITestOutputHelper _output; + + public ImpersonatedAuthTests(WindowsIdentityFixture windowsIdentityFixture, ITestOutputHelper output) + { + _output = output; + _fixture = windowsIdentityFixture; + + Assert.False(_fixture.TestAccount.AccountTokenHandle.IsInvalid); + Assert.False(string.IsNullOrEmpty(_fixture.TestAccount.AccountName)); + } + + [OuterLoop] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))] + [InlineData(true)] + [InlineData(false)] + [PlatformSpecific(TestPlatforms.Windows)] + public async Task DefaultHandler_ImpersonatedUser_Success(bool useNtlm) + { + await LoopbackServer.CreateClientAndServerAsync( + async uri => + { + HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); + requestMessage.Version = new Version(1, 1); + + var handler = new HttpClientHandler(); + handler.UseDefaultCredentials = true; + + using (var client = new HttpClient(handler)) + { + HttpResponseMessage response = await client.SendAsync(requestMessage); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("foo", await response.Content.ReadAsStringAsync()); + + string initialUser = response.Headers.GetValues(NtAuthTests.UserHeaderName).First(); + + _output.WriteLine($"Starting test as {WindowsIdentity.GetCurrent().Name}"); + + // get token and run another request as different user. + WindowsIdentity.RunImpersonated(_fixture.TestAccount.AccountTokenHandle, () => + { + _output.WriteLine($"Running test as {WindowsIdentity.GetCurrent().Name}"); + Assert.Equal(_fixture.TestAccount.AccountName, WindowsIdentity.GetCurrent().Name); + + requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); + requestMessage.Version = new Version(1, 1); + + HttpResponseMessage response = client.SendAsync(requestMessage).GetAwaiter().GetResult(); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("foo", response.Content.ReadAsStringAsync().GetAwaiter().GetResult()); + + string newUser = response.Headers.GetValues(NtAuthTests.UserHeaderName).First(); + Assert.Equal(_fixture.TestAccount.AccountName, newUser); + }); + } + }, + async server => + { + await server.AcceptConnectionAsync(async connection => + { + Task t = useNtlm ? NtAuthTests.HandleNtlmAuthenticationRequest(connection, closeConnection: false) : NtAuthTests.HandleNegotiateAuthenticationRequest(connection, closeConnection: false); + await t; + _output.WriteLine("Finished first request"); + + // Second request should use new connection as it runs as different user. + // We keep first connection open so HttpClient may be tempted top use it. + await server.AcceptConnectionAsync(async connection => + { + Task t = useNtlm ? NtAuthTests.HandleNtlmAuthenticationRequest(connection, closeConnection: false) : NtAuthTests.HandleNegotiateAuthenticationRequest(connection, closeConnection: false); + await t; + }).ConfigureAwait(false); + }).ConfigureAwait(false); + }); + + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.Windows.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.Windows.cs new file mode 100644 index 00000000000000..8bb4df5747efcd --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.Windows.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Net.Security; +using System.Net.Test.Common; +using System.Security.Principal; +using System.Threading.Tasks; + +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.Http.Functional.Tests +{ + public partial class NtAuthTests : IClassFixture + { + internal const string NtlmAuthHeader = "WWW-Authenticate: NTLM"; + internal const string NegotiateAuthHeader = "WWW-Authenticate: Negotiate"; + internal const string UserHeaderName = "X-User"; + + internal static Task HandleNtlmAuthenticationRequest(LoopbackServer.Connection connection, bool closeConnection = true) + { + return HandleAuthenticationRequest(connection, useNtlm: true, useNegotiate: false, closeConnection); + } + + internal static Task HandleNegotiateAuthenticationRequest(LoopbackServer.Connection connection, bool closeConnection = true) + { + return HandleAuthenticationRequest(connection, useNtlm: false, useNegotiate: true, closeConnection); + } + + internal static async Task HandleAuthenticationRequest(LoopbackServer.Connection connection, bool useNtlm, bool useNegotiate, bool closeConnection) + { + HttpRequestData request = await connection.ReadRequestDataAsync(); + NTAuthentication authContext = null; + string authHeader = null; + + foreach (HttpHeaderData header in request.Headers) + { + if (header.Name == "Authorization") + { + authHeader = header.Value; + break; + } + } + + if (string.IsNullOrEmpty(authHeader)) + { + // This is initial request, we reject with showing supported mechanisms. + authHeader = string.Empty; + if (useNtlm) + { + authHeader += NtlmAuthHeader + "\r\n"; + } + + if (useNegotiate) + { + authHeader += NegotiateAuthHeader + "\r\n"; + } + + await connection.SendResponseAsync(HttpStatusCode.Unauthorized, authHeader).ConfigureAwait(false); + connection.CompleteRequestProcessing(); + + // Read next requests and fall-back to loop bellow to process it. + request = await connection.ReadRequestDataAsync(); + } + + SecurityStatusPal statusCode; + do + { + foreach (HttpHeaderData header in request.Headers) + { + if (header.Name == "Authorization") + { + authHeader = header.Value; + break; + } + } + + Assert.NotNull(authHeader); + var tokens = authHeader.Split(' ', 2, StringSplitOptions.TrimEntries); + // Should be type and base64 encoded blob + Assert.Equal(2, tokens.Length); + + authContext ??= new NTAuthentication(isServer: true, tokens[0], CredentialCache.DefaultNetworkCredentials, null, ContextFlagsPal.Connection, null); + + byte[]? outBlob = authContext.GetOutgoingBlob(Convert.FromBase64String(tokens[1]), throwOnError: false, out statusCode); + + if (outBlob != null && statusCode.ErrorCode == SecurityStatusPalErrorCode.ContinueNeeded) + { + authHeader = $"WWW-Authenticate: {tokens[0]} {Convert.ToBase64String(outBlob)}\r\n"; + await connection.SendResponseAsync(HttpStatusCode.Unauthorized, authHeader); + connection.CompleteRequestProcessing(); + + request = await connection.ReadRequestDataAsync(); + } + } + while (statusCode.ErrorCode == SecurityStatusPalErrorCode.ContinueNeeded); + + if (statusCode.ErrorCode == SecurityStatusPalErrorCode.OK) + { + // If authentication succeeded ask Windows about the identity and send it back as custom header. + SecurityContextTokenHandle? userContext = null; + using SafeDeleteContext securityContext = authContext.GetContext(out SecurityStatusPal statusCodeNew)!; + SSPIWrapper.QuerySecurityContextToken(GlobalSSPI.SSPIAuth, securityContext, out userContext); + using WindowsIdentity identity = new WindowsIdentity(userContext.DangerousGetHandle(), authContext.ProtocolName); + + authHeader = $"{UserHeaderName}: {identity.Name}\r\n"; + if (closeConnection) + { + authHeader += "Connection: close\r\n"; + } + + await connection.SendResponseAsync(HttpStatusCode.OK, authHeader, "foo"); + userContext.Dispose(); + } + else + { + await connection.SendResponseAsync(HttpStatusCode.Forbidden, "Connection: close\r\n", "boo"); + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsWindows), nameof(PlatformDetection.IsNotWindowsNanoServer))] + [InlineData(true)] + [InlineData(false)] + [PlatformSpecific(TestPlatforms.Windows)] + public async Task DefaultHandler_DefaultCredentials_Success(bool useNtlm) + { + await LoopbackServer.CreateClientAndServerAsync( + async uri => + { + HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri); + requestMessage.Version = new Version(1, 1); + + var handler = new HttpClientHandler() { UseDefaultCredentials = true }; + using (var client = new HttpClient(handler)) + { + HttpResponseMessage response = await client.SendAsync(requestMessage); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + _output.WriteLine($"Authenticated as {response.Headers.GetValues(NtAuthTests.UserHeaderName).First()}"); + Assert.Equal("foo", await response.Content.ReadAsStringAsync()); + } + }, + async server => + { + await server.AcceptConnectionAsync(async connection => + { + Task t = useNtlm ? HandleNtlmAuthenticationRequest(connection) : HandleNegotiateAuthenticationRequest(connection); + await t; + }).ConfigureAwait(false); + }); + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.cs index 096c5af0b42651..5c5954fb3491d2 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.cs @@ -104,7 +104,7 @@ public void Dispose() } } - public class NtAuthTests : IClassFixture + public partial class NtAuthTests : IClassFixture { private readonly NtAuthServers _servers; private readonly ITestOutputHelper _output; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2FlowControl.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2FlowControl.cs index 84ea142f933af6..f28491882ac3db 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2FlowControl.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2FlowControl.cs @@ -51,8 +51,10 @@ public async Task InitialHttp2StreamWindowSize_SentInSettingsFrame() Assert.Equal(WindowSize, (int)entry.Value); } - [Fact] - public Task InvalidRttPingResponse_RequestShouldFail() + [Theory] + [InlineData(0)] // Invalid PING payload + [InlineData(1)] // Unexpected PING response + public Task BadRttPingResponse_RequestShouldFail(int mode) { return Http2LoopbackServer.CreateClientAndServerAsync(async uri => { @@ -67,13 +69,24 @@ public Task InvalidRttPingResponse_RequestShouldFail() (int streamId, _) = await connection.ReadAndParseRequestHeaderAsync(); await connection.SendDefaultResponseHeadersAsync(streamId); PingFrame pingFrame = await connection.ReadPingAsync(); // expect an RTT PING - await connection.SendPingAckAsync(-6666); // send an invalid PING response + + if (mode == 0) + { + // Invalid PING payload + await connection.SendPingAckAsync(-6666); // send an invalid PING response + } + else + { + // Unexpected PING response + await connection.SendPingAckAsync(pingFrame.Data); // send an valid PING response + await connection.SendPingAckAsync(pingFrame.Data - 1); // send a second unexpected PING response + } + await connection.SendResponseDataAsync(streamId, new byte[] { 1, 2, 3 }, true); // otherwise fine response }, NoAutoPingResponseHttp2Options); } - [OuterLoop("Runs long")] [Fact] public async Task HighBandwidthDelayProduct_ClientStreamReceiveWindowWindowScalesUp() diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs index 14f444b1935a60..bfd1e83bfad502 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.cs @@ -837,8 +837,10 @@ public async Task Http2GetAsync_NoTrailingHeaders_EmptyCollection() } } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] - public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted() + [InlineData(false)] + [InlineData(true)] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] + public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted(bool responseHasContentLength) { using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) using (HttpClient client = CreateHttpClient()) @@ -850,7 +852,14 @@ public async Task Http2GetAsync_MissingTrailer_TrailingHeadersAccepted() int streamId = await connection.ReadRequestHeaderAsync(); // Response header. - await connection.SendDefaultResponseHeadersAsync(streamId); + if (responseHasContentLength) + { + await connection.SendResponseHeadersAsync(streamId, endStream: false, headers: new[] { new HttpHeaderData("Content-Length", DataBytes.Length.ToString()) }); + } + else + { + await connection.SendDefaultResponseHeadersAsync(streamId); + } // Response data, missing Trailers. await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); @@ -888,8 +897,10 @@ public async Task Http2GetAsync_TrailerHeaders_TrailingPseudoHeadersThrow() } } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] - public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Available() + [InlineData(false)] + [InlineData(true)] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsAlpn))] + public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Available(bool responseHasContentLength) { using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer()) using (HttpClient client = CreateHttpClient()) @@ -901,7 +912,14 @@ public async Task Http2GetAsyncResponseHeadersReadOption_TrailingHeaders_Availab int streamId = await connection.ReadRequestHeaderAsync(); // Response header. - await connection.SendDefaultResponseHeadersAsync(streamId); + if (responseHasContentLength) + { + await connection.SendResponseHeadersAsync(streamId, endStream: false, headers: new[] { new HttpHeaderData("Content-Length", DataBytes.Length.ToString()) }); + } + else + { + await connection.SendDefaultResponseHeadersAsync(streamId); + } // Response data, missing Trailers. await connection.WriteFrameAsync(MakeDataFrame(streamId, DataBytes)); 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 5c177598057214..718551f9b65d55 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 @@ -1,4 +1,4 @@ - + ../../src/Resources/Strings.resx $(DefineConstants);TargetsWindows @@ -33,8 +33,8 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs index f856652adb71fb..0f8a249a7665d7 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/ClientOperations.cs @@ -508,12 +508,6 @@ public static (string name, Func operation)[] Operations = private static void ValidateStatusCode(HttpResponseMessage m, HttpStatusCode expectedStatus = HttpStatusCode.OK) { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/55261")] - if (m.StatusCode == HttpStatusCode.InternalServerError) - { - throw new Exception("IGNORE"); - } - if (m.StatusCode != expectedStatus) { throw new Exception($"Expected status code {expectedStatus}, got {m.StatusCode}"); diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile index 28c10ddfa8a086..02378956718778 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/Dockerfile @@ -10,9 +10,9 @@ COPY . . # Pulling the msquic Debian package from msquic-ci public pipeline and from a hardcoded build. # Note that this is a temporary solution until we have properly published Linux packages. # Also note that in order to update to a newer msquic build, you have update this link. -ARG MSQUIC_PACKAGE=libmsquic_1.6.0_amd64.deb -ARG PACKAGES_DIR=LinuxPackages -RUN wget 'https://dev.azure.com/dnceng/9ee6d478-d288-47f7-aacc-f6e6d082ae6d/_apis/build/builds/1266893/artifacts?artifactName=LinuxPackages&api-version=6.0&%24format=zip' -O "$PACKAGES_DIR".zip +ARG MSQUIC_PACKAGE=libmsquic_1.9.0_amd64.deb +ARG PACKAGES_DIR=UnsignedUnixPackages +RUN wget 'https://dev.azure.com/dnceng/9ee6d478-d288-47f7-aacc-f6e6d082ae6d/_apis/build/builds/1426627/artifacts?artifactName=UnsignedUnixPackages&api-version=6.0&%24format=zip' -O "$PACKAGES_DIR".zip RUN apt-get update RUN apt-get install unzip RUN unzip $PACKAGES_DIR.zip diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/HttpStress.csproj b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/HttpStress.csproj index 80b4aa21b108ba..770f3370a79ad4 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/HttpStress.csproj +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/HttpStress.csproj @@ -5,6 +5,7 @@ net6.0 preview enable + True @@ -20,4 +21,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressClient.cs b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressClient.cs index be0dd1c42b0636..fe0a13360fd410 100644 --- a/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressClient.cs +++ b/src/libraries/System.Net.Http/tests/StressTests/HttpStress/StressClient.cs @@ -209,11 +209,6 @@ async Task RunWorker(int taskNum) { _aggregator.RecordCancellation(opIndex, stopwatch.Elapsed); } - catch (Exception e) when (e.Message == "IGNORE") - { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/55261")] - // See ClientOperations.ValidateStatusCode - } catch (Exception e) { _aggregator.RecordFailure(e, opIndex, stopwatch.Elapsed, requestContext.IsCancellationRequested, taskNum: taskNum, iteration: i); diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs index f56f85ac5bd0d4..139422163a95bc 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/HttpHeadersTest.cs @@ -2112,6 +2112,44 @@ public void AddHeaders_SourceHasInvalidHeaderValues_InvalidHeadersRemovedFromSou Assert.False(destination.Contains("custom"), "destination contains 'custom' header."); } + [Fact] + public void AddHeaders_ResponseHeaderToRequestHeaders_Success() + { + const string Name = "WWW-Authenticate"; + const string Value = "Basic realm=\"Access to the staging site\", charset=\"UTF-8\""; + + var request = new HttpRequestMessage(); + Assert.True(request.Headers.TryAddWithoutValidation(Name, Value)); + + Assert.True(request.Headers.Contains(Name)); + Assert.True(request.Headers.NonValidated.Contains(Name)); + + Assert.True(request.Headers.TryGetValues(Name, out IEnumerable values)); + Assert.Equal(Value, values.Single()); + + Assert.True(request.Headers.NonValidated.TryGetValues(Name, out HeaderStringValues nvValues)); + Assert.Equal(Value, nvValues.Single()); + } + + [Fact] + public void AddHeaders_RequestHeaderToResponseHeaders_Success() + { + const string Name = "Referer"; + const string Value = "https://dot.net"; + + var response = new HttpResponseMessage(); + Assert.True(response.Headers.TryAddWithoutValidation(Name, Value)); + + Assert.True(response.Headers.Contains(Name)); + Assert.True(response.Headers.NonValidated.Contains(Name)); + + Assert.True(response.Headers.TryGetValues(Name, out IEnumerable values)); + Assert.Equal(Value, values.Single()); + + Assert.True(response.Headers.NonValidated.TryGetValues(Name, out HeaderStringValues nvValues)); + Assert.Equal(Value, nvValues.Single()); + } + [Fact] public void HeaderStringValues_Default_Empty() { diff --git a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ObjectCollectionTest.cs b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ObjectCollectionTest.cs index d8ffd2c4ee1c75..3a8f69d9a44386 100644 --- a/src/libraries/System.Net.Http/tests/UnitTests/Headers/ObjectCollectionTest.cs +++ b/src/libraries/System.Net.Http/tests/UnitTests/Headers/ObjectCollectionTest.cs @@ -36,9 +36,74 @@ public void Ctor_ExecuteBothOverloads_MatchExpectation() c.Add("value1"); Assert.Throws(() => { c.Add(null); }); + } + + [Fact] + public void ContainsAndRemove_UsesEqualitySemantics() + { + ObjectCollection c = new ObjectCollection(); + string val1 = "value1"; + string val1DifferentReference = "value" + 1; + Assert.NotSame(val1, val1DifferentReference); + Assert.Equal(val1, val1DifferentReference); + + string val2 = "value2"; + string val2DifferentReference = "value" + 2; + Assert.NotSame(val2, val2DifferentReference); + Assert.Equal(val2, val2DifferentReference); + + string val3 = "value3"; + + // Start empty + Assert.Equal(0, c.Count); + Assert.False(c.Contains(val1)); + + // Single item + c.Add(val1); Assert.Equal(1, c.Count); - Assert.True(c.Contains("value1")); + Assert.True(c.Contains(val1)); + Assert.True(c.Contains(val1DifferentReference)); + Assert.False(c.Contains(val2)); + + // Single item removal + Assert.True(c.Remove(val1)); + Assert.Equal(0, c.Count); + Assert.False(c.Contains(val1)); + + // Multi-value + c.Add(val1); + c.Add(val2); + Assert.Equal(2, c.Count); + Assert.True(c.Contains(val1)); + Assert.True(c.Contains(val1DifferentReference)); + Assert.True(c.Contains(val2)); + Assert.True(c.Contains(val1DifferentReference)); + Assert.False(c.Contains(val3)); + + // Removal when multiple exist, using different reference. + Assert.True(c.Remove(val1)); + Assert.False(c.Contains(val1)); + Assert.True(c.Contains(val2)); + Assert.Equal(1, c.Count); + + // Removal of non-existent + Assert.False(c.Remove(val3)); + Assert.False(c.Remove(val1DifferentReference)); + Assert.Equal(1, c.Count); + Assert.True(c.Contains(val2DifferentReference)); + + // Removal last item + Assert.True(c.Remove(val2DifferentReference)); + Assert.Equal(0, c.Count); + Assert.False(c.Contains(val2)); + Assert.False(c.Contains(val1)); + + // Remove from empty + Assert.False(c.Remove(val1)); + Assert.False(c.Remove(val2)); + Assert.False(c.Remove(val3)); + Assert.Equal(0, c.Count); } } } diff --git a/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs b/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs index b8d331ba9918cd..66ab317a7d93de 100644 --- a/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs +++ b/src/libraries/System.Net.NetworkInformation/ref/System.Net.NetworkInformation.cs @@ -123,9 +123,11 @@ public virtual void CopyTo(System.Net.NetworkInformation.IPAddressInformation[] public abstract partial class IPGlobalProperties { protected IPGlobalProperties() { } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract string DhcpScopeName { get; } public abstract string DomainName { get; } public abstract string HostName { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsWinsProxy { get; } public abstract System.Net.NetworkInformation.NetBiosNodeType NodeType { get; } public virtual System.IAsyncResult BeginGetUnicastAddresses(System.AsyncCallback? callback, object? state) { throw null; } @@ -136,16 +138,22 @@ protected IPGlobalProperties() { } public abstract System.Net.IPEndPoint[] GetActiveTcpListeners(); [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.IPEndPoint[] GetActiveUdpListeners(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IcmpV4Statistics GetIcmpV4Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IcmpV6Statistics GetIcmpV6Statistics(); [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] public static System.Net.NetworkInformation.IPGlobalProperties GetIPGlobalProperties() { throw null; } public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv4GlobalStatistics(); public abstract System.Net.NetworkInformation.IPGlobalStatistics GetIPv6GlobalStatistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv4Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.TcpStatistics GetTcpIPv6Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv4Statistics(); + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.UdpStatistics GetUdpIPv6Statistics(); public virtual System.Net.NetworkInformation.UnicastIPAddressInformationCollection GetUnicastAddresses() { throw null; } public virtual System.Threading.Tasks.Task GetUnicastAddressesAsync() { throw null; } @@ -153,41 +161,69 @@ protected IPGlobalProperties() { } public abstract partial class IPGlobalStatistics { protected IPGlobalStatistics() { } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract int DefaultTtl { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool ForwardingEnabled { get; } public abstract int NumberOfInterfaces { get; } public abstract int NumberOfIPAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract int NumberOfRoutes { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketRequests { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketRoutingDiscards { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketsDiscarded { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long OutputPacketsWithNoRoute { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketFragmentFailures { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketReassembliesRequired { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketReassemblyFailures { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketReassemblyTimeout { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketsFragmented { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long PacketsReassembled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPackets { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDelivered { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDiscarded { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsForwarded { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithAddressErrors { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithHeadersErrors { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithUnknownProtocol { get; } } public abstract partial class IPInterfaceProperties { protected IPInterfaceProperties() { } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressInformationCollection AnycastAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressCollection DhcpServerAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressCollection DnsAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract string DnsSuffix { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.GatewayIPAddressInformationCollection GatewayAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsDnsEnabled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsDynamicDnsEnabled { get; } public abstract System.Net.NetworkInformation.MulticastIPAddressInformationCollection MulticastAddresses { get; } public abstract System.Net.NetworkInformation.UnicastIPAddressInformationCollection UnicastAddresses { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract System.Net.NetworkInformation.IPAddressCollection WinsServersAddresses { get; } public abstract System.Net.NetworkInformation.IPv4InterfaceProperties GetIPv4Properties(); public abstract System.Net.NetworkInformation.IPv6InterfaceProperties GetIPv6Properties(); @@ -212,11 +248,16 @@ public abstract partial class IPv4InterfaceProperties { protected IPv4InterfaceProperties() { } public abstract int Index { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingActive { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingEnabled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsDhcpEnabled { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool IsForwardingEnabled { get; } public abstract int Mtu { get; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public abstract bool UsesWins { get; } } public abstract partial class IPv4InterfaceStatistics @@ -316,7 +357,9 @@ protected NetworkInterface() { } [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] public static System.Net.NetworkInformation.NetworkInterface[] GetAllNetworkInterfaces() { throw null; } public virtual System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public virtual System.Net.NetworkInformation.IPInterfaceStatistics GetIPStatistics() { throw null; } + [System.Runtime.Versioning.UnsupportedOSPlatform("android")] public virtual System.Net.NetworkInformation.IPv4InterfaceStatistics GetIPv4Statistics() { throw null; } [System.Runtime.Versioning.UnsupportedOSPlatform("illumos")] [System.Runtime.Versioning.UnsupportedOSPlatform("solaris")] diff --git a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj index dc251f9c75dc41..b1c5a10f45a648 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj +++ b/src/libraries/System.Net.NetworkInformation/src/System.Net.NetworkInformation.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-Solaris;$(NetCoreAppCurrent) enable @@ -118,8 +118,8 @@ - - + + @@ -144,6 +144,17 @@ + + + + + + + + + + + diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs new file mode 100644 index 00000000000000..4cebb2c55efa9a --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalProperties.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPGlobalProperties : UnixIPGlobalProperties + { + public override TcpConnectionInformation[] GetActiveTcpConnections() => throw new PlatformNotSupportedException(); + + public override IPEndPoint[] GetActiveTcpListeners() => throw new PlatformNotSupportedException(); + + public override IPEndPoint[] GetActiveUdpListeners() => throw new PlatformNotSupportedException(); + + public override IcmpV4Statistics GetIcmpV4Statistics() => throw new PlatformNotSupportedException(); + + public override IcmpV6Statistics GetIcmpV6Statistics() => throw new PlatformNotSupportedException(); + + public override IPGlobalStatistics GetIPv4GlobalStatistics() + => new AndroidIPGlobalStatistics(ipv4: true); + + public override IPGlobalStatistics GetIPv6GlobalStatistics() + => new AndroidIPGlobalStatistics(ipv4: false); + + public override TcpStatistics GetTcpIPv4Statistics() => throw new PlatformNotSupportedException(); + + public override TcpStatistics GetTcpIPv6Statistics() => throw new PlatformNotSupportedException(); + + public override UdpStatistics GetUdpIPv4Statistics() => throw new PlatformNotSupportedException(); + + public override UdpStatistics GetUdpIPv6Statistics() => throw new PlatformNotSupportedException(); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs new file mode 100644 index 00000000000000..de57e068a1ddbf --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPGlobalStatistics.cs @@ -0,0 +1,73 @@ +// 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.InteropServices; +using System.Runtime.Versioning; +using System.Net.Sockets; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPGlobalStatistics : IPGlobalStatistics + { + public AndroidIPGlobalStatistics(bool ipv4) + { + AndroidNetworkInterface[] networkInterfaces = NetworkInterfacePal.GetAndroidNetworkInterfaces(); + + foreach (var networkInterface in networkInterfaces) + { + var component = ipv4 ? NetworkInterfaceComponent.IPv4 : NetworkInterfaceComponent.IPv6; + if (networkInterface.Supports(component)) + { + NumberOfInterfaces++; + } + + foreach (UnixUnicastIPAddressInformation addressInformation in networkInterface.UnicastAddress) + { + bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) + { + NumberOfIPAddresses++; + } + } + + if (networkInterface.MulticastAddresess != null) + { + foreach (IPAddress address in networkInterface.MulticastAddresess) + { + bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork; + if (isIPv4 == ipv4) + { + NumberOfIPAddresses++; + } + } + } + } + } + + public override int NumberOfInterfaces { get; } + public override int NumberOfIPAddresses { get; } + + public override int DefaultTtl => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool ForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override int NumberOfRoutes => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketRequests => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketRoutingDiscards => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketsDiscarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long OutputPacketsWithNoRoute => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketFragmentFailures => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketReassembliesRequired => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketReassemblyFailures => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketReassemblyTimeout => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketsFragmented => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long PacketsReassembled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPackets => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsDelivered => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsDiscarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsForwarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsWithAddressErrors => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsWithHeadersErrors => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override long ReceivedPacketsWithUnknownProtocol => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs new file mode 100644 index 00000000000000..cee58c47d84475 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPInterfaceProperties.cs @@ -0,0 +1,30 @@ +// 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.IO; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPInterfaceProperties : UnixIPInterfaceProperties + { + private readonly AndroidIPv4InterfaceProperties _ipv4Properties; + private readonly AndroidIPv6InterfaceProperties _ipv6Properties; + + public AndroidIPInterfaceProperties(AndroidNetworkInterface ani) + : base(ani, globalConfig: true) + { + _ipv4Properties = new AndroidIPv4InterfaceProperties(ani); + _ipv6Properties = new AndroidIPv6InterfaceProperties(ani); + } + + public override IPv4InterfaceProperties GetIPv4Properties() => _ipv4Properties; + public override IPv6InterfaceProperties GetIPv6Properties() => _ipv6Properties; + + public override bool IsDynamicDnsEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPAddressInformationCollection AnycastAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override GatewayIPAddressInformationCollection GatewayAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPAddressCollection DhcpServerAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPAddressCollection WinsServersAddresses => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs new file mode 100644 index 00000000000000..cc12cf7f357456 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv4InterfaceProperties.cs @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPv4InterfaceProperties : UnixIPv4InterfaceProperties + { + public AndroidIPv4InterfaceProperties(AndroidNetworkInterface androidNetworkInterface) + : base(androidNetworkInterface) + { + Mtu = androidNetworkInterface._mtu; + } + + public override int Mtu { get; } + + public override bool IsAutomaticPrivateAddressingActive => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool IsAutomaticPrivateAddressingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool IsDhcpEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool IsForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override bool UsesWins => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs new file mode 100644 index 00000000000000..9a5f872231efde --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidIPv6InterfaceProperties.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; + +namespace System.Net.NetworkInformation +{ + internal sealed class AndroidIPv6InterfaceProperties : UnixIPv6InterfaceProperties + { + private readonly AndroidNetworkInterface _androidNetworkInterface; + + public AndroidIPv6InterfaceProperties(AndroidNetworkInterface androidNetworkInterface) + : base(androidNetworkInterface) + { + _androidNetworkInterface = androidNetworkInterface; + } + + public override int Mtu => _androidNetworkInterface._mtu; + + public override long GetScopeId(ScopeLevel scopeLevel) + { + if (scopeLevel == ScopeLevel.None || scopeLevel == ScopeLevel.Interface || + scopeLevel == ScopeLevel.Link || scopeLevel == ScopeLevel.Subnet) + { + return _androidNetworkInterface.Index; + } + + return 0; + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs new file mode 100644 index 00000000000000..dcf66895aea7b1 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/AndroidNetworkInterface.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Net; + +namespace System.Net.NetworkInformation +{ + /// + /// Implements a NetworkInterface on Android. + /// + internal sealed class AndroidNetworkInterface : UnixNetworkInterface + { + internal readonly int _mtu; + private readonly AndroidIPInterfaceProperties _ipProperties; + + internal unsafe AndroidNetworkInterface(string name, Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo) + : base(name) + { + _index = networkInterfaceInfo->InterfaceIndex; + if (networkInterfaceInfo->NumAddressBytes > 0) + { + _physicalAddress = new PhysicalAddress(new ReadOnlySpan(networkInterfaceInfo->AddressBytes, networkInterfaceInfo->NumAddressBytes).ToArray()); + } + + _mtu = networkInterfaceInfo->Mtu; + _ipProperties = new AndroidIPInterfaceProperties(this); + + OperationalStatus = (OperationalStatus)networkInterfaceInfo->OperationalState; + Speed = networkInterfaceInfo->Speed; + SupportsMulticast = networkInterfaceInfo->SupportsMulticast != 0; + NetworkInterfaceType = (NetworkInterfaceType)networkInterfaceInfo->HardwareType; + } + + internal unsafe void AddAddress(Interop.Sys.IpAddressInfo *addressInfo) + { + var address = new IPAddress(new ReadOnlySpan(addressInfo->AddressBytes, addressInfo->NumAddressBytes)); + if (address.IsIPv6LinkLocal) + { + address.ScopeId = addressInfo->InterfaceIndex; + } + + AddAddress(address, addressInfo->PrefixLength); + } + + public override bool SupportsMulticast { get; } + public override IPInterfaceProperties GetIPProperties() => _ipProperties; + public override IPInterfaceStatistics GetIPStatistics() => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override IPv4InterfaceStatistics GetIPv4Statistics() => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform); + public override OperationalStatus OperationalStatus { get; } + public override NetworkInterfaceType NetworkInterfaceType { get; } + public override long Speed { get; } + public override bool IsReceiveOnly => false; + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs index d835ce2ecd65ba..1371a47d3ed945 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalProperties.cs @@ -40,6 +40,7 @@ public static IPGlobalProperties GetIPGlobalProperties() /// /// Gets the Dynamic Host Configuration Protocol (DHCP) scope name. /// + [UnsupportedOSPlatform("android")] public abstract string DhcpScopeName { get; } /// @@ -55,6 +56,7 @@ public static IPGlobalProperties GetIPGlobalProperties() /// /// Gets a bool value that specifies whether the local computer is acting as a Windows Internet Name Service (WINS) proxy. /// + [UnsupportedOSPlatform("android")] public abstract bool IsWinsProxy { get; } /// @@ -72,25 +74,31 @@ public virtual UnicastIPAddressInformationCollection EndGetUnicastAddresses(IAsy throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); } + [UnsupportedOSPlatform("android")] public abstract TcpStatistics GetTcpIPv4Statistics(); + [UnsupportedOSPlatform("android")] public abstract TcpStatistics GetTcpIPv6Statistics(); /// /// Provides User Datagram Protocol (UDP) statistical data for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract UdpStatistics GetUdpIPv4Statistics(); + [UnsupportedOSPlatform("android")] public abstract UdpStatistics GetUdpIPv6Statistics(); /// /// Provides Internet Control Message Protocol (ICMP) version 4 statistical data for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract IcmpV4Statistics GetIcmpV4Statistics(); /// /// Provides Internet Control Message Protocol (ICMP) version 6 statistical data for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract IcmpV6Statistics GetIcmpV6Statistics(); /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs new file mode 100644 index 00000000000000..33e09ece17c696 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalPropertiesPal.Android.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Net.NetworkInformation +{ + internal static class IPGlobalPropertiesPal + { + public static IPGlobalProperties GetIPGlobalProperties() + { + return new AndroidIPGlobalProperties(); + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs index a8103f867e83d4..04b9f14f1eab2b 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPGlobalStatistics.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.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -11,11 +13,13 @@ public abstract class IPGlobalStatistics /// /// Gets the default time-to-live (TTL) value for Internet Protocol (IP) packets. /// + [UnsupportedOSPlatform("android")] public abstract int DefaultTtl { get; } /// /// Gets a bool value that specifies whether Internet Protocol (IP) packet forwarding is enabled. /// + [UnsupportedOSPlatform("android")] public abstract bool ForwardingEnabled { get; } /// @@ -31,91 +35,109 @@ public abstract class IPGlobalStatistics /// /// Gets the number of outbound Internet Protocol (IP) packets. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketRequests { get; } /// /// Gets the number of routes in the routing table that have been discarded. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketRoutingDiscards { get; } /// /// Gets the number of transmitted Internet Protocol (IP) packets that have been discarded. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketsDiscarded { get; } /// /// Gets the number of Internet Protocol (IP) packets for which the local computer could not determine a route to the destination address. /// + [UnsupportedOSPlatform("android")] public abstract long OutputPacketsWithNoRoute { get; } /// /// Gets the number of Internet Protocol (IP) packets that could not be fragmented. /// + [UnsupportedOSPlatform("android")] public abstract long PacketFragmentFailures { get; } /// /// Gets the number of Internet Protocol (IP) packets that required reassembly. /// + [UnsupportedOSPlatform("android")] public abstract long PacketReassembliesRequired { get; } /// /// Gets the number of Internet Protocol (IP) packets that were not successfully reassembled. /// + [UnsupportedOSPlatform("android")] public abstract long PacketReassemblyFailures { get; } /// /// Gets the maximum amount of time within which all fragments of an Internet Protocol (IP) packet must arrive. /// + [UnsupportedOSPlatform("android")] public abstract long PacketReassemblyTimeout { get; } /// /// Gets the number of Internet Protocol (IP) packets fragmented. /// + [UnsupportedOSPlatform("android")] public abstract long PacketsFragmented { get; } /// /// Gets the number of Internet Protocol (IP) packets reassembled. /// + [UnsupportedOSPlatform("android")] public abstract long PacketsReassembled { get; } /// /// Gets the number of Internet Protocol (IP) packets received. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPackets { get; } /// /// Gets the number of Internet Protocol(IP) packets received and delivered. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDelivered { get; } /// /// Gets the number of Internet Protocol (IP) packets that have been received and discarded. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsDiscarded { get; } /// /// Gets the number of Internet Protocol (IP) packets forwarded. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsForwarded { get; } /// /// Gets the number of Internet Protocol (IP) packets with address errors that were received. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithAddressErrors { get; } /// /// Gets the number of Internet Protocol (IP) packets with header errors that were received. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithHeadersErrors { get; } /// /// Gets the number of Internet Protocol (IP) packets received on the local machine with an unknown protocol in the header. /// + [UnsupportedOSPlatform("android")] public abstract long ReceivedPacketsWithUnknownProtocol { get; } /// /// Gets the number of routes in the Internet Protocol (IP) routing table. /// + [UnsupportedOSPlatform("android")] public abstract int NumberOfRoutes { get; } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs index e659598f5e4f4c..863737ce18f6d3 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPInterfaceProperties.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.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -12,16 +14,19 @@ public abstract class IPInterfaceProperties /// /// Gets a bool value that indicates whether this interface is configured to send name resolution queries to a Domain Name System (DNS) server. /// + [UnsupportedOSPlatform("android")] public abstract bool IsDnsEnabled { get; } /// /// Gets the Domain Name System (DNS) suffix associated with this interface. /// + [UnsupportedOSPlatform("android")] public abstract string DnsSuffix { get; } /// /// Gets a bool value that indicates whether this interface is configured to automatically register its IP address information with the Domain Name System (DNS). /// + [UnsupportedOSPlatform("android")] public abstract bool IsDynamicDnsEnabled { get; } /// @@ -37,26 +42,31 @@ public abstract class IPInterfaceProperties /// /// The address identifies multiple computers. Packets sent to an anycast address are sent to one of the computers identified by the address. /// + [UnsupportedOSPlatform("android")] public abstract IPAddressInformationCollection AnycastAddresses { get; } /// /// The address is that of a Domain Name Service (DNS) server for the local computer. /// + [UnsupportedOSPlatform("android")] public abstract IPAddressCollection DnsAddresses { get; } /// /// Gets the network gateway addresses. /// + [UnsupportedOSPlatform("android")] public abstract GatewayIPAddressInformationCollection GatewayAddresses { get; } /// /// Gets the addresses for Dynamic Host Configuration Protocol (DHCP) servers. /// + [UnsupportedOSPlatform("android")] public abstract IPAddressCollection DhcpServerAddresses { get; } /// /// Gets the list of Wins Servers registered with this interface /// + [UnsupportedOSPlatform("android")] public abstract IPAddressCollection WinsServersAddresses { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs index 0f104e3fce8fc3..9f9d0b1e3766dd 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/IPv4InterfaceProperties.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.Runtime.Versioning; + namespace System.Net.NetworkInformation { /// @@ -11,21 +13,25 @@ public abstract class IPv4InterfaceProperties /// /// Gets a bool value that indicates whether an interface uses Windows Internet Name Service (WINS). /// + [UnsupportedOSPlatform("android")] public abstract bool UsesWins { get; } /// /// Gets a bool value that indicates whether the interface is configured to use a dynamic host configuration protocol (DHCP) server to obtain an IP address. /// + [UnsupportedOSPlatform("android")] public abstract bool IsDhcpEnabled { get; } /// /// Gets a bool value that indicates whether this interface has an automatic private IP addressing (APIPA) address. /// + [UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingActive { get; } /// /// Gets a bool value that indicates whether this interface has automatic private IP addressing (APIPA) enabled. /// + [UnsupportedOSPlatform("android")] public abstract bool IsAutomaticPrivateAddressingEnabled { get; } /// @@ -36,6 +42,7 @@ public abstract class IPv4InterfaceProperties /// /// Gets a bool value that indicates whether this interface can route packets. /// + [UnsupportedOSPlatform("android")] public abstract bool IsForwardingEnabled { get; } /// diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs index 94cb8fb0b9d81c..24f02186c3dc3a 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterface.cs @@ -70,6 +70,7 @@ public virtual IPInterfaceProperties GetIPProperties() /// Provides Internet Protocol (IP) statistical data for this network interface. /// /// The interface's IP statistics. + [UnsupportedOSPlatform("android")] public virtual IPInterfaceStatistics GetIPStatistics() { throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); @@ -81,6 +82,7 @@ public virtual IPInterfaceStatistics GetIPStatistics() /// Do not use this method, use GetIPStatistics instead. /// /// The interface's IP statistics. + [UnsupportedOSPlatform("android")] public virtual IPv4InterfaceStatistics GetIPv4Statistics() { throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs new file mode 100644 index 00000000000000..820e01f093b34c --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkInterfacePal.Android.cs @@ -0,0 +1,110 @@ +// 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.InteropServices; + +namespace System.Net.NetworkInformation +{ + internal static class NetworkInterfacePal + { + /// Returns objects that describe the network interfaces on the local computer. + public static NetworkInterface[] GetAllNetworkInterfaces() => GetAndroidNetworkInterfaces(); + public static bool GetIsNetworkAvailable() => TransformNetworkInterfacess(IsSomeNetworkUp); + public static int IPv6LoopbackInterfaceIndex => LoopbackInterfaceIndex; + public static int LoopbackInterfaceIndex => TransformNetworkInterfacess(FindLoopbackInterfaceIndex); + + internal static unsafe AndroidNetworkInterface[] GetAndroidNetworkInterfaces() + => TransformNetworkInterfacess(ToAndroidNetworkInterfaceArray); + + private static unsafe T TransformNetworkInterfacess(Func transform) + { + int interfaceCount = 0; + int addressCount = 0; + Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo = null; + Interop.Sys.IpAddressInfo *addressInfo = null; + + if (Interop.Sys.GetNetworkInterfaces(ref interfaceCount, ref networkInterfaceInfo, ref addressCount, ref addressInfo) != 0) + { + string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); + throw new NetworkInformationException(message); + } + + // the native implementation of Interop.Sys.GetNetworkInterfaces allocates one block of memory + // for both networkInterfaceInfo and addressInfo so we only need to call free once pointing at + // the start of the network interfaces list + var globalMemory = (IntPtr)networkInterfaceInfo; + + try + { + return transform(interfaceCount, (IntPtr)networkInterfaceInfo, addressCount, (IntPtr)addressInfo); + } + finally + { + Marshal.FreeHGlobal(globalMemory); + } + } + + private static unsafe AndroidNetworkInterface[] ToAndroidNetworkInterfaceArray(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaces = new AndroidNetworkInterface[interfaceCount]; + + var networkInterfaceInfo = (Interop.Sys.NetworkInterfaceInfo*)networkInterfacesPtr; + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + var name = Marshal.PtrToStringAnsi((IntPtr)networkInterfaceInfo->Name); + networkInterfaces[i] = new AndroidNetworkInterface(name!, networkInterfaceInfo); + } + + var addressInfo = (Interop.Sys.IpAddressInfo*)addressPtr; + for (int i = 0; i < addressCount; i++, addressInfo++) + { + // there is usually just a handful of few network interfaces on Android devices + // and this linear search does not have any impact on performance + foreach (var networkInterface in networkInterfaces) + { + if (networkInterface.Index == addressInfo->InterfaceIndex) + { + networkInterface.AddAddress(addressInfo); + break; + } + } + } + + return networkInterfaces; + } + + private static unsafe int FindLoopbackInterfaceIndex(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaceInfo = (Interop.Sys.NetworkInterfaceInfo*)networkInterfacesPtr; + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + if (networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Loopback) + { + return networkInterfaceInfo->InterfaceIndex; + } + } + + throw new NetworkInformationException(SR.net_NoLoopback); + } + + private static unsafe bool IsSomeNetworkUp(int interfaceCount, IntPtr networkInterfacesPtr, int addressCount, IntPtr addressPtr) + { + var networkInterfaceInfo = (Interop.Sys.NetworkInterfaceInfo*)networkInterfacesPtr; + for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++) + { + if (networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Loopback + || networkInterfaceInfo->HardwareType == (int)NetworkInterfaceType.Tunnel) + { + continue; + } + + if (networkInterfaceInfo->OperationalState == (int)OperationalStatus.Up) + { + return true; + } + } + + return false; + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs index cca949a317a6f8..eafa42ff3fec12 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixIPGlobalProperties.cs @@ -13,6 +13,7 @@ namespace System.Net.NetworkInformation internal abstract class UnixIPGlobalProperties : IPGlobalProperties { [UnsupportedOSPlatform("linux")] + [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("osx")] [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] @@ -26,6 +27,7 @@ internal abstract class UnixIPGlobalProperties : IPGlobalProperties public override string HostName { get { return HostInformation.HostName; } } [UnsupportedOSPlatform("linux")] + [UnsupportedOSPlatform("android")] [UnsupportedOSPlatform("osx")] [UnsupportedOSPlatform("ios")] [UnsupportedOSPlatform("tvos")] diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs index d248c72b6930cf..00c5b3a9a3028c 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/UnixNetworkInterface.cs @@ -60,7 +60,7 @@ public override bool Supports(NetworkInterfaceComponent networkInterfaceComponen public List UnicastAddress { get { return _unicastAddresses; } } /// - /// Returns a list of all Unicast addresses of the interface's IP Addresses. + /// Returns a list of all Multicast addresses of the interface's IP Addresses. /// public List? MulticastAddresess { get { return _multicastAddresses; } } diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs index 860e64f216edbe..70804e19499e2f 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPGlobalPropertiesTest.cs @@ -26,7 +26,7 @@ public IPGlobalPropertiesTest(ITestOutputHelper output) } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36890", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [SkipOnPlatform(TestPlatforms.Android, "Expected behavior is different on Android")] public void IPGlobalProperties_AccessAllMethods_NoErrors() { IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties(); @@ -36,7 +36,7 @@ public void IPGlobalProperties_AccessAllMethods_NoErrors() Assert.NotNull(gp.GetActiveUdpListeners()); Assert.NotNull(gp.GetIPv4GlobalStatistics()); - if (!OperatingSystem.IsMacOS() && !OperatingSystem.IsFreeBSD()) + if (!OperatingSystem.IsMacOS() && !OperatingSystem.IsIOS() && !OperatingSystem.IsTvOS() && !OperatingSystem.IsFreeBSD()) { // OSX and FreeBSD do not provide IPv6 stats. Assert.NotNull(gp.GetIPv6GlobalStatistics()); @@ -50,9 +50,71 @@ public void IPGlobalProperties_AccessAllMethods_NoErrors() Assert.NotNull(gp.GetUdpIPv6Statistics()); } + [Fact] + [PlatformSpecific(TestPlatforms.Android)] + public void IPGlobalProperties_AccessAllMethods_NoErrors_Android() + { + IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties(); + + Assert.NotNull(gp.GetIPv4GlobalStatistics()); + Assert.NotNull(gp.GetIPv6GlobalStatistics()); + + Assert.Throws(() => gp.GetActiveTcpConnections()); + Assert.Throws(() => gp.GetActiveTcpListeners()); + Assert.Throws(() => gp.GetActiveUdpListeners()); + Assert.Throws(() => gp.GetIcmpV4Statistics()); + Assert.Throws(() => gp.GetIcmpV6Statistics()); + Assert.Throws(() => gp.GetTcpIPv4Statistics()); + Assert.Throws(() => gp.GetTcpIPv6Statistics()); + Assert.Throws(() => gp.GetUdpIPv4Statistics()); + Assert.Throws(() => gp.GetUdpIPv6Statistics()); + } + + [Theory] + [InlineData(4)] + [InlineData(6)] + [PlatformSpecific(TestPlatforms.Android)] + public void IPGlobalProperties_IPv4_IPv6_NoErrors_Android(int ipVersion) + { + IPGlobalProperties gp = IPGlobalProperties.GetIPGlobalProperties(); + IPGlobalStatistics statistics = ipVersion switch { + 4 => gp.GetIPv4GlobalStatistics(), + 6 => gp.GetIPv6GlobalStatistics(), + _ => throw new ArgumentOutOfRangeException() + }; + + _log.WriteLine($"- IPv{ipVersion} statistics: -"); + _log.WriteLine($"Number of interfaces: {statistics.NumberOfInterfaces}"); + _log.WriteLine($"Number of IP addresses: {statistics.NumberOfIPAddresses}"); + + Assert.InRange(statistics.NumberOfInterfaces, 1, int.MaxValue); + Assert.InRange(statistics.NumberOfIPAddresses, 1, int.MaxValue); + + Assert.Throws(() => statistics.DefaultTtl); + Assert.Throws(() => statistics.ForwardingEnabled); + Assert.Throws(() => statistics.OutputPacketRequests); + Assert.Throws(() => statistics.OutputPacketRoutingDiscards); + Assert.Throws(() => statistics.OutputPacketsDiscarded); + Assert.Throws(() => statistics.OutputPacketsWithNoRoute); + Assert.Throws(() => statistics.PacketFragmentFailures); + Assert.Throws(() => statistics.PacketReassembliesRequired); + Assert.Throws(() => statistics.PacketReassemblyFailures); + Assert.Throws(() => statistics.PacketReassemblyTimeout); + Assert.Throws(() => statistics.PacketsFragmented); + Assert.Throws(() => statistics.PacketsReassembled); + Assert.Throws(() => statistics.ReceivedPackets); + Assert.Throws(() => statistics.ReceivedPacketsDelivered); + Assert.Throws(() => statistics.ReceivedPacketsDiscarded); + Assert.Throws(() => statistics.ReceivedPacketsForwarded); + Assert.Throws(() => statistics.ReceivedPacketsWithAddressErrors); + Assert.Throws(() => statistics.ReceivedPacketsWithHeadersErrors); + Assert.Throws(() => statistics.ReceivedPacketsWithUnknownProtocol); + Assert.Throws(() => statistics.NumberOfRoutes); + } + [Theory] [MemberData(nameof(Loopbacks))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36890", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")] public void IPGlobalProperties_TcpListeners_Succeed(IPAddress address) { using (var server = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) @@ -78,7 +140,7 @@ public void IPGlobalProperties_TcpListeners_Succeed(IPAddress address) [Theory] [ActiveIssue("https://github.com/dotnet/runtime/issues/34690", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36890", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] + [PlatformSpecific(~(TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.Android))] [MemberData(nameof(Loopbacks))] public async Task IPGlobalProperties_TcpActiveConnections_Succeed(IPAddress address) { @@ -109,6 +171,7 @@ public async Task IPGlobalProperties_TcpActiveConnections_Succeed(IPAddress addr } [Fact] + [SkipOnPlatform(TestPlatforms.Android, "Unsupported on Android")] public void IPGlobalProperties_TcpActiveConnections_NotListening() { TcpConnectionInformation[] tcpCconnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections(); @@ -119,7 +182,6 @@ public void IPGlobalProperties_TcpActiveConnections_NotListening() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public async Task GetUnicastAddresses_NotEmpty() { IPGlobalProperties props = IPGlobalProperties.GetIPGlobalProperties(); diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs new file mode 100644 index 00000000000000..61e57c854aa479 --- /dev/null +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/IPInterfacePropertiesTest_Android.cs @@ -0,0 +1,221 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Linq; +using System.Net.Http.Functional.Tests; +using System.Net.Sockets; +using System.Net.Test.Common; +using System.Threading.Tasks; + +using Xunit; +using Xunit.Abstractions; + +namespace System.Net.NetworkInformation.Tests +{ + [PlatformSpecific(TestPlatforms.Android)] + public class IPInterfacePropertiesTest_Android + { + private readonly ITestOutputHelper _log; + + public IPInterfacePropertiesTest_Android(ITestOutputHelper output) + { + _log = output; + } + + [Fact] + public async Task IPInfoTest_AccessAllProperties_NoErrors() + { + await Task.Run(() => + { + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + _log.WriteLine("- Speed:" + nic.Speed); + Assert.Equal(-1, nic.Speed); + _log.WriteLine("- Supports IPv4: " + nic.Supports(NetworkInterfaceComponent.IPv4)); + _log.WriteLine("- Supports IPv6: " + nic.Supports(NetworkInterfaceComponent.IPv6)); + Assert.False(nic.IsReceiveOnly); + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + Assert.NotNull(ipProperties); + + Assert.Throws(() => ipProperties.AnycastAddresses); + Assert.Throws(() => ipProperties.DhcpServerAddresses); + Assert.Throws(() => ipProperties.DnsAddresses); + Assert.Throws(() => ipProperties.DnsSuffix); + Assert.Throws(() => ipProperties.GatewayAddresses); + Assert.Throws(() => ipProperties.IsDnsEnabled); + Assert.Throws(() => ipProperties.IsDynamicDnsEnabled); + + Assert.NotNull(ipProperties.MulticastAddresses); + _log.WriteLine("- Multicast Addresses: " + ipProperties.MulticastAddresses.Count); + foreach (IPAddressInformation multi in ipProperties.MulticastAddresses) + { + _log.WriteLine("-- " + multi.Address.ToString()); + Assert.Throws(() => multi.IsDnsEligible); + Assert.Throws(() => multi.IsTransient); + } + + Assert.NotNull(ipProperties.UnicastAddresses); + _log.WriteLine("- Unicast Addresses: " + ipProperties.UnicastAddresses.Count); + foreach (UnicastIPAddressInformation uni in ipProperties.UnicastAddresses) + { + _log.WriteLine("-- " + uni.Address.ToString()); + Assert.Throws(() => uni.AddressPreferredLifetime); + Assert.Throws(() => uni.AddressValidLifetime); + Assert.Throws(() => uni.DhcpLeaseLifetime); + Assert.Throws(() => uni.DuplicateAddressDetectionState); + + Assert.NotNull(uni.IPv4Mask); + _log.WriteLine("--- IPv4 Mask: " + uni.IPv4Mask); + Assert.Throws(() => uni.IsDnsEligible); + Assert.Throws(() => uni.IsTransient); + Assert.Throws(() => uni.PrefixOrigin); + Assert.Throws(() => uni.SuffixOrigin); + + // Prefix Length + _log.WriteLine("--- PrefixLength: " + uni.PrefixLength); + Assert.True(uni.PrefixLength > 0); + Assert.True((uni.Address.AddressFamily == AddressFamily.InterNetwork ? 33 : 129) > uni.PrefixLength); + } + + Assert.Throws(() => ipProperties.WinsServersAddresses); + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + public async Task IPInfoTest_AccessAllIPv4Properties_NoErrors() + { + await Task.Run(() => + { + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + _log.WriteLine("IPv4 Properties:"); + + IPv4InterfaceProperties ipv4Properties = ipProperties.GetIPv4Properties(); + + _log.WriteLine("Index: " + ipv4Properties.Index); + Assert.Throws(() => ipv4Properties.IsAutomaticPrivateAddressingActive); + Assert.Throws(() => ipv4Properties.IsAutomaticPrivateAddressingEnabled); + Assert.Throws(() => ipv4Properties.IsDhcpEnabled); + Assert.Throws(() => ipv4Properties.IsForwardingEnabled); + _log.WriteLine("Mtu: " + ipv4Properties.Mtu); + Assert.Throws(() => ipv4Properties.UsesWins); + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + public async Task IPInfoTest_AccessAllIPv6Properties_NoErrors() + { + await Task.Run(() => + { + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + _log.WriteLine("IPv6 Properties:"); + + IPv6InterfaceProperties ipv6Properties = ipProperties.GetIPv6Properties(); + + if (ipv6Properties == null) + { + _log.WriteLine("IPv6Properties is null"); + continue; + } + + _log.WriteLine("Index: " + ipv6Properties.Index); + _log.WriteLine("Mtu: " + ipv6Properties.Mtu); + _log.WriteLine("Scope: " + ipv6Properties.GetScopeId(ScopeLevel.Link)); + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + [Trait("IPv6", "true")] + public async Task IPv6ScopeId_AccessAllValues_Success() + { + await Task.Run(() => + { + Assert.True(Capability.IPv6Support()); + + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + _log.WriteLine("Nic: " + nic.Name); + + if (!nic.Supports(NetworkInterfaceComponent.IPv6)) + { + continue; + } + + IPInterfaceProperties ipProperties = nic.GetIPProperties(); + + IPv6InterfaceProperties ipv6Properties = ipProperties.GetIPv6Properties(); + + Array values = Enum.GetValues(typeof(ScopeLevel)); + foreach (ScopeLevel level in values) + { + _log.WriteLine("-- Level: " + level + "; " + ipv6Properties.GetScopeId(level)); + } + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + [Trait("IPv4", "true")] + public async Task IPInfoTest_IPv4Loopback_ProperAddress() + { + await Task.Run(() => + { + Assert.True(Capability.IPv4Support()); + + _log.WriteLine("Loopback IPv4 index: " + NetworkInterface.LoopbackInterfaceIndex); + + NetworkInterface loopback = NetworkInterface.GetAllNetworkInterfaces().First(ni => ni.Name == "lo"); + Assert.NotNull(loopback); + + foreach (UnicastIPAddressInformation unicast in loopback.GetIPProperties().UnicastAddresses) + { + if (unicast.Address.Equals(IPAddress.Loopback)) + { + Assert.Equal(IPAddress.Parse("255.0.0.0"), unicast.IPv4Mask); + Assert.Equal(8, unicast.PrefixLength); + break; + } + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + + [Fact] + [Trait("IPv6", "true")] + public async Task IPInfoTest_IPv6Loopback_ProperAddress() + { + await Task.Run(() => + { + Assert.True(Capability.IPv6Support()); + + _log.WriteLine("Loopback IPv6 index: " + NetworkInterface.IPv6LoopbackInterfaceIndex); + + NetworkInterface loopback = NetworkInterface.GetAllNetworkInterfaces().First(ni => ni.Name == "lo"); + Assert.NotNull(loopback); + + foreach (UnicastIPAddressInformation unicast in loopback.GetIPProperties().UnicastAddresses) + { + if (unicast.Address.Equals(IPAddress.IPv6Loopback)) + { + Assert.Equal(128, unicast.PrefixLength); + break; + } + } + }).WaitAsync(TestHelper.PassingTestTimeout); + } + } +} diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs index 3455f06297d793..c022f74b2c234c 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceBasicTest.cs @@ -20,7 +20,6 @@ public NetworkInterfaceBasicTest(ITestOutputHelper output) } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public void BasicTest_GetNetworkInterfaces_AtLeastOne() { Assert.NotEqual(0, NetworkInterface.GetAllNetworkInterfaces().Length); @@ -57,7 +56,7 @@ public void BasicTest_AccessInstanceProperties_NoExceptions() } [Fact] - [PlatformSpecific(TestPlatforms.Linux)] // Some APIs are not supported on Linux + [PlatformSpecific(TestPlatforms.Linux|TestPlatforms.Android)] // Some APIs are not supported on Linux and Android public void BasicTest_AccessInstanceProperties_NoExceptions_Linux() { foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) @@ -132,7 +131,6 @@ public void BasicTest_AccessInstanceProperties_NoExceptions_Bsd() [Fact] [Trait("IPv4", "true")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public void BasicTest_StaticLoopbackIndex_MatchesLoopbackNetworkInterface() { Assert.True(Capability.IPv4Support()); @@ -156,7 +154,6 @@ public void BasicTest_StaticLoopbackIndex_MatchesLoopbackNetworkInterface() [Fact] [Trait("IPv4", "true")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public void BasicTest_StaticLoopbackIndex_ExceptionIfV4NotSupported() { Assert.True(Capability.IPv4Support()); @@ -166,7 +163,6 @@ public void BasicTest_StaticLoopbackIndex_ExceptionIfV4NotSupported() [Fact] [Trait("IPv6", "true")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public void BasicTest_StaticIPv6LoopbackIndex_MatchesLoopbackNetworkInterface() { Assert.True(Capability.IPv6Support()); @@ -191,7 +187,6 @@ public void BasicTest_StaticIPv6LoopbackIndex_MatchesLoopbackNetworkInterface() [Fact] [Trait("IPv6", "true")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public void BasicTest_StaticIPv6LoopbackIndex_ExceptionIfV6NotSupported() { Assert.True(Capability.IPv6Support()); @@ -272,8 +267,6 @@ public void BasicTest_GetIPInterfaceStatistics_Success_Bsd() [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/36890", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public void BasicTest_GetIsNetworkAvailable_Success() { Assert.True(NetworkInterface.GetIsNetworkAvailable()); @@ -285,7 +278,6 @@ public void BasicTest_GetIsNetworkAvailable_Success() [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] [InlineData(false)] [InlineData(true)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50567", TestPlatforms.Android)] public async Task NetworkInterface_LoopbackInterfaceIndex_MatchesReceivedPackets(bool ipv6) { using (var client = new Socket(SocketType.Dgram, ProtocolType.Udp)) diff --git a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs index 52aceb0d3f9c14..9b73374e99b267 100644 --- a/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/tests/FunctionalTests/NetworkInterfaceIPv4Statistics.cs @@ -69,6 +69,17 @@ public void BasicTest_GetIPv4InterfaceStatistics_Success_Linux() } } + [Fact] + [PlatformSpecific(TestPlatforms.Android)] // This API is not supported on Android + public void BasicTest_GetIPv4InterfaceStatistics_NotSupported_Android() + { + // This API is not actually IPv4 specific. + foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) + { + Assert.Throws(() => nic.GetIPv4Statistics()); + } + } + [Fact] [PlatformSpecific(TestPlatforms.OSX)] // Some APIs are not supported on OSX public void BasicTest_GetIPv4InterfaceStatistics_Success_OSX() diff --git a/src/libraries/System.Net.Ping/tests/FunctionalTests/PingTest.cs b/src/libraries/System.Net.Ping/tests/FunctionalTests/PingTest.cs index b206e1e0f165d9..32ef250d8657eb 100644 --- a/src/libraries/System.Net.Ping/tests/FunctionalTests/PingTest.cs +++ b/src/libraries/System.Net.Ping/tests/FunctionalTests/PingTest.cs @@ -878,7 +878,9 @@ public async Task SendPingToExternalHostWithLowTtlTest() options.Ttl = 1; // This should always fail unless host is one IP hop away. pingReply = await ping.SendPingAsync(host, TestSettings.PingTimeout, TestSettings.PayloadAsBytesShort, options); - Assert.NotEqual(IPStatus.Success, pingReply.Status); + + Assert.True(pingReply.Status == IPStatus.TimeExceeded || pingReply.Status == IPStatus.TtlExpired); + Assert.NotEqual(IPAddress.Any, pingReply.Address); } [Fact] diff --git a/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs b/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs index 0d686f9a8ee4ad..b34f45bdd881f7 100644 --- a/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs +++ b/src/libraries/System.Net.Ping/tests/FunctionalTests/UnixPingUtilityTests.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Xunit; +using Microsoft.DotNet.XUnitExtensions; namespace System.Net.NetworkInformation.Tests { @@ -19,7 +20,7 @@ public class UnixPingUtilityTests { private const int IcmpHeaderLengthInBytes = 8; - [Theory] + [ConditionalTheory] [InlineData(0)] [InlineData(100)] [InlineData(1000)] @@ -32,13 +33,26 @@ public static void TimeoutIsRespected(int timeout) p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; + bool destinationNetUnreachable = false; + p.OutputDataReceived += delegate (object sendingProcess, DataReceivedEventArgs outputLine) + { + if (outputLine.Data?.Contains("Destination Net Unreachable", StringComparison.OrdinalIgnoreCase) == true) + destinationNetUnreachable = true; + }; + Stopwatch stopWatch = Stopwatch.StartNew(); p.Start(); + p.BeginOutputReadLine(); p.WaitForExit(); - //ensure that the process takes longer than or equal to 'timeout' - Assert.True(stopWatch.ElapsedMilliseconds >= timeout); + if (destinationNetUnreachable) + { + throw new SkipTestException($"Network doesn't route {TestSettings.UnreachableAddress}, skipping test."); + } + + //ensure that the process takes longer than or within 10ms of 'timeout', with a 5s maximum + Assert.InRange(stopWatch.ElapsedMilliseconds, timeout - 10, 5000); } [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] diff --git a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs index 790ad3feb2939d..be0b43d4200f37 100644 --- a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs +++ b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs @@ -109,6 +109,7 @@ public override void Flush() { } public override void SetLength(long value) { } public void Shutdown() { } public System.Threading.Tasks.ValueTask ShutdownCompleted(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public System.Threading.Tasks.ValueTask WaitForWriteCompletionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override void Write(byte[] buffer, int offset, int count) { } public override void Write(System.ReadOnlySpan buffer) { } public System.Threading.Tasks.ValueTask WriteAsync(System.Buffers.ReadOnlySequence buffers, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 4549842ee8e681..58f158d9a6cef5 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -100,7 +100,8 @@ + GeneratePathProperty="true" + Condition="'$(DotNetBuildFromSource)' != 'true'" /> @@ -128,7 +129,7 @@ + ('$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'x86') and '$(DotNetBuildFromSource)' != 'true'"> diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs index 7487a958db91f9..e409b962d0296e 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs @@ -8,6 +8,8 @@ using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; +using System.Collections.Concurrent; +using System.Collections.Generic; namespace System.Net.Quic.Implementations.Mock { @@ -244,6 +246,9 @@ internal MockStream OpenStream(long streamId, bool bidirectional) } MockStream.StreamState streamState = new MockStream.StreamState(streamId, bidirectional); + // TODO Streams are never removed from a connection. Consider cleaning up in the future. + state._streams[streamState._streamId] = streamState; + Channel streamChannel = _isClient ? state._clientInitiatedStreamChannel : state._serverInitiatedStreamChannel; streamChannel.Writer.TryWrite(streamState); @@ -320,6 +325,12 @@ internal override ValueTask CloseAsync(long errorCode, CancellationToken cancell state._serverErrorCode = errorCode; DrainAcceptQueue(errorCode, -1); } + + foreach (KeyValuePair kvp in state._streams) + { + kvp.Value._outboundWritesCompletedTcs.TrySetException(new QuicConnectionAbortedException(errorCode)); + kvp.Value._inboundWritesCompletedTcs.TrySetException(new QuicConnectionAbortedException(errorCode)); + } } Dispose(); @@ -474,8 +485,9 @@ public PeerStreamLimit(int maxUnidirectional, int maxBidirectional) internal sealed class ConnectionState { public readonly SslApplicationProtocol _applicationProtocol; - public Channel _clientInitiatedStreamChannel; - public Channel _serverInitiatedStreamChannel; + public readonly Channel _clientInitiatedStreamChannel; + public readonly Channel _serverInitiatedStreamChannel; + public readonly ConcurrentDictionary _streams; public PeerStreamLimit? _clientStreamLimit; public PeerStreamLimit? _serverStreamLimit; @@ -490,6 +502,7 @@ public ConnectionState(SslApplicationProtocol applicationProtocol) _clientInitiatedStreamChannel = Channel.CreateUnbounded(); _serverInitiatedStreamChannel = Channel.CreateUnbounded(); _clientErrorCode = _serverErrorCode = -1; + _streams = new ConcurrentDictionary(); } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs index 588da85d32f420..fbace756f2fbda 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs @@ -164,6 +164,7 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool e if (endStream) { streamBuffer.EndWrite(); + WritesCompletedTcs.TrySetResult(); } } @@ -206,10 +207,12 @@ internal override void AbortRead(long errorCode) if (_isInitiator) { _streamState._outboundWriteErrorCode = errorCode; + _streamState._inboundWritesCompletedTcs.TrySetException(new QuicStreamAbortedException(errorCode)); } else { _streamState._inboundWriteErrorCode = errorCode; + _streamState._outboundWritesCompletedTcs.TrySetException(new QuicOperationAbortedException()); } ReadStreamBuffer?.AbortRead(); @@ -220,10 +223,12 @@ internal override void AbortWrite(long errorCode) if (_isInitiator) { _streamState._outboundReadErrorCode = errorCode; + _streamState._outboundWritesCompletedTcs.TrySetException(new QuicStreamAbortedException(errorCode)); } else { _streamState._inboundReadErrorCode = errorCode; + _streamState._inboundWritesCompletedTcs.TrySetException(new QuicOperationAbortedException()); } WriteStreamBuffer?.EndWrite(); @@ -251,6 +256,8 @@ internal override void Shutdown() { _connection.LocalStreamLimit!.Bidirectional.Decrement(); } + + WritesCompletedTcs.TrySetResult(); } private void CheckDisposed() @@ -283,6 +290,17 @@ public override ValueTask DisposeAsync() return default; } + internal override ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default) + { + CheckDisposed(); + + return new ValueTask(WritesCompletedTcs.Task); + } + + private TaskCompletionSource WritesCompletedTcs => _isInitiator + ? _streamState._outboundWritesCompletedTcs + : _streamState._inboundWritesCompletedTcs; + internal sealed class StreamState { public readonly long _streamId; @@ -292,6 +310,8 @@ internal sealed class StreamState public long _inboundReadErrorCode; public long _outboundWriteErrorCode; public long _inboundWriteErrorCode; + public TaskCompletionSource _outboundWritesCompletedTcs; + public TaskCompletionSource _inboundWritesCompletedTcs; private const int InitialBufferSize = #if DEBUG @@ -310,6 +330,8 @@ public StreamState(long streamId, bool bidirectional) _streamId = streamId; _outboundStreamBuffer = new StreamBuffer(initialBufferSize: InitialBufferSize, maxBufferSize: MaxBufferSize); _inboundStreamBuffer = (bidirectional ? new StreamBuffer() : null); + _outboundWritesCompletedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + _inboundWritesCompletedTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index ddd002d59d2c2e..e67f2ee60846f3 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -283,6 +283,11 @@ private static uint HandleEventShutdownInitiatedByTransport(State state, ref Con state.ConnectTcs = null; } + // To throw QuicConnectionAbortedException (instead of QuicOperationAbortedException) out of AcceptStreamAsync() since + // it wasn't our side who shutdown the connection. + // We should rather keep the Status and propagate it either in a different exception or as a different field of QuicConnectionAbortedException. + // See: https://github.com/dotnet/runtime/issues/60133 + state.AbortErrorCode = 0; state.AcceptQueue.Writer.TryComplete(); return MsQuicStatusCodes.Success; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs index bbaf9c4ed41bb7..54f0ed3f4ec85b 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs @@ -69,6 +69,11 @@ private sealed class State // Resettable completions to be used for multiple calls to send. public readonly ResettableCompletionSource SendResettableCompletionSource = new ResettableCompletionSource(); + public ShutdownWriteState ShutdownWriteState; + + // Set once writes have been shutdown. + public readonly TaskCompletionSource ShutdownWriteCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + public ShutdownState ShutdownState; // The value makes sure that we release the handles only once. public int ShutdownDone; @@ -95,6 +100,14 @@ public void Cleanup() // inbound. internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) { + if (!connectionState.TryAddStream(this)) + { + throw new ObjectDisposedException(nameof(QuicConnection)); + } + // this assignment should be done before SetCallbackHandlerDelegate to prevent NRE in HandleEventConnectionClose + // but after TryAddStream to prevent unnecessary RemoveStream in finalizer + _state.ConnectionState = connectionState; + _state.Handle = streamHandle; _canRead = true; _canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); @@ -117,14 +130,6 @@ internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHa throw; } - if (!connectionState.TryAddStream(this)) - { - _state.StateGCHandle.Free(); - throw new ObjectDisposedException(nameof(QuicConnection)); - } - - _state.ConnectionState = connectionState; - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { @@ -140,6 +145,14 @@ internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_F { Debug.Assert(connectionState.Handle != null); + if (!connectionState.TryAddStream(this)) + { + throw new ObjectDisposedException(nameof(QuicConnection)); + } + // this assignment should be done before StreamOpenDelegate to prevent NRE in HandleEventConnectionClose + // but after TryAddStream to prevent unnecessary RemoveStream in finalizer + _state.ConnectionState = connectionState; + _canRead = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); _canWrite = true; @@ -170,15 +183,6 @@ internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_F throw; } - if (!connectionState.TryAddStream(this)) - { - _state.Handle?.Dispose(); - _state.StateGCHandle.Free(); - throw new ObjectDisposedException(nameof(QuicConnection)); - } - - _state.ConnectionState = connectionState; - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { @@ -265,7 +269,7 @@ internal override async ValueTask WriteAsync(ReadOnlySequence buffers, boo { ThrowIfDisposed(); - using CancellationTokenRegistration registration = HandleWriteStartState(cancellationToken); + using CancellationTokenRegistration registration = HandleWriteStartState(buffers.IsEmpty, cancellationToken); await SendReadOnlySequenceAsync(buffers, endStream ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE).ConfigureAwait(false); @@ -281,7 +285,7 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory { ThrowIfDisposed(); - using CancellationTokenRegistration registration = HandleWriteStartState(cancellationToken); + using CancellationTokenRegistration registration = HandleWriteStartState(buffers.IsEmpty, cancellationToken); await SendReadOnlyMemoryListAsync(buffers, endStream ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE).ConfigureAwait(false); @@ -292,20 +296,20 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool e { ThrowIfDisposed(); - using CancellationTokenRegistration registration = HandleWriteStartState(cancellationToken); + using CancellationTokenRegistration registration = HandleWriteStartState(buffer.IsEmpty, cancellationToken); await SendReadOnlyMemoryAsync(buffer, endStream ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE).ConfigureAwait(false); HandleWriteCompletedState(); } - private CancellationTokenRegistration HandleWriteStartState(CancellationToken cancellationToken) + private CancellationTokenRegistration HandleWriteStartState(bool emptyBuffer, CancellationToken cancellationToken) { if (_state.SendState == SendState.Closed) { throw new InvalidOperationException(SR.net_quic_writing_notallowed); } - else if ( _state.SendState == SendState.Aborted) + if (_state.SendState == SendState.Aborted) { if (_state.SendErrorCode != -1) { @@ -363,10 +367,14 @@ private CancellationTokenRegistration HandleWriteStartState(CancellationToken ca throw new OperationCanceledException(SR.net_quic_sending_aborted); } - else if (_state.SendState == SendState.ConnectionClosed) + if (_state.SendState == SendState.ConnectionClosed) { throw GetConnectionAbortedException(_state); } + + // Change the state in the same lock where we check for final states to prevent coming back from Aborted/ConnectionClosed. + Debug.Assert(_state.SendState != SendState.Pending); + _state.SendState = emptyBuffer ? SendState.Finished : SendState.Pending; } return registration; @@ -574,12 +582,26 @@ internal override void AbortWrite(long errorCode) return; } + bool shouldComplete = false; + lock (_state) { if (_state.SendState < SendState.Aborted) { _state.SendState = SendState.Aborted; } + + if (_state.ShutdownWriteState == ShutdownWriteState.None) + { + _state.ShutdownWriteState = ShutdownWriteState.Canceled; + shouldComplete = true; + } + } + + if (shouldComplete) + { + _state.ShutdownWriteCompletionSource.SetException( + ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException("Write was aborted."))); } StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_SEND, errorCode); @@ -626,13 +648,33 @@ internal override async ValueTask ShutdownCompleted(CancellationToken cancellati await _state.ShutdownCompletionSource.Task.ConfigureAwait(false); } + internal override ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default) + { + // TODO: What should happen if this is called for a unidirectional stream and there are no writes? + + ThrowIfDisposed(); + + lock (_state) + { + if (_state.ShutdownWriteState == ShutdownWriteState.ConnectionClosed) + { + throw GetConnectionAbortedException(_state); + } + } + + return new ValueTask(_state.ShutdownWriteCompletionSource.Task.WaitAsync(cancellationToken)); + } + internal override void Shutdown() { ThrowIfDisposed(); lock (_state) { - _state.SendState = SendState.Finished; + if (_state.SendState < SendState.Finished) + { + _state.SendState = SendState.Finished; + } } // it is ok to send shutdown several times, MsQuic will ignore it @@ -855,6 +897,11 @@ private static uint HandleEvent(State state, ref StreamEvent evt) // Peer has stopped receiving data, don't send anymore. case QUIC_STREAM_EVENT_TYPE.PEER_RECEIVE_ABORTED: return HandleEventPeerRecvAborted(state, ref evt); + // Occurs when shutdown is completed for the send side. + // This only happens for shutdown on sending, not receiving + // Receive shutdown can only be abortive. + case QUIC_STREAM_EVENT_TYPE.SEND_SHUTDOWN_COMPLETE: + return HandleEventSendShutdownComplete(state, ref evt); // Shutdown for both sending and receiving is completed. case QUIC_STREAM_EVENT_TYPE.SHUTDOWN_COMPLETE: return HandleEventShutdownComplete(state, ref evt); @@ -987,23 +1034,37 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) private static uint HandleEventPeerRecvAborted(State state, ref StreamEvent evt) { - bool shouldComplete = false; + bool shouldSendComplete = false; + bool shouldShutdownWriteComplete = false; lock (state) { if (state.SendState == SendState.None || state.SendState == SendState.Pending) { - shouldComplete = true; + shouldSendComplete = true; + } + + if (state.ShutdownWriteState == ShutdownWriteState.None) + { + state.ShutdownWriteState = ShutdownWriteState.Canceled; + shouldShutdownWriteComplete = true; } + state.SendState = SendState.Aborted; state.SendErrorCode = (long)evt.Data.PeerReceiveAborted.ErrorCode; } - if (shouldComplete) + if (shouldSendComplete) { state.SendResettableCompletionSource.CompleteException( ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.SendErrorCode))); } + if (shouldShutdownWriteComplete) + { + state.ShutdownWriteCompletionSource.SetException( + ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.SendErrorCode))); + } + return MsQuicStatusCodes.Success; } @@ -1015,6 +1076,38 @@ private static uint HandleEventStartComplete(State state, ref StreamEvent evt) return MsQuicStatusCodes.Success; } + private static uint HandleEventSendShutdownComplete(State state, ref StreamEvent evt) + { + // Graceful will be false in three situations: + // 1. The peer aborted reads and the PEER_RECEIVE_ABORTED event was raised. + // ShutdownWriteCompletionSource is already complete with an error. + // 2. We aborted writes. + // ShutdownWriteCompletionSource is already complete with an error. + // 3. The connection was closed. + // SHUTDOWN_COMPLETE event will be raised immediately after this event. It will handle completing with an error. + // + // Only use this event with sends gracefully completed. + if (evt.Data.SendShutdownComplete.Graceful != 0) + { + bool shouldComplete = false; + lock (state) + { + if (state.ShutdownWriteState == ShutdownWriteState.None) + { + state.ShutdownWriteState = ShutdownWriteState.Finished; + shouldComplete = true; + } + } + + if (shouldComplete) + { + state.ShutdownWriteCompletionSource.SetResult(); + } + } + + return MsQuicStatusCodes.Success; + } + private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt) { StreamEventDataShutdownComplete shutdownCompleteEvent = evt.Data.ShutdownComplete; @@ -1025,6 +1118,7 @@ private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt } bool shouldReadComplete = false; + bool shouldShutdownWriteComplete = false; bool shouldShutdownComplete = false; lock (state) @@ -1034,6 +1128,15 @@ private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt shouldReadComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted); + if (state.ShutdownWriteState == ShutdownWriteState.None) + { + // TODO: We can get to this point if the stream is unidirectional and there are no writes. + // Consider what is the best behavior here with write shutdown and the read side of + // unidirecitonal streams in the future. + state.ShutdownWriteState = ShutdownWriteState.Finished; + shouldShutdownWriteComplete = true; + } + if (state.ShutdownState == ShutdownState.None) { state.ShutdownState = ShutdownState.Finished; @@ -1046,6 +1149,11 @@ private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt state.ReceiveResettableCompletionSource.Complete(0); } + if (shouldShutdownWriteComplete) + { + state.ShutdownWriteCompletionSource.SetResult(); + } + if (shouldShutdownComplete) { state.ShutdownCompletionSource.SetResult(); @@ -1157,12 +1265,6 @@ private unsafe ValueTask SendReadOnlyMemoryAsync( ReadOnlyMemory buffer, QUIC_SEND_FLAGS flags) { - lock (_state) - { - Debug.Assert(_state.SendState != SendState.Pending); - _state.SendState = buffer.IsEmpty ? SendState.Finished : SendState.Pending; - } - if (buffer.IsEmpty) { if ((flags & QUIC_SEND_FLAGS.FIN) == QUIC_SEND_FLAGS.FIN) @@ -1211,13 +1313,6 @@ private unsafe ValueTask SendReadOnlySequenceAsync( ReadOnlySequence buffers, QUIC_SEND_FLAGS flags) { - - lock (_state) - { - Debug.Assert(_state.SendState != SendState.Pending); - _state.SendState = buffers.IsEmpty ? SendState.Finished : SendState.Pending; - } - if (buffers.IsEmpty) { if ((flags & QUIC_SEND_FLAGS.FIN) == QUIC_SEND_FLAGS.FIN) @@ -1281,12 +1376,6 @@ private unsafe ValueTask SendReadOnlyMemoryListAsync( ReadOnlyMemory> buffers, QUIC_SEND_FLAGS flags) { - lock (_state) - { - Debug.Assert(_state.SendState != SendState.Pending); - _state.SendState = buffers.IsEmpty ? SendState.Finished : SendState.Pending; - } - if (buffers.IsEmpty) { if ((flags & QUIC_SEND_FLAGS.FIN) == QUIC_SEND_FLAGS.FIN) @@ -1374,6 +1463,7 @@ private static uint HandleEventConnectionClose(State state) bool shouldCompleteRead = false; bool shouldCompleteSend = false; + bool shouldCompleteShutdownWrite = false; bool shouldCompleteShutdown = false; lock (state) @@ -1386,6 +1476,12 @@ private static uint HandleEventConnectionClose(State state) } state.SendState = SendState.ConnectionClosed; + if (state.ShutdownWriteState == ShutdownWriteState.None) + { + shouldCompleteShutdownWrite = true; + } + state.ShutdownWriteState = ShutdownWriteState.ConnectionClosed; + if (state.ShutdownState == ShutdownState.None) { shouldCompleteShutdown = true; @@ -1405,6 +1501,12 @@ private static uint HandleEventConnectionClose(State state) ExceptionDispatchInfo.SetCurrentStackTrace(GetConnectionAbortedException(state))); } + if (shouldCompleteShutdownWrite) + { + state.ShutdownWriteCompletionSource.SetException( + ExceptionDispatchInfo.SetCurrentStackTrace(GetConnectionAbortedException(state))); + } + if (shouldCompleteShutdown) { state.ShutdownCompletionSource.SetException( @@ -1506,6 +1608,14 @@ private enum ReadState Closed } + private enum ShutdownWriteState + { + None = 0, + Canceled, + Finished, + ConnectionClosed + } + private enum ShutdownState { None = 0, diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs index 66c9a8b6e51c2d..215ce1304c1a4d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs @@ -47,6 +47,8 @@ internal abstract class QuicStreamProvider : IDisposable, IAsyncDisposable internal abstract ValueTask ShutdownCompleted(CancellationToken cancellationToken = default); + internal abstract ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default); + internal abstract void Shutdown(); internal abstract void Flush(); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index 8a6dbe496ed4a4..912d32c9ad889c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -117,6 +117,8 @@ public override int WriteTimeout public ValueTask ShutdownCompleted(CancellationToken cancellationToken = default) => _provider.ShutdownCompleted(cancellationToken); + public ValueTask WaitForWriteCompletionAsync(CancellationToken cancellationToken = default) => _provider.WaitForWriteCompletionAsync(cancellationToken); + public void Shutdown() => _provider.Shutdown(); protected override void Dispose(bool disposing) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index 9e3cc64cae132d..809b9a3ba8035a 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -104,7 +104,6 @@ public async Task ConnectWithCertificateChain() } [Fact] - [PlatformSpecific(TestPlatforms.Windows)] public async Task UntrustedClientCertificateFails() { var listenerOptions = new QuicListenerOptions(); @@ -330,7 +329,6 @@ public async Task ConnectWithCertificateForLoopbackIP_IndicatesExpectedError(str } [Theory] - [PlatformSpecific(TestPlatforms.Windows)] [InlineData(true)] // [InlineData(false)] [ActiveIssue("https://github.com/dotnet/runtime/issues/57308")] public async Task ConnectWithClientCertificate(bool sendCerttificate) diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs index 098bd4d2af1d2f..ed371262c924c2 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -769,6 +769,230 @@ await RunClientServer( } ); } + + [Fact] + public async Task WaitForWriteCompletionAsync_ClientReadAborted_Throws() + { + const int ExpectedErrorCode = 0xfffffff; + + TaskCompletionSource waitForAbortTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + SemaphoreSlim sem = new SemaphoreSlim(0); + + await RunBidirectionalClientServer( + async clientStream => + { + await clientStream.WriteAsync(new byte[1], endStream: true); + + // Wait for server to read data + await sem.WaitAsync(); + + clientStream.AbortRead(ExpectedErrorCode); + }, + async serverStream => + { + var writeCompletionTask = ReleaseOnWriteCompletionAsync(); + + int received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(1, received); + received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(0, received); + + Assert.False(writeCompletionTask.IsCompleted, "Server is still writing."); + + // Tell client that data has been read and it can abort its reads. + sem.Release(); + + long sendAbortErrorCode = await waitForAbortTcs.Task; + Assert.Equal(ExpectedErrorCode, sendAbortErrorCode); + + await writeCompletionTask; + + async ValueTask ReleaseOnWriteCompletionAsync() + { + try + { + await serverStream.WaitForWriteCompletionAsync(); + waitForAbortTcs.SetException(new Exception("WaitForWriteCompletionAsync didn't throw stream aborted.")); + } + catch (QuicStreamAbortedException ex) + { + waitForAbortTcs.SetResult(ex.ErrorCode); + } + catch (Exception ex) + { + waitForAbortTcs.SetException(ex); + } + }; + }); + } + + [Fact] + public async Task WaitForWriteCompletionAsync_ServerWriteAborted_Throws() + { + const int ExpectedErrorCode = 0xfffffff; + + TaskCompletionSource waitForAbortTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + await RunBidirectionalClientServer( + async clientStream => + { + await clientStream.WriteAsync(new byte[1], endStream: true); + }, + async serverStream => + { + var writeCompletionTask = ReleaseOnWriteCompletionAsync(); + + int received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(1, received); + received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(0, received); + + Assert.False(writeCompletionTask.IsCompleted, "Server is still writing."); + + serverStream.AbortWrite(ExpectedErrorCode); + + await waitForAbortTcs.Task; + await writeCompletionTask; + + async ValueTask ReleaseOnWriteCompletionAsync() + { + try + { + await serverStream.WaitForWriteCompletionAsync(); + waitForAbortTcs.SetException(new Exception("WaitForWriteCompletionAsync didn't throw stream aborted.")); + } + catch (QuicOperationAbortedException) + { + waitForAbortTcs.SetResult(); + } + catch (Exception ex) + { + waitForAbortTcs.SetException(ex); + } + }; + }); + } + + [Fact] + public async Task WaitForWriteCompletionAsync_ServerShutdown_Success() + { + await RunBidirectionalClientServer( + async clientStream => + { + await clientStream.WriteAsync(new byte[1], endStream: true); + + int readCount = await clientStream.ReadAsync(new byte[1]); + Assert.Equal(1, readCount); + + readCount = await clientStream.ReadAsync(new byte[1]); + Assert.Equal(0, readCount); + }, + async serverStream => + { + var writeCompletionTask = serverStream.WaitForWriteCompletionAsync(); + + int received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(1, received); + received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(0, received); + + await serverStream.WriteAsync(new byte[1]); + + Assert.False(writeCompletionTask.IsCompleted, "Server is still writing."); + + serverStream.Shutdown(); + + await writeCompletionTask; + }); + } + + [Fact] + public async Task WaitForWriteCompletionAsync_GracefulShutdown_Success() + { + await RunBidirectionalClientServer( + async clientStream => + { + await clientStream.WriteAsync(new byte[1], endStream: true); + + int readCount = await clientStream.ReadAsync(new byte[1]); + Assert.Equal(1, readCount); + + readCount = await clientStream.ReadAsync(new byte[1]); + Assert.Equal(0, readCount); + }, + async serverStream => + { + var writeCompletionTask = serverStream.WaitForWriteCompletionAsync(); + + int received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(1, received); + received = await serverStream.ReadAsync(new byte[1]); + Assert.Equal(0, received); + + Assert.False(writeCompletionTask.IsCompleted, "Server is still writing."); + + await serverStream.WriteAsync(new byte[1], endStream: true); + + await writeCompletionTask; + }); + } + + [Fact] + public async Task WaitForWriteCompletionAsync_ConnectionClosed_Throws() + { + const int ExpectedErrorCode = 0xfffffff; + + using SemaphoreSlim sem = new SemaphoreSlim(0); + TaskCompletionSource waitForAbortTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + await RunClientServer( + serverFunction: async connection => + { + await using QuicStream stream = await connection.AcceptStreamAsync(); + + var writeCompletionTask = ReleaseOnWriteCompletionAsync(); + + int received = await stream.ReadAsync(new byte[1]); + Assert.Equal(1, received); + received = await stream.ReadAsync(new byte[1]); + Assert.Equal(0, received); + + // Signal that the server has read data + sem.Release(); + + long closeErrorCode = await waitForAbortTcs.Task; + Assert.Equal(ExpectedErrorCode, closeErrorCode); + + await writeCompletionTask; + + async ValueTask ReleaseOnWriteCompletionAsync() + { + try + { + await stream.WaitForWriteCompletionAsync(); + waitForAbortTcs.SetException(new Exception("WaitForWriteCompletionAsync didn't throw connection aborted.")); + } + catch (QuicConnectionAbortedException ex) + { + waitForAbortTcs.SetResult(ex.ErrorCode); + } + }; + }, + clientFunction: async connection => + { + await using QuicStream stream = connection.OpenBidirectionalStream(); + + await stream.WriteAsync(new byte[1], endStream: true); + + await stream.WaitForWriteCompletionAsync(); + + // Wait for the server to read data before closing the connection + await sem.WaitAsync(); + + await connection.CloseAsync(ExpectedErrorCode); + } + ); + } } public sealed class QuicStreamTests_MockProvider : QuicStreamTests diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Linux.cs b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Linux.cs index 0ddef7980c836f..d59c76ce47228a 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Linux.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/CipherSuitesPolicyPal.Linux.cs @@ -28,7 +28,7 @@ internal sealed class CipherSuitesPolicyPal internal CipherSuitesPolicyPal(IEnumerable allowedCipherSuites) { - if (!Interop.Ssl.Tls13Supported) + if (!Interop.Ssl.Capabilities.Tls13Supported) { throw new PlatformNotSupportedException(SR.net_ssl_ciphersuites_policy_not_supported); } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs index 10dd32c0316519..adb6680fb999bf 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SecureChannel.cs @@ -695,11 +695,13 @@ private bool AcquireServerCredentials(ref byte[]? thumbPrint) _sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(selectedCert); } + Debug.Assert(_sslAuthenticationOptions.CertificateContext != null); // // Note selectedCert is a safe ref possibly cloned from the user passed Cert object // byte[] guessedThumbPrint = selectedCert.GetCertHash(); - SafeFreeCredentials? cachedCredentialHandle = SslSessionsCache.TryCachedCredential(guessedThumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy); + bool sendTrustedList = _sslAuthenticationOptions.CertificateContext!.Trust?._sendTrustInHandshake ?? false; + SafeFreeCredentials? cachedCredentialHandle = SslSessionsCache.TryCachedCredential(guessedThumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy, sendTrustedList); if (cachedCredentialHandle != null) { @@ -763,6 +765,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte byte[]? result = Array.Empty(); SecurityStatusPal status = default; bool cachedCreds = false; + bool sendTrustList = false; byte[]? thumbPrint = null; // @@ -779,6 +782,11 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte cachedCreds = _sslAuthenticationOptions.IsServer ? AcquireServerCredentials(ref thumbPrint) : AcquireClientCredentials(ref thumbPrint); + + if (cachedCreds && _sslAuthenticationOptions.IsServer) + { + sendTrustList = _sslAuthenticationOptions.CertificateContext?.Trust?._sendTrustInHandshake ?? false; + } } if (_sslAuthenticationOptions.IsServer) @@ -820,7 +828,7 @@ private SecurityStatusPal GenerateToken(ReadOnlySpan inputBuffer, ref byte // if (!cachedCreds && _securityContext != null && !_securityContext.IsInvalid && _credentialsHandle != null && !_credentialsHandle.IsInvalid) { - SslSessionsCache.CacheCredential(_credentialsHandle, thumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy); + SslSessionsCache.CacheCredential(_credentialsHandle, thumbPrint, _sslAuthenticationOptions.EnabledSslProtocols, _sslAuthenticationOptions.IsServer, _sslAuthenticationOptions.EncryptionPolicy, sendTrustList); } } } diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslSessionsCache.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslSessionsCache.cs index 13e4f772f6b3b9..35eb4ec534b83d 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslSessionsCache.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslSessionsCache.cs @@ -25,18 +25,20 @@ internal static class SslSessionsCache private readonly int _allowedProtocols; private readonly EncryptionPolicy _encryptionPolicy; private readonly bool _isServerMode; + private readonly bool _sendTrustList; // // SECURITY: X509Certificate.GetCertHash() is virtual hence before going here, // the caller of this ctor has to ensure that a user cert object was inspected and // optionally cloned. // - internal SslCredKey(byte[]? thumbPrint, int allowedProtocols, bool isServerMode, EncryptionPolicy encryptionPolicy) + internal SslCredKey(byte[]? thumbPrint, int allowedProtocols, bool isServerMode, EncryptionPolicy encryptionPolicy, bool sendTrustList) { _thumbPrint = thumbPrint ?? Array.Empty(); _allowedProtocols = allowedProtocols; _encryptionPolicy = encryptionPolicy; _isServerMode = isServerMode; + _sendTrustList = sendTrustList; } public override int GetHashCode() @@ -65,6 +67,7 @@ public override int GetHashCode() hashCode ^= _allowedProtocols; hashCode ^= (int)_encryptionPolicy; hashCode ^= _isServerMode ? 0x10000 : 0x20000; + hashCode ^= _sendTrustList ? 0x40000 : 0x80000; return hashCode; } @@ -96,6 +99,11 @@ public bool Equals(SslCredKey other) return false; } + if (_sendTrustList != other._sendTrustList) + { + return false; + } + for (int i = 0; i < thumbPrint.Length; ++i) { if (thumbPrint[i] != otherThumbPrint[i]) @@ -114,7 +122,7 @@ public bool Equals(SslCredKey other) // ATTN: The returned handle can be invalid, the callers of InitializeSecurityContext and AcceptSecurityContext // must be prepared to execute a back-out code if the call fails. // - internal static SafeFreeCredentials? TryCachedCredential(byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy) + internal static SafeFreeCredentials? TryCachedCredential(byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy, bool sendTrustList = false) { if (s_cachedCreds.IsEmpty) { @@ -122,7 +130,7 @@ public bool Equals(SslCredKey other) return null; } - var key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy); + var key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy, sendTrustList); //SafeCredentialReference? cached; SafeFreeCredentials? credentials = GetCachedCredential(key); @@ -147,7 +155,7 @@ public bool Equals(SslCredKey other) // // ATTN: The thumbPrint must be from inspected and possibly cloned user Cert object or we get a security hole in SslCredKey ctor. // - internal static void CacheCredential(SafeFreeCredentials creds, byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy) + internal static void CacheCredential(SafeFreeCredentials creds, byte[]? thumbPrint, SslProtocols sslProtocols, bool isServer, EncryptionPolicy encryptionPolicy, bool sendTrustList = false) { Debug.Assert(creds != null, "creds == null"); @@ -157,7 +165,7 @@ internal static void CacheCredential(SafeFreeCredentials creds, byte[]? thumbPri return; } - SslCredKey key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy); + SslCredKey key = new SslCredKey(thumbPrint, (int)sslProtocols, isServer, encryptionPolicy, sendTrustList); SafeFreeCredentials? credentials = GetCachedCredential(key); diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs index 29ab3bed0ee8c6..1824e9b0233123 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs @@ -124,8 +124,8 @@ public static SafeFreeCredentials AcquireCredentialsHandle(SslStreamCertificateC { // New crypto API supports TLS1.3 but it does not allow to force NULL encryption. SafeFreeCredentials cred = !UseNewCryptoApi || policy == EncryptionPolicy.NoEncryption ? - AcquireCredentialsHandleSchannelCred(certificateContext?.Certificate, protocols, policy, isServer) : - AcquireCredentialsHandleSchCredentials(certificateContext?.Certificate, protocols, policy, isServer); + AcquireCredentialsHandleSchannelCred(certificateContext, protocols, policy, isServer) : + AcquireCredentialsHandleSchCredentials(certificateContext, protocols, policy, isServer); if (certificateContext != null && certificateContext.Trust != null && certificateContext.Trust._sendTrustInHandshake) { AttachCertificateStore(cred, certificateContext.Trust._store!); @@ -157,8 +157,9 @@ private static unsafe void AttachCertificateStore(SafeFreeCredentials cred, X509 // This is legacy crypto API used on .NET Framework and older Windows versions. // It only supports TLS up to 1.2 - public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(X509Certificate2? certificate, SslProtocols protocols, EncryptionPolicy policy, bool isServer) + public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(SslStreamCertificateContext? certificateContext, SslProtocols protocols, EncryptionPolicy policy, bool isServer) { + X509Certificate2? certificate = certificateContext?.Certificate; int protocolFlags = GetProtocolFlagsFromSslProtocols(protocols, isServer); Interop.SspiCli.SCHANNEL_CRED.Flags flags; Interop.SspiCli.CredentialUse direction; @@ -183,6 +184,10 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(X5 { direction = Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND; flags = Interop.SspiCli.SCHANNEL_CRED.Flags.SCH_SEND_AUX_RECORD; + if (certificateContext?.Trust?._sendTrustInHandshake == true) + { + flags |= Interop.SspiCli.SCHANNEL_CRED.Flags.SCH_CRED_NO_SYSTEM_MAPPER; + } } if (NetEventSource.Log.IsEnabled()) NetEventSource.Info($"flags=({flags}), ProtocolFlags=({protocolFlags}), EncryptionPolicy={policy}"); @@ -203,8 +208,9 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchannelCred(X5 } // This function uses new crypto API to support TLS 1.3 and beyond. - public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials(X509Certificate2? certificate, SslProtocols protocols, EncryptionPolicy policy, bool isServer) + public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials(SslStreamCertificateContext? certificateContext, SslProtocols protocols, EncryptionPolicy policy, bool isServer) { + X509Certificate2? certificate = certificateContext?.Certificate; int protocolFlags = GetProtocolFlagsFromSslProtocols(protocols, isServer); Interop.SspiCli.SCH_CREDENTIALS.Flags flags; Interop.SspiCli.CredentialUse direction; @@ -212,6 +218,10 @@ public static unsafe SafeFreeCredentials AcquireCredentialsHandleSchCredentials( { direction = Interop.SspiCli.CredentialUse.SECPKG_CRED_INBOUND; flags = Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_SEND_AUX_RECORD; + if (certificateContext?.Trust?._sendTrustInHandshake == true) + { + flags |= Interop.SspiCli.SCH_CREDENTIALS.Flags.SCH_CRED_NO_SYSTEM_MAPPER; + } } else { diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/LoggingTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/LoggingTest.cs index 60320d78a0ce2e..1b99f0cd4d85ae 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/LoggingTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/LoggingTest.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using Microsoft.DotNet.RemoteExecutor; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Net.Security.Tests @@ -26,6 +27,12 @@ public void EventSource_ExistsWithCorrectId() [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public void EventSource_EventsRaisedAsExpected() { + if (PlatformDetection.IsWindows10Version22000OrGreater) + { + // [ActiveIssue("https://github.com/dotnet/runtime/issues/58927")] + throw new SkipTestException("Unstable on Windows 11"); + } + RemoteExecutor.Invoke(() => { using (var listener = new TestEventListener("Private.InternalDiagnostics.System.Net.Security", EventLevel.Verbose)) diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs index 3428ba78845d48..285b6f1ff87952 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs @@ -413,6 +413,12 @@ await Assert.ThrowsAsync(()=> [PlatformSpecific(TestPlatforms.Windows)] public async Task SslStream_NegotiateClientCertificateAsyncTls13_Succeeds(bool sendClientCertificate) { + if (PlatformDetection.IsWindows10Version22000OrGreater) + { + // [ActiveIssue("https://github.com/dotnet/runtime/issues/58927")] + throw new SkipTestException("Unstable on Windows 11"); + } + bool negotiateClientCertificateCalled = false; using CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(TestConfiguration.PassingTestTimeout); diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs index 3ecfbc4e92493f..b05fbc6f53bc44 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamStreamToStreamTest.cs @@ -11,6 +11,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Net.Security.Tests @@ -66,11 +67,18 @@ public static IEnumerable SslStream_StreamToStream_Authentication_Succ } } - [Theory] + [ConditionalTheory] [MemberData(nameof(SslStream_StreamToStream_Authentication_Success_MemberData))] [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "X509 certificate store is not supported on iOS or tvOS.")] public async Task SslStream_StreamToStream_Authentication_Success(X509Certificate serverCert = null, X509Certificate clientCert = null) { + + if (PlatformDetection.IsWindows10Version22000OrGreater) + { + // [ActiveIssue("https://github.com/dotnet/runtime/issues/58927")] + throw new SkipTestException("Unstable on Windows 11"); + } + (Stream stream1, Stream stream2) = TestHelper.GetConnectedStreams(); using (var client = new SslStream(stream1, false, AllowAnyServerCertificate)) using (var server = new SslStream(stream2, false, delegate { return true; })) diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs index 5380b4027a6f76..8e6b2176f62cbc 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamSystemDefaultsTest.cs @@ -8,7 +8,7 @@ using System.Security.Cryptography.X509Certificates; using System.Security.Authentication; using System.Threading.Tasks; - +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Net.Security.Tests @@ -76,6 +76,12 @@ public static IEnumerable OneOrBothUseDefaulData() [MemberData(nameof(OneOrBothUseDefaulData))] public async Task ClientAndServer_OneOrBothUseDefault_Ok(SslProtocols? clientProtocols, SslProtocols? serverProtocols) { + if (PlatformDetection.IsWindows10Version22000OrGreater) + { + // [ActiveIssue("https://github.com/dotnet/runtime/issues/58927")] + throw new SkipTestException("Unstable on Windows 11"); + } + using (X509Certificate2 serverCertificate = Configuration.Certificates.GetServerCertificate()) using (X509Certificate2 clientCertificate = Configuration.Certificates.GetClientCertificate()) { diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DnsEndPointTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DnsEndPointTest.cs index 1e362a04819c0f..f23a1e835b7be3 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/DnsEndPointTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/DnsEndPointTest.cs @@ -272,7 +272,7 @@ public void Socket_ConnectAsyncDnsEndPoint_HostNotFound() bool willRaiseEvent = sock.ConnectAsync(args); if (willRaiseEvent) { - Assert.True(complete.WaitOne(TestSettings.PassingTestTimeout), "Timed out while waiting for connection"); + Assert.True(complete.WaitOne(TestSettings.PassingTestLongTimeout), "Timed out while waiting for connection"); complete.Dispose(); // only dispose on success as we know we're done with the instance } @@ -332,7 +332,7 @@ public void Socket_StaticConnectAsync_Success(SocketImplementationType type) if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, args)) { - Assert.True(complete.WaitOne(TestSettings.PassingTestTimeout), "Timed out while waiting for connection"); + Assert.True(complete.WaitOne(TestSettings.PassingTestLongTimeout), "Timed out while waiting for connection"); } Assert.Equal(SocketError.Success, args.SocketError); @@ -348,7 +348,7 @@ public void Socket_StaticConnectAsync_Success(SocketImplementationType type) if (Socket.ConnectAsync(SocketType.Stream, ProtocolType.Tcp, args)) { - Assert.True(complete.WaitOne(TestSettings.PassingTestTimeout), "Timed out while waiting for connection"); + Assert.True(complete.WaitOne(TestSettings.PassingTestLongTimeout), "Timed out while waiting for connection"); } complete.Dispose(); // only dispose on success as we know we're done with the instance @@ -404,7 +404,7 @@ public void Socket_StaticConnectAsync_HostNotFound() OnConnectAsyncCompleted(null, args); } - Assert.True(complete.WaitOne(TestSettings.PassingTestTimeout), "Timed out while waiting for connection"); + Assert.True(complete.WaitOne(TestSettings.PassingTestLongTimeout), "Timed out while waiting for connection"); complete.Dispose(); // only dispose on success as we know we're done with the instance AssertHostNotFoundOrNoData(args); diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs index cda5d75b48c303..aa0d967e9f783d 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendFile.cs @@ -235,45 +235,6 @@ public async Task SliceBuffers_Success() } } - [ActiveIssue("https://github.com/dotnet/runtime/issues/42534", TestPlatforms.Windows)] - [OuterLoop("Creates and sends a file several gigabytes long")] - [Fact] - public async Task GreaterThan2GBFile_SendsAllBytes() - { - const long FileLength = 100L + int.MaxValue; - - using var tmpFile = TempFile.Create(); - using (FileStream fs = File.Create(tmpFile.Path)) - { - fs.SetLength(FileLength); - } - - using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - using var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - listener.BindToAnonymousPort(IPAddress.Loopback); - listener.Listen(1); - - client.Connect(listener.LocalEndPoint); - using Socket server = listener.Accept(); - - await new Task[] - { - SendFileAsync(server, tmpFile.Path), - Task.Run(() => - { - byte[] buffer = new byte[100_000]; - long count = 0; - while (count < FileLength) - { - int received = client.Receive(buffer); - Assert.NotEqual(0, received); - count += received; - } - Assert.Equal(0, client.Available); - }) - }.WhenAllOrAnyFailed(); - } - [Fact] public async Task SendFileGetsCanceledByDispose() { @@ -503,4 +464,78 @@ public void EndSendFile_NullAsyncResult_Throws() Assert.Throws(() => s.EndSendFile(null)); } } + + // Running all cases of GreaterThan2GBFile_SendsAllBytes in parallel may attempt to allocate Min(ProcessorCount, Subclass_Count) * 2GB of disk space + // in extreme cases. Some CI machines may run out of disk space if this happens. + [Collection(nameof(NoParallelTests))] + public abstract class SendFile_NonParallel : SocketTestHelperBase where T : SocketHelperBase, new() + { + protected SendFile_NonParallel(ITestOutputHelper output) : base(output) + { + } + + [ActiveIssue("https://github.com/dotnet/runtime/issues/42534", TestPlatforms.Windows)] + [OuterLoop("Creates and sends a file several gigabytes long")] + [Fact] + public async Task GreaterThan2GBFile_SendsAllBytes() + { + const long FileLength = 100L + int.MaxValue; + + using var tmpFile = TempFile.Create(); + using (FileStream fs = File.Create(tmpFile.Path)) + { + fs.SetLength(FileLength); + } + + using var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + using var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + listener.BindToAnonymousPort(IPAddress.Loopback); + listener.Listen(1); + + client.Connect(listener.LocalEndPoint); + using Socket server = listener.Accept(); + + await new Task[] + { + SendFileAsync(server, tmpFile.Path), + Task.Run(() => + { + byte[] buffer = new byte[100_000]; + long count = 0; + while (count < FileLength) + { + int received = client.Receive(buffer); + Assert.NotEqual(0, received); + count += received; + } + Assert.Equal(0, client.Available); + }) + }.WhenAllOrAnyFailed(); + } + } + + public sealed class SendFile_NonParallel_SyncSpan : SendFile_NonParallel + { + public SendFile_NonParallel_SyncSpan(ITestOutputHelper output) : base(output) { } + } + + public sealed class SendFile_NonParallel_SyncSpanForceNonBlocking : SendFile_NonParallel + { + public SendFile_NonParallel_SyncSpanForceNonBlocking(ITestOutputHelper output) : base(output) { } + } + + public sealed class SendFile_NonParallel_ArraySync : SendFile_NonParallel + { + public SendFile_NonParallel_ArraySync(ITestOutputHelper output) : base(output) { } + } + + public sealed class SendFile_NonParallel_Task : SendFile_NonParallel + { + public SendFile_NonParallel_Task(ITestOutputHelper output) : base(output) { } + } + + public sealed class SendFile_NonParallel_Apm : SendFile_NonParallel + { + public SendFile_NonParallel_Apm(ITestOutputHelper output) : base(output) { } + } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs index 29c24352c1a76c..10ebc472f93be2 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/SendPacketsAsync.cs @@ -6,11 +6,14 @@ using System.Net.Test.Common; using System.Threading; +using Microsoft.DotNet.XUnitExtensions; + using Xunit; using Xunit.Abstractions; namespace System.Net.Sockets.Tests { + [Collection(nameof(NoParallelTests))] public class SendPacketsAsync { private readonly ITestOutputHelper _log; @@ -525,7 +528,10 @@ public void SendPacketsElement_FileStreamMultiPart_Success() } } - [Fact] + public static bool IsNotWindows11 = !PlatformDetection.IsWindows10Version22000OrGreater; + + [ActiveIssue("https://github.com/dotnet/runtime/issues/58898")] + [ConditionalFact(nameof(IsNotWindows11))] public void SendPacketsElement_FileStreamLargeOffset_Throws() { using (var stream = new FileStream(TestFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync: true)) @@ -548,7 +554,8 @@ public void SendPacketsElement_FileStreamLargeCount_Throws() } } - [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/58898")] + [ConditionalFact(nameof(IsNotWindows11))] public void SendPacketsElement_FileStreamWithOptions_Success() { using (var stream = new FileStream(TestFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan)) { var element = new SendPacketsElement(stream, 0, s_testFileSize); @@ -579,7 +586,8 @@ public void SendPacketsElement_FileStreamMultiPartMixed_Success() { } } - [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/58898")] + [ConditionalFact(nameof(IsNotWindows11))] public void SendPacketsElement_FileStreamMultiPartMixed_MultipleFileStreams_Success() { using (var stream = new FileStream(TestFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous)) using (var stream2 = new FileStream(TestFileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous)) { diff --git a/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.sln b/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.sln index 6c64c7da37d5f8..a0efb293da7af1 100644 --- a/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.sln +++ b/src/libraries/System.Net.WebSockets.Client/System.Net.WebSockets.Client.sln @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{A0314AC5-E49 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6F9A42A0-A04B-4CD0-B8C9-9A728274C851}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Net.WebSockets.Client.Wasm.Tests", "tests\wasm\System.Net.WebSockets.Client.Wasm.Tests.csproj", "{CA20532A-33B3-4DC0-92D2-EA6D7987D59F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -53,6 +55,10 @@ Global {6B9721B2-00D0-41EC-96B9-6428CF1830CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B9721B2-00D0-41EC-96B9-6428CF1830CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B9721B2-00D0-41EC-96B9-6428CF1830CF}.Release|Any CPU.Build.0 = Release|Any CPU + {CA20532A-33B3-4DC0-92D2-EA6D7987D59F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA20532A-33B3-4DC0-92D2-EA6D7987D59F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA20532A-33B3-4DC0-92D2-EA6D7987D59F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA20532A-33B3-4DC0-92D2-EA6D7987D59F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -65,6 +71,7 @@ Global {0CD4C24D-7746-46F0-8D47-A396882B5468} = {6F9A42A0-A04B-4CD0-B8C9-9A728274C851} {8CD4D190-F656-4970-9AE9-4A9F8B30A2F8} = {6F9A42A0-A04B-4CD0-B8C9-9A728274C851} {59A23CAB-D098-495F-A467-74C7553FF5BB} = {6F9A42A0-A04B-4CD0-B8C9-9A728274C851} + {CA20532A-33B3-4DC0-92D2-EA6D7987D59F} = {BEE2F256-0489-4809-AB20-27ADB2D0E10C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {D91D7DC5-24CC-4716-A357-8170C4EB1C32} diff --git a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs index f5d86dfff25ba8..b8b4159e2db52d 100644 --- a/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs +++ b/src/libraries/System.Net.WebSockets.Client/tests/SendReceiveTest.cs @@ -255,12 +255,12 @@ await SendAsync( "ReceiveAsync"), ex.Message); - Assert.Equal(WebSocketState.Aborted, cws.State); + Assert.True(WebSocketState.Aborted == cws.State, cws.State+" state when InvalidOperationException"); } else if (ex is WebSocketException) { // Multiple cases. - Assert.Equal(WebSocketState.Aborted, cws.State); + Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when WebSocketException"); WebSocketError errCode = (ex as WebSocketException).WebSocketErrorCode; Assert.True( @@ -269,7 +269,7 @@ await SendAsync( } else if (ex is OperationCanceledException) { - Assert.Equal(WebSocketState.Aborted, cws.State); + Assert.True(WebSocketState.Aborted == cws.State, cws.State + " state when OperationCanceledException"); } else { diff --git a/src/libraries/System.Net.WebSockets.Client/tests/wasm/BrowserTimerThrottlingTest.cs b/src/libraries/System.Net.WebSockets.Client/tests/wasm/BrowserTimerThrottlingTest.cs new file mode 100644 index 00000000000000..df6e5f17705909 --- /dev/null +++ b/src/libraries/System.Net.WebSockets.Client/tests/wasm/BrowserTimerThrottlingTest.cs @@ -0,0 +1,181 @@ +// 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 System.Net.WebSockets.Client.Tests; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using Xunit; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace System.Net.WebSockets.Client.Wasm.Tests +{ + // https://developer.chrome.com/blog/timer-throttling-in-chrome-88/ + // https://docs.google.com/document/d/11FhKHRcABGS4SWPFGwoL6g0ALMqrFKapCk5ZTKKupEk/view + // requires chromium based browser + // requires minimized browser or browser tab out of focus, browser can't be headless + // requires --enable-features=IntensiveWakeUpThrottling:grace_period_seconds/1 chromeDriver flags + // doesn't work with --disable-background-timer-throttling + [TestCaseOrderer("System.Net.WebSockets.Client.Wasm.Tests.AlphabeticalOrderer", "System.Net.WebSockets.Client.Wasm.Tests")] + public class BrowserTimerThrottlingTest : ClientWebSocketTestBase + { + public static bool IsBrowser => RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")); + const double moreThanLightThrottlingThreshold = 1900; + const double detectLightThrottlingThreshold = 900; + const double webSocketMessageFrequency = 45000; + const double fastTimeoutFrequency = 100; + + public BrowserTimerThrottlingTest(ITestOutputHelper output) : base(output) { } + + [ConditionalFact(nameof(PlatformDetection.IsBrowser))] + [OuterLoop] // involves long delay + // this test is influenced by usage of WS on the same browser tab in previous unit tests. we may need to wait long time for it to fizzle down + public async Task DotnetTimersAreHeavilyThrottledWithoutWebSocket() + { + double maxDelayMs = 0; + double maxLightDelayMs = 0; + DateTime start = DateTime.Now; + CancellationTokenSource cts = new CancellationTokenSource(); + + using (var timer = new Timers.Timer(fastTimeoutFrequency)) + { + DateTime last = DateTime.Now; + timer.AutoReset = true; + timer.Enabled = true; + timer.Elapsed += (object? source, Timers.ElapsedEventArgs? e) => + { + var ms = (e.SignalTime - last).TotalMilliseconds; + if (maxDelayMs < ms) + { + maxDelayMs = ms; + } + if (ms > moreThanLightThrottlingThreshold) + { +#if DEBUG + Console.WriteLine("Too slow tick " + ms); +#endif + // stop, we are throttled heavily, this is what we are looking for + cts.Cancel(); + } + else if (ms > detectLightThrottlingThreshold) + { + maxLightDelayMs = ms; + // we are lightly throttled +#if DEBUG + Console.WriteLine("Slow tick NO-WS " + ms); +#endif + } + last = e.SignalTime; + }; + + // test it for 10 minutes + try { await Task.Delay(10 * 60 * 1000, cts.Token); } catch (Exception) { } + timer.Close(); + } + Assert.True(maxDelayMs > detectLightThrottlingThreshold, "Expect that it throttled lightly " + maxDelayMs); + Assert.True(maxDelayMs > moreThanLightThrottlingThreshold, "Expect that it was heavily throttled " + maxDelayMs); + } + + [ConditionalFact(nameof(WebSocketsSupported), nameof(PlatformDetection.IsBrowser))] + [OuterLoop] // involves long delay + public async Task WebSocketKeepsDotnetTimersOnlyLightlyThrottled() + { + double maxDelayMs = 0; + double maxLightDelayMs = 0; + DateTime start = DateTime.Now; + CancellationTokenSource cts = new CancellationTokenSource(); + + using (ClientWebSocket cws = await WebSocketHelper.GetConnectedWebSocket(Test.Common.Configuration.WebSockets.RemoteEchoServer, TimeOutMilliseconds, _output)) + { + await SendAndReceive(cws, "test"); + using (var timer = new Timers.Timer(fastTimeoutFrequency)) + { + DateTime last = DateTime.Now; + DateTime lastSent = DateTime.MinValue; + timer.AutoReset = true; + timer.Enabled = true; + timer.Elapsed += async (object? source, Timers.ElapsedEventArgs? e) => + { + var ms = (e.SignalTime - last).TotalMilliseconds; + var msSent = (e.SignalTime - lastSent).TotalMilliseconds; + if (maxDelayMs < ms) + { + maxDelayMs = ms; + } + if (ms > moreThanLightThrottlingThreshold) + { + // fail fast, we are throttled heavily +#if DEBUG + Console.WriteLine("Too slow tick " + ms); +#endif + cts.Cancel(); + } + else if (ms > detectLightThrottlingThreshold) + { + maxLightDelayMs = ms; + // we are lightly throttled +#if DEBUG + Console.WriteLine("Slow tick WS " + ms); +#endif + } + if (msSent > webSocketMessageFrequency) + { + await SendAndReceive(cws, "test"); + lastSent = DateTime.Now; + } + last = e.SignalTime; + }; + + // test it for 10 minutes + try { await Task.Delay(10 * 60 * 1000, cts.Token); } catch (Exception) { } + timer.Close(); + } + await cws.CloseAsync(WebSocketCloseStatus.NormalClosure, "WebSocketKeepsDotnetTimersOnlyLightlyThrottled", CancellationToken.None); + } + Assert.True(maxDelayMs > detectLightThrottlingThreshold, "Expect that it throttled lightly " + maxDelayMs); + Assert.True(maxDelayMs < moreThanLightThrottlingThreshold, "Expect that it wasn't heavily throttled " + maxDelayMs); + } + + private async static Task SendAndReceive(ClientWebSocket cws, string message) + { + try + { + byte[] buffer = Encoding.UTF8.GetBytes(message); + await cws.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, CancellationToken.None); + + var receiveBuffer = new byte[100]; + var receiveSegment = new ArraySegment(receiveBuffer); + WebSocketReceiveResult recvRet = await cws.ReceiveAsync(receiveSegment, CancellationToken.None); +#if DEBUG + Console.WriteLine("SendAndReceive"); +#endif + } + catch (OperationCanceledException) + { + } + catch (Exception ex) + { +#if DEBUG + Console.WriteLine("SendAndReceive fail:" + ex); +#endif + } + } + } + + // this is just for convinience, as the second test has side-effect to running page, the first test would take longer if they are in another order + public class AlphabeticalOrderer : ITestCaseOrderer + { + public IEnumerable OrderTestCases(IEnumerable testCases) + where TTestCase : ITestCase + { + List result = testCases.ToList(); + result.Sort((x, y) => StringComparer.Ordinal.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name)); + return result; + } + } +} diff --git a/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj b/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj new file mode 100644 index 00000000000000..754539cfe25eaa --- /dev/null +++ b/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.csproj @@ -0,0 +1,66 @@ + + + ../../src/Resources/Strings.resx + $(NetCoreAppCurrent)-Browser + $(DefineConstants);NETSTANDARD + + + + --background-throttling + WasmTestOnBrowser + $(TestArchiveRoot)browseronly/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.sln b/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.sln new file mode 100644 index 00000000000000..11f24affd5e1c1 --- /dev/null +++ b/src/libraries/System.Net.WebSockets.Client/tests/wasm/System.Net.WebSockets.Client.Wasm.Tests.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31521.260 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Net.WebSockets.Client.Wasm.Tests", "System.Net.WebSockets.Client.Wasm.Tests.csproj", "{DA6DF153-169E-485D-90A4-EDBDA54B32A6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DA6DF153-169E-485D-90A4-EDBDA54B32A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA6DF153-169E-485D-90A4-EDBDA54B32A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA6DF153-169E-485D-90A4-EDBDA54B32A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA6DF153-169E-485D-90A4-EDBDA54B32A6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {627DB5DF-DE31-44B4-B5FD-E5666467145E} + EndGlobalSection +EndGlobal diff --git a/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx b/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx index 693f8d3863fd7f..e96ac19e3f8ef4 100644 --- a/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx +++ b/src/libraries/System.Net.WebSockets/src/Resources/Strings.resx @@ -165,4 +165,7 @@ The compression options for a continuation cannot be different than the options used to send the first fragment of the message. - \ No newline at end of file + + The WebSocket received a frame with an invalid payload length. + + diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketDeflater.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketDeflater.cs index 7d8eb832c2e2ad..7c8db8eedcc871 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketDeflater.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/Compression/WebSocketDeflater.cs @@ -144,7 +144,13 @@ private unsafe void UnsafeDeflate(ReadOnlySpan input, Span output, o consumed = input.Length - (int)_stream.AvailIn; written = output.Length - (int)_stream.AvailOut; - needsMoreBuffer = errorCode == ErrorCode.BufError || _stream.AvailIn > 0; + // It is important here to also check that we haven't + // exhausted the output buffer because after deflating we're + // always going to issue a flush and a flush with empty output + // is going to throw. + needsMoreBuffer = errorCode == ErrorCode.BufError + || _stream.AvailIn > 0 + || written == output.Length; } } @@ -152,6 +158,7 @@ private unsafe int UnsafeFlush(Span output, out bool needsMoreBuffer) { Debug.Assert(_stream is not null); Debug.Assert(_stream.AvailIn == 0); + Debug.Assert(output.Length > 0); fixed (byte* fixedOutput = output) { diff --git a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs index 05b171cf94ed72..ec62d92ac11a9a 100644 --- a/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs +++ b/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs @@ -1116,6 +1116,14 @@ private async ValueTask CloseWithReceiveErrorAndThrowAsync( return SR.net_Websockets_ReservedBitsSet; } + if (header.PayloadLength < 0) + { + // as per RFC, if payload length is a 64-bit integer, the most significant bit MUST be 0 + // frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF; 64 bits in length + resultHeader = default; + return SR.net_Websockets_InvalidPayloadLength; + } + if (header.Compressed && _inflater is null) { resultHeader = default; diff --git a/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs b/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs index f940df0add3aee..f9fd4e3c564e57 100644 --- a/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs +++ b/src/libraries/System.Net.WebSockets/tests/WebSocketCreateTest.cs @@ -149,6 +149,37 @@ public async Task ReceiveAsync_InvalidFrameHeader_AbortsAndThrowsException(byte } } + [Theory] + [InlineData(new byte[] { 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, false)] // max allowed value + [InlineData(new byte[] { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, true)] + public async Task ReceiveAsync_InvalidPayloadLength_AbortsAndThrowsException(byte[] lenBytes, bool shouldFail) + { + var frame = new byte[11]; + frame[0] = 0b1_000_0010; // FIN, RSV, OPCODE + frame[1] = 0b0_1111111; // MASK, PAYLOAD_LEN + Assert.Equal(8, lenBytes.Length); + Array.Copy(lenBytes, 0, frame, 2, lenBytes.Length); // EXTENDED_PAYLOAD_LEN + frame[10] = (byte)'a'; + + using var stream = new MemoryStream(frame, writable: true); + using WebSocket websocket = CreateFromStream(stream, false, null, Timeout.InfiniteTimeSpan); + + var buffer = new byte[1]; + Task t = websocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None); + if (shouldFail) + { + var exc = await Assert.ThrowsAsync(() => t); + Assert.Equal(WebSocketState.Aborted, websocket.State); + } + else + { + WebSocketReceiveResult result = await t; + Assert.False(result.EndOfMessage); + Assert.Equal(1, result.Count); + Assert.Equal('a', (char)buffer[0]); + } + } + [Fact] [SkipOnPlatform(TestPlatforms.Browser, "System.Net.Sockets is not supported on this platform.")] [ActiveIssue("https://github.com/dotnet/runtime/issues/34690", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] diff --git a/src/libraries/System.Private.CoreLib/generators/EventSourceGenerator.Parser.cs b/src/libraries/System.Private.CoreLib/generators/EventSourceGenerator.Parser.cs index be971bb185f0b8..2b28b46e03335b 100644 --- a/src/libraries/System.Private.CoreLib/generators/EventSourceGenerator.Parser.cs +++ b/src/libraries/System.Private.CoreLib/generators/EventSourceGenerator.Parser.cs @@ -7,10 +7,10 @@ using System.Security.Cryptography; using System.Text; using System.Threading; - using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace Generators { @@ -31,14 +31,14 @@ public Parser(Compilation compilation, Action reportDiagnostic, Canc public EventSourceClass[] GetEventSourceClasses(List classDeclarations) { - INamedTypeSymbol? autogenerateAttribute = _compilation.GetTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); + INamedTypeSymbol? autogenerateAttribute = _compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAutoGenerateAttribute"); if (autogenerateAttribute is null) { // No EventSourceAutoGenerateAttribute return Array.Empty(); } - INamedTypeSymbol? eventSourceAttribute = _compilation.GetTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute"); + INamedTypeSymbol? eventSourceAttribute = _compilation.GetBestTypeByMetadataName("System.Diagnostics.Tracing.EventSourceAttribute"); if (eventSourceAttribute is null) { // No EventSourceAttribute diff --git a/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj b/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj index bf6c663b56432f..451bb520f66ead 100644 --- a/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj +++ b/src/libraries/System.Private.CoreLib/generators/System.Private.CoreLib.Generators.csproj @@ -15,6 +15,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml index 53a41aff8c935a..ee28b6e38cfe61 100644 --- a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml +++ b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -4,5 +4,9 @@ + + + + diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs index 9f689b161bbd00..c2eab851bd60e2 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.OverlappedValueTaskSource.Windows.cs @@ -86,8 +86,11 @@ internal static Exception GetIOError(int errorCode, string? path) _bufferSize = memory.Length; _memoryHandle = memory.Pin(); _overlapped = _fileHandle.ThreadPoolBinding!.AllocateNativeOverlapped(_preallocatedOverlapped); - _overlapped->OffsetLow = (int)fileOffset; - _overlapped->OffsetHigh = (int)(fileOffset >> 32); + if (_fileHandle.CanSeek) + { + _overlapped->OffsetLow = (int)fileOffset; + _overlapped->OffsetHigh = (int)(fileOffset >> 32); + } return _overlapped; } diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs index ee1def85b9e024..266fd93e5082da 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs @@ -16,6 +16,7 @@ public sealed partial class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid // not using bool? as it's not thread safe private volatile NullableBool _canSeek = NullableBool.Undefined; + private volatile NullableBool _supportsRandomAccess = NullableBool.Undefined; private bool _deleteOnClose; private bool _isLocked; @@ -33,6 +34,25 @@ private SafeFileHandle(bool ownsHandle) internal bool CanSeek => !IsClosed && GetCanSeek(); + internal bool SupportsRandomAccess + { + get + { + NullableBool supportsRandomAccess = _supportsRandomAccess; + if (supportsRandomAccess == NullableBool.Undefined) + { + _supportsRandomAccess = supportsRandomAccess = GetCanSeek() ? NullableBool.True : NullableBool.False; + } + + return supportsRandomAccess == NullableBool.True; + } + set + { + Debug.Assert(value == false); // We should only use the setter to disable random access. + _supportsRandomAccess = value ? NullableBool.True : NullableBool.False; + } + } + internal ThreadPoolBoundHandle? ThreadPoolBinding => null; internal void EnsureThreadPoolBindingInitialized() { /* nop */ } @@ -121,17 +141,6 @@ private static bool DirectoryExists(string fullPath) protected override bool ReleaseHandle() { - // When the SafeFileHandle was opened, we likely issued an flock on the created descriptor in order to add - // an advisory lock. This lock should be removed via closing the file descriptor, but close can be - // interrupted, and we don't retry closes. As such, we could end up leaving the file locked, - // which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively - // try to release the lock before we close the handle. - if (_isLocked) - { - Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors - _isLocked = false; - } - // If DeleteOnClose was requested when constructed, delete the file now. // (Unix doesn't directly support DeleteOnClose, so we mimic it here.) if (_deleteOnClose) @@ -143,6 +152,17 @@ protected override bool ReleaseHandle() Interop.Sys.Unlink(_path); // ignore errors; it's valid that the path may no longer exist } + // When the SafeFileHandle was opened, we likely issued an flock on the created descriptor in order to add + // an advisory lock. This lock should be removed via closing the file descriptor, but close can be + // interrupted, and we don't retry closes. As such, we could end up leaving the file locked, + // which could prevent subsequent usage of the file until this process dies. To avoid that, we proactively + // try to release the lock before we close the handle. + if (_isLocked) + { + Interop.Sys.FLock(handle, Interop.Sys.LockOperations.LOCK_UN); // ignore any errors + _isLocked = false; + } + // Close the descriptor. Although close is documented to potentially fail with EINTR, we never want // to retry, as the descriptor could actually have been closed, been subsequently reassigned, and // be in use elsewhere in the process. Instead, we simply check whether the call was successful. @@ -274,7 +294,6 @@ private static Interop.Sys.OpenFlags PreOpenConfigurationFromOptions(FileMode mo private void Init(string path, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize) { IsAsync = (options & FileOptions.Asynchronous) != 0; - _deleteOnClose = (options & FileOptions.DeleteOnClose) != 0; // Lock the file if requested via FileShare. This is only advisory locking. FileShare.None implies an exclusive // lock on the file and all other modes use a shared lock. While this is not as granular as Windows, not mandatory, @@ -293,6 +312,10 @@ private void Init(string path, FileMode mode, FileAccess access, FileShare share } } + // Enable DeleteOnClose when we've succesfully locked the file. + // On Windows, the locking happens atomically as part of opening the file. + _deleteOnClose = (options & FileOptions.DeleteOnClose) != 0; + // These provide hints around how the file will be accessed. Specifying both RandomAccess // and Sequential together doesn't make sense as they are two competing options on the same spectrum, // so if both are specified, we prefer RandomAccess (behavior on Windows is unspecified if both are provided). @@ -323,20 +346,24 @@ private void Init(string path, FileMode mode, FileAccess access, FileShare share } } - // If preallocationSize has been provided for a creatable and writeable file - if (FileStreamHelpers.ShouldPreallocate(preallocationSize, access, mode)) + if (preallocationSize > 0 && Interop.Sys.FAllocate(this, 0, preallocationSize) < 0) { - int fallocateResult = Interop.Sys.PosixFAllocate(this, 0, preallocationSize); - if (fallocateResult != 0) + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + + // Only throw for errors that indicate there is not enough space. + if (errorInfo.Error == Interop.Error.EFBIG || + errorInfo.Error == Interop.Error.ENOSPC) { Dispose(); - Interop.Sys.Unlink(path!); // remove the file to mimic Windows behaviour (atomic operation) - Debug.Assert(fallocateResult == -1 || fallocateResult == -2); - throw new IOException(SR.Format( - fallocateResult == -1 ? SR.IO_DiskFull_Path_AllocationSize : SR.IO_FileTooLarge_Path_AllocationSize, - path, - preallocationSize)); + // Delete the file we've created. + Debug.Assert(mode == FileMode.Create || mode == FileMode.CreateNew); + Interop.Sys.Unlink(path!); + + throw new IOException(SR.Format(errorInfo.Error == Interop.Error.EFBIG + ? SR.IO_FileTooLarge_Path_AllocationSize + : SR.IO_DiskFull_Path_AllocationSize, + path, preallocationSize)); } } } diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs index a7c4751a094786..3352f0194e73b9 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs @@ -34,7 +34,7 @@ internal static unsafe SafeFileHandle Open(string fullPath, FileMode mode, FileA // of converting DOS to NT file paths (RtlDosPathNameToRelativeNtPathName_U_WithStatus is not documented) SafeFileHandle fileHandle = CreateFile(fullPath, mode, access, share, options); - if (FileStreamHelpers.ShouldPreallocate(preallocationSize, access, mode)) + if (preallocationSize > 0) { Preallocate(fullPath, preallocationSize, fileHandle); } @@ -121,19 +121,19 @@ private static unsafe void Preallocate(string fullPath, long preallocationSize, { int errorCode = Marshal.GetLastPInvokeError(); - // we try to mimic the atomic NtCreateFile here: - // if preallocation fails, close the handle and delete the file - fileHandle.Dispose(); - Interop.Kernel32.DeleteFile(fullPath); - - switch (errorCode) + // Only throw for errors that indicate there is not enough space. + if (errorCode == Interop.Errors.ERROR_DISK_FULL || + errorCode == Interop.Errors.ERROR_FILE_TOO_LARGE) { - case Interop.Errors.ERROR_DISK_FULL: - throw new IOException(SR.Format(SR.IO_DiskFull_Path_AllocationSize, fullPath, preallocationSize)); - case Interop.Errors.ERROR_FILE_TOO_LARGE: - throw new IOException(SR.Format(SR.IO_FileTooLarge_Path_AllocationSize, fullPath, preallocationSize)); - default: - throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); + fileHandle.Dispose(); + + // Delete the file we've created. + Interop.Kernel32.DeleteFile(fullPath); + + throw new IOException(SR.Format(errorCode == Interop.Errors.ERROR_DISK_FULL + ? SR.IO_DiskFull_Path_AllocationSize + : SR.IO_FileTooLarge_Path_AllocationSize, + fullPath, preallocationSize)); } } } diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 6cd99cac9c9531..cb95472d7f96d3 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -528,6 +528,9 @@ Type passed must be an interface. + + Object must be of type NFloat. + Type must be a Pointer. @@ -1092,6 +1095,12 @@ Append access can be requested only in write-only mode. + + Preallocation size can be requested only in write mode. + + + Preallocation size can be requested only for new files. + Type of argument is not compatible with the generic comparer. @@ -2659,9 +2668,6 @@ BindHandle for ThreadPool failed on this handle. - - The link's file system entry type is inconsistent with that of its target: {0} - The file '{0}' already exists. 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 5a1593f032c69a..ce942ea7e85696 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 @@ -2029,8 +2029,8 @@ Common\Interop\Unix\System.Native\Interop.PosixFAdvise.cs - - Common\Interop\Unix\System.Native\Interop.PosixFAllocate.cs + + Common\Interop\Unix\System.Native\Interop.FAllocate.cs Common\Interop\Unix\System.Native\Interop.PRead.cs @@ -2098,7 +2098,7 @@ - + @@ -2112,6 +2112,8 @@ + + @@ -2155,14 +2157,15 @@ Link="Common\Interop\Linux\Interop.ProcFsStat.TryReadStatusFile.cs" /> - - + + @@ -2325,4 +2328,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index c8b5fcba415f5e..94760aa0ef991c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -1,7 +1,10 @@ // 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.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.Tracing; using System.IO; using System.Reflection; @@ -30,5 +33,52 @@ private static string GetBaseDirectoryCore() return directory; } + + internal static void LogSwitchValues(RuntimeEventSource ev) + { + if (s_switches is not null) + { + lock (s_switches) + { + foreach (KeyValuePair kvp in s_switches) + { + // Convert bool to int because it's cheaper to log (no boxing) + ev.LogAppContextSwitch(kvp.Key, kvp.Value ? 1 : 0); + } + } + } + + if (s_dataStore is not null) + { + lock (s_dataStore) + { + if (s_switches is not null) + { + lock (s_switches) + { + LogDataStore(ev, s_switches); + } + } + else + { + LogDataStore(ev, null); + } + + static void LogDataStore(RuntimeEventSource ev, Dictionary? switches) + { + Debug.Assert(s_dataStore is not null); + foreach (KeyValuePair kvp in s_dataStore) + { + if (kvp.Value is string s && + bool.TryParse(s, out bool isEnabled) && + switches?.ContainsKey(kvp.Key) != true) + { + ev.LogAppContextSwitch(kvp.Key, isEnabled ? 1 : 0); + } + } + } + } + } + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Byte.cs b/src/libraries/System.Private.CoreLib/src/System/Byte.cs index 3d5b448159a63d..cbf21d307d636e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Byte.cs @@ -285,11 +285,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IAdditionOperators.operator +(byte left, byte right) => (byte)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IAdditionOperators.operator +(byte left, byte right) // => checked((byte)(left + right)); @@ -297,30 +297,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.LeadingZeroCount(byte value) => (byte)(BitOperations.LeadingZeroCount(value) - 24); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.PopCount(byte value) => (byte)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.RotateLeft(byte value, int rotateAmount) => (byte)((value << (rotateAmount & 7)) | (value >> ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.RotateRight(byte value, int rotateAmount) => (byte)((value >> (rotateAmount & 7)) | (value << ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryInteger.TrailingZeroCount(byte value) => (byte)(BitOperations.TrailingZeroCount(value << 24) - 24); @@ -328,11 +328,11 @@ static byte IBinaryInteger.TrailingZeroCount(byte value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(byte value) => BitOperations.IsPow2((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBinaryNumber.Log2(byte value) => (byte)BitOperations.Log2(value); @@ -340,19 +340,19 @@ static byte IBinaryNumber.Log2(byte value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator &(byte left, byte right) => (byte)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator |(byte left, byte right) => (byte)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator ^(byte left, byte right) => (byte)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IBitwiseOperators.operator ~(byte value) => (byte)(~value); @@ -360,19 +360,19 @@ static byte IBinaryNumber.Log2(byte value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(byte left, byte right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(byte left, byte right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(byte left, byte right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(byte left, byte right) => left >= right; @@ -380,11 +380,11 @@ static byte IBinaryNumber.Log2(byte value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IDecrementOperators.operator --(byte value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IDecrementOperators.operator --(byte value) // => checked(--value); @@ -392,11 +392,11 @@ static byte IBinaryNumber.Log2(byte value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IDivisionOperators.operator /(byte left, byte right) => (byte)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IDivisionOperators.operator /(byte left, byte right) // => checked((byte)(left / right)); @@ -404,11 +404,11 @@ static byte IBinaryNumber.Log2(byte value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(byte left, byte right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(byte left, byte right) => left != right; @@ -416,11 +416,11 @@ static byte IBinaryNumber.Log2(byte value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IIncrementOperators.operator ++(byte value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IIncrementOperators.operator ++(byte value) // => checked(++value); @@ -428,21 +428,21 @@ static byte IBinaryNumber.Log2(byte value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IModulusOperators.operator %(byte left, byte right) => (byte)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IModulusOperators.operator %(byte left, byte right) // => checked((byte)(left % right)); @@ -450,18 +450,18 @@ static byte IBinaryNumber.Log2(byte value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IMultiplyOperators.operator *(byte left, byte right) => (byte)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IMultiplyOperators.operator *(byte left, byte right) // => checked((byte)(left * right)); @@ -469,21 +469,21 @@ static byte IBinaryNumber.Log2(byte value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Abs(byte value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Clamp(byte value, byte min, byte max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static byte INumber.Create(TOther value) { @@ -550,7 +550,7 @@ static byte INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static byte INumber.CreateSaturating(TOther value) { @@ -637,7 +637,7 @@ static byte INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static byte INumber.CreateTruncating(TOther value) { @@ -704,31 +704,31 @@ static byte INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (byte Quotient, byte Remainder) INumber.DivRem(byte left, byte right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Max(byte x, byte y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Min(byte x, byte y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte INumber.Sign(byte value) => (byte)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out byte result) { @@ -914,11 +914,11 @@ static bool INumber.TryCreate(TOther value, out byte result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out byte result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out byte result) => TryParse(s, style, provider, out result); @@ -926,11 +926,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out byte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -938,15 +938,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IShiftOperators.operator <<(byte value, int shiftAmount) => (byte)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IShiftOperators.operator >>(byte value, int shiftAmount) => (byte)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static byte IShiftOperators.operator >>>(byte value, int shiftAmount) // => (byte)(value >> shiftAmount); @@ -954,11 +954,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out byte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -966,11 +966,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte ISubtractionOperators.operator -(byte left, byte right) => (byte)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte ISubtractionOperators.operator -(byte left, byte right) // => checked((byte)(left - right)); @@ -978,11 +978,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IUnaryNegationOperators.operator -(byte value) => (byte)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IUnaryNegationOperators.operator -(byte value) // => checked((byte)(-value)); @@ -990,11 +990,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static byte IUnaryPlusOperators.operator +(byte value) => (byte)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked byte IUnaryPlusOperators.operator +(byte value) // => checked((byte)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index 26ff3399fe10ed..497b60b5d3449b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -1065,11 +1065,11 @@ public static int ConvertToUtf32(string s, int index) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IAdditionOperators.operator +(char left, char right) => (char)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IAdditionOperators.operator +(char left, char right) // => checked((char)(left + right)); @@ -1077,30 +1077,30 @@ public static int ConvertToUtf32(string s, int index) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IAdditiveIdentity.AdditiveIdentity => (char)0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.LeadingZeroCount(char value) => (char)(BitOperations.LeadingZeroCount(value) - 16); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.PopCount(char value) => (char)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.RotateLeft(char value, int rotateAmount) => (char)((value << (rotateAmount & 15)) | (value >> ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.RotateRight(char value, int rotateAmount) => (char)((value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryInteger.TrailingZeroCount(char value) => (char)(BitOperations.TrailingZeroCount(value << 16) - 16); @@ -1108,11 +1108,11 @@ static char IBinaryInteger.TrailingZeroCount(char value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(char value) => BitOperations.IsPow2((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBinaryNumber.Log2(char value) => (char)BitOperations.Log2(value); @@ -1120,19 +1120,19 @@ static char IBinaryNumber.Log2(char value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator &(char left, char right) => (char)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator |(char left, char right) => (char)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator ^(char left, char right) => (char)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IBitwiseOperators.operator ~(char value) => (char)(~value); @@ -1140,19 +1140,19 @@ static char IBinaryNumber.Log2(char value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(char left, char right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(char left, char right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(char left, char right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(char left, char right) => left >= right; @@ -1160,11 +1160,11 @@ static char IBinaryNumber.Log2(char value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IDecrementOperators.operator --(char value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IDecrementOperators.operator --(char value) // => checked(--value); @@ -1172,11 +1172,11 @@ static char IBinaryNumber.Log2(char value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IDivisionOperators.operator /(char left, char right) => (char)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IDivisionOperators.operator /(char left, char right) // => checked((char)(left / right)); @@ -1184,11 +1184,11 @@ static char IBinaryNumber.Log2(char value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(char left, char right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(char left, char right) => left != right; @@ -1196,11 +1196,11 @@ static char IBinaryNumber.Log2(char value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IIncrementOperators.operator ++(char value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IIncrementOperators.operator ++(char value) // => checked(++value); @@ -1208,21 +1208,21 @@ static char IBinaryNumber.Log2(char value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IModulusOperators.operator %(char left, char right) => (char)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IModulusOperators.operator %(char left, char right) // => checked((char)(left % right)); @@ -1230,18 +1230,18 @@ static char IBinaryNumber.Log2(char value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMultiplicativeIdentity.MultiplicativeIdentity => (char)1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IMultiplyOperators.operator *(char left, char right) => (char)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IMultiplyOperators.operator *(char left, char right) // => checked((char)(left * right)); @@ -1249,21 +1249,21 @@ static char IBinaryNumber.Log2(char value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.One => (char)1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Zero => (char)0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Abs(char value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Clamp(char value, char min, char max) => (char)Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static char INumber.Create(TOther value) { @@ -1330,7 +1330,7 @@ static char INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static char INumber.CreateSaturating(TOther value) { @@ -1414,7 +1414,7 @@ static char INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static char INumber.CreateTruncating(TOther value) { @@ -1481,23 +1481,23 @@ static char INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (char Quotient, char Remainder) INumber.DivRem(char left, char right) => ((char, char))Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Max(char x, char y) => (char)Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Min(char x, char y) => (char)Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) { if (s.Length != 1) @@ -1507,11 +1507,11 @@ static char INumber.Parse(ReadOnlySpan s, NumberStyles style, IForma return s[0]; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char INumber.Sign(char value) => (char)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out char result) { @@ -1689,11 +1689,11 @@ static bool INumber.TryCreate(TOther value, out char result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out char result) => TryParse(s, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out char result) { if (s.Length != 1) @@ -1709,11 +1709,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IParseable.Parse(string s, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out char result) => TryParse(s, out result); @@ -1721,15 +1721,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IShiftOperators.operator <<(char value, int shiftAmount) => (char)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IShiftOperators.operator >>(char value, int shiftAmount) => (char)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static char IShiftOperators.operator >>>(char value, int shiftAmount) // => (char)(value >> shiftAmount); @@ -1737,7 +1737,7 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) { if (s.Length != 1) @@ -1747,7 +1747,7 @@ static char ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? pr return s[0]; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out char result) { if (s.Length != 1) @@ -1763,11 +1763,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char ISubtractionOperators.operator -(char left, char right) => (char)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char ISubtractionOperators.operator -(char left, char right) // => checked((char)(left - right)); @@ -1775,11 +1775,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IUnaryNegationOperators.operator -(char value) => (char)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IUnaryNegationOperators.operator -(char value) // => checked((char)(-value)); @@ -1787,11 +1787,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static char IUnaryPlusOperators.operator +(char value) => (char)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked char IUnaryPlusOperators.operator +(char value) // => checked((char)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs index 7e64638fa51031..955ecb17b79c34 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateOnly.cs @@ -817,15 +817,13 @@ public string ToString(string? format, IFormatProvider? provider) return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider); default: - charsWritten = 0; - return false; + throw new FormatException(SR.Argument_BadFormatSpecifier); } } if (!DateTimeFormat.IsValidCustomDateFormat(format, throwOnError: false)) { - charsWritten = 0; - return false; + throw new FormatException(SR.Format(SR.Format_DateTimeOnlyContainsNoneDateParts, format.ToString(), nameof(DateOnly))); } return DateTimeFormat.TryFormat(GetEquivalentDateTime(), destination, out charsWritten, format, provider); @@ -836,19 +834,19 @@ public string ToString(string? format, IFormatProvider? provider) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(DateOnly left, DateOnly right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(DateOnly left, DateOnly right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(DateOnly left, DateOnly right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(DateOnly left, DateOnly right) => left >= right; @@ -856,11 +854,11 @@ public string ToString(string? format, IFormatProvider? provider) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(DateOnly left, DateOnly right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(DateOnly left, DateOnly right) => left != right; @@ -868,21 +866,21 @@ public string ToString(string? format, IFormatProvider? provider) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly IMinMaxValue.MaxValue => MaxValue; // // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -890,11 +888,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateOnly ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index 1d0235268a14ec..5017c7c49cceca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -1521,11 +1521,11 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IAdditionOperators.operator +(DateTime left, TimeSpan right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTime IAdditionOperators.operator +(DateTime left, TimeSpan right) // => checked(left + right); @@ -1533,7 +1533,7 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditiveIdentity.AdditiveIdentity => default; @@ -1541,19 +1541,19 @@ static TimeSpan IAdditiveIdentity.AdditiveIdentity // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(DateTime left, DateTime right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(DateTime left, DateTime right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(DateTime left, DateTime right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(DateTime left, DateTime right) => left >= right; @@ -1561,11 +1561,11 @@ static TimeSpan IAdditiveIdentity.AdditiveIdentity // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(DateTime left, DateTime right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(DateTime left, DateTime right) => left != right; @@ -1573,21 +1573,21 @@ static TimeSpan IAdditiveIdentity.AdditiveIdentity // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IMinMaxValue.MaxValue => MaxValue; // // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateTime result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -1595,11 +1595,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateTime result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -1607,19 +1607,19 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTime ISubtractionOperators.operator -(DateTime left, TimeSpan right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTime ISubtractionOperators.operator -(DateTime left, TimeSpan right) // => checked(left - right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(DateTime left, DateTime right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(DateTime left, DateTime right) // => checked(left - right); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs index f9fcc33b9a0cfe..f2c9a77df524ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTimeOffset.cs @@ -870,11 +870,11 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IAdditionOperators.operator +(DateTimeOffset left, TimeSpan right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTimeOffset IAdditionOperators.operator +(DateTimeOffset left, TimeSpan right) // => checked(left + right); @@ -882,26 +882,26 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditiveIdentity.AdditiveIdentity => default; // // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(DateTimeOffset left, DateTimeOffset right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(DateTimeOffset left, DateTimeOffset right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(DateTimeOffset left, DateTimeOffset right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(DateTimeOffset left, DateTimeOffset right) => left >= right; @@ -909,11 +909,11 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(DateTimeOffset left, DateTimeOffset right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(DateTimeOffset left, DateTimeOffset right) => left != right; @@ -921,21 +921,21 @@ public static implicit operator DateTimeOffset(DateTime dateTime) => // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IMinMaxValue.MaxValue => MaxValue; // // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out DateTimeOffset result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -943,11 +943,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, I // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out DateTimeOffset result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -955,19 +955,19 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IForma // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static DateTimeOffset ISubtractionOperators.operator -(DateTimeOffset left, TimeSpan right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked DateTimeOffset ISubtractionOperators.operator -(DateTimeOffset left, TimeSpan right) // => checked(left - right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(DateTimeOffset left, DateTimeOffset right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(DateTimeOffset left, DateTimeOffset right) // => checked(left - right); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index 5c4f30795cd6da..6c5d654abf0ec1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1085,11 +1085,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IAdditionOperators.operator +(decimal left, decimal right) => checked(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IAdditionOperators.operator +(decimal left, decimal right) // => checked(left + right); @@ -1097,26 +1097,26 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IAdditiveIdentity.AdditiveIdentity => 0.0m; // // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(decimal left, decimal right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(decimal left, decimal right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(decimal left, decimal right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(decimal left, decimal right) => left >= right; @@ -1124,11 +1124,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IDecrementOperators.operator --(decimal value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IDecrementOperators.operator --(decimal value) // => checked(--value); @@ -1136,11 +1136,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IDivisionOperators.operator /(decimal left, decimal right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IDivisionOperators.operator /(decimal left, decimal right) // => checked(left / right); @@ -1148,11 +1148,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(decimal left, decimal right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(decimal left, decimal right) => left != right; @@ -1160,11 +1160,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IIncrementOperators.operator ++(decimal value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IIncrementOperators.operator ++(decimal value) // => checked(++value); @@ -1172,21 +1172,21 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IModulusOperators.operator %(decimal left, decimal right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IModulusOperators.operator %(decimal left, decimal right) // => checked(left % right); @@ -1194,18 +1194,18 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMultiplicativeIdentity.MultiplicativeIdentity => 1.0m; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IMultiplyOperators.operator *(decimal left, decimal right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IMultiplyOperators.operator *(decimal left, decimal right) // => checked(left * right); @@ -1213,17 +1213,17 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.One => 1.0m; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Zero => 0.0m; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Abs(decimal value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static decimal INumber.Create(TOther value) { @@ -1290,7 +1290,7 @@ static decimal INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static decimal INumber.CreateSaturating(TOther value) { @@ -1357,7 +1357,7 @@ static decimal INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static decimal INumber.CreateTruncating(TOther value) { @@ -1424,35 +1424,35 @@ static decimal INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Clamp(decimal value, decimal min, decimal max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (decimal Quotient, decimal Remainder) INumber.DivRem(decimal left, decimal right) => (left / right, left % right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Max(decimal x, decimal y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Min(decimal x, decimal y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal INumber.Sign(decimal value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out decimal result) { @@ -1534,11 +1534,11 @@ static bool INumber.TryCreate(TOther value, out decimal result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out decimal result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out decimal result) => TryParse(s, style, provider, out result); @@ -1546,11 +1546,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out decimal result) => TryParse(s, NumberStyles.Number, provider, out result); @@ -1558,18 +1558,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatP // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Number, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out decimal result) => TryParse(s, NumberStyles.Number, provider, out result); @@ -1577,11 +1577,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvid // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal ISubtractionOperators.operator -(decimal left, decimal right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal ISubtractionOperators.operator -(decimal left, decimal right) // => checked(left - right); @@ -1589,11 +1589,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvid // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IUnaryNegationOperators.operator -(decimal value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IUnaryNegationOperators.operator -(decimal value) // => checked(-value); @@ -1601,11 +1601,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvid // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static decimal IUnaryPlusOperators.operator +(decimal value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked decimal IUnaryPlusOperators.operator +(decimal value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index 6d57c82ef6cc40..3b3ac30c10aa9a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -14,6 +14,11 @@ internal sealed partial class RuntimeEventSource : EventSource { internal const string EventSourceName = "System.Runtime"; + public static class Keywords + { + public const EventKeywords AppContext = (EventKeywords)0x1; + } + private static RuntimeEventSource? s_RuntimeEventSource; private PollingCounter? _gcHeapSizeCounter; private IncrementingPollingCounter? _gen0GCCounter; @@ -50,6 +55,17 @@ public static void Initialize() // as you can't make a constructor partial. private RuntimeEventSource(int _) { } + private enum EventId : int + { + AppContextSwitch = 1 + } + + [Event((int)EventId.AppContextSwitch, Level = EventLevel.Informational, Keywords = Keywords.AppContext)] + internal void LogAppContextSwitch(string switchName, int value) + { + base.WriteEvent((int)EventId.AppContextSwitch, switchName, value); + } + protected override void OnEventCommand(EventCommandEventArgs command) { if (command.Command == EventCommand.Enable) @@ -87,6 +103,8 @@ protected override void OnEventCommand(EventCommandEventArgs command) _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" }; _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" }; _jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; + + AppContext.LogSwitchValues(this); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 3165535dd15b4f..23143143c1dfce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -455,11 +455,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IAdditionOperators.operator +(double left, double right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IAdditionOperators.operator +(double left, double right) // => checked(left + right); @@ -467,14 +467,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IAdditiveIdentity.AdditiveIdentity => 0.0; // // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(double value) { ulong bits = BitConverter.DoubleToUInt64Bits(value); @@ -487,7 +487,7 @@ static bool IBinaryNumber.IsPow2(double value) && (significand == MinSignificand); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBinaryNumber.Log2(double value) => Math.Log2(value); @@ -495,28 +495,28 @@ static double IBinaryNumber.Log2(double value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator &(double left, double right) { ulong bits = BitConverter.DoubleToUInt64Bits(left) & BitConverter.DoubleToUInt64Bits(right); return BitConverter.UInt64BitsToDouble(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator |(double left, double right) { ulong bits = BitConverter.DoubleToUInt64Bits(left) | BitConverter.DoubleToUInt64Bits(right); return BitConverter.UInt64BitsToDouble(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator ^(double left, double right) { ulong bits = BitConverter.DoubleToUInt64Bits(left) ^ BitConverter.DoubleToUInt64Bits(right); return BitConverter.UInt64BitsToDouble(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IBitwiseOperators.operator ~(double value) { ulong bits = ~BitConverter.DoubleToUInt64Bits(value); @@ -527,19 +527,19 @@ static double IBinaryNumber.Log2(double value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(double left, double right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(double left, double right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(double left, double right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(double left, double right) => left >= right; @@ -547,11 +547,11 @@ static double IBinaryNumber.Log2(double value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IDecrementOperators.operator --(double value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IDecrementOperators.operator --(double value) // => checked(--value); @@ -559,11 +559,11 @@ static double IBinaryNumber.Log2(double value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IDivisionOperators.operator /(double left, double right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IDivisionOperators.operator /(double left, double right) // => checked(left / right); @@ -571,11 +571,11 @@ static double IBinaryNumber.Log2(double value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(double left, double right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(double left, double right) => left != right; @@ -583,178 +583,202 @@ static double IBinaryNumber.Log2(double value) // IFloatingPoint // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.E => Math.E; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Epsilon => Epsilon; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.NaN => NaN; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.NegativeInfinity => NegativeInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.NegativeZero => -0.0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Pi => Math.PI; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.PositiveInfinity => PositiveInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Tau => Math.Tau; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Acos(double x) => Math.Acos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Acosh(double x) => Math.Acosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Asin(double x) => Math.Asin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Asinh(double x) => Math.Asinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Atan(double x) => Math.Atan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Atan2(double y, double x) => Math.Atan2(y, x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Atanh(double x) => Math.Atanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.BitIncrement(double x) => Math.BitIncrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.BitDecrement(double x) => Math.BitDecrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Cbrt(double x) => Math.Cbrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Ceiling(double x) => Math.Ceiling(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.CopySign(double x, double y) => Math.CopySign(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Cos(double x) => Math.Cos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Cosh(double x) => Math.Cosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Exp(double x) => Math.Exp(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Floor(double x) => Math.Floor(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.FusedMultiplyAdd(double left, double right, double addend) => Math.FusedMultiplyAdd(left, right, addend); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.IEEERemainder(double left, double right) => Math.IEEERemainder(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TInteger IFloatingPoint.ILogB(double x) => TInteger.Create(Math.ILogB(x)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log(double x) => Math.Log(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log(double x, double newBase) => Math.Log(x, newBase); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log2(double x) => Math.Log2(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Log10(double x) => Math.Log10(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.MaxMagnitude(double x, double y) => Math.MaxMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.MinMagnitude(double x, double y) => Math.MinMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Pow(double x, double y) => Math.Pow(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x) => Math.Round(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x, TInteger digits) => Math.Round(x, int.Create(digits)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x, MidpointRounding mode) => Math.Round(x, mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Round(double x, TInteger digits, MidpointRounding mode) => Math.Round(x, int.Create(digits), mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.ScaleB(double x, TInteger n) => Math.ScaleB(x, int.Create(n)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Sin(double x) => Math.Sin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Sinh(double x) => Math.Sinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Sqrt(double x) => Math.Sqrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Tan(double x) => Math.Tan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Tanh(double x) => Math.Tanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IFloatingPoint.Truncate(double x) => Math.Truncate(x); + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsFinite(double d) => IsFinite(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsInfinity(double d) => IsInfinity(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNaN(double d) => IsNaN(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNegative(double d) => IsNegative(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNegativeInfinity(double d) => IsNegativeInfinity(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNormal(double d) => IsNormal(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsPositiveInfinity(double d) => IsPositiveInfinity(d); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsSubnormal(double d) => IsSubnormal(d); + // static double IFloatingPoint.AcosPi(double x) // => Math.AcosPi(x); // @@ -825,11 +849,11 @@ static double IFloatingPoint.Truncate(double x) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IIncrementOperators.operator ++(double value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IIncrementOperators.operator ++(double value) // => checked(++value); @@ -837,21 +861,21 @@ static double IFloatingPoint.Truncate(double x) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IModulusOperators.operator %(double left, double right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IModulusOperators.operator %(double left, double right) // => checked(left % right); @@ -859,18 +883,18 @@ static double IFloatingPoint.Truncate(double x) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMultiplicativeIdentity.MultiplicativeIdentity => 1.0; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMultiplyOperators.operator *(double left, double right) => (double)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IMultiplyOperators.operator *(double left, double right) // => checked((double)(left * right)); @@ -878,21 +902,21 @@ static double IFloatingPoint.Truncate(double x) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.One => 1.0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Zero => 0.0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Abs(double value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Clamp(double value, double min, double max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static double INumber.Create(TOther value) { @@ -959,7 +983,7 @@ static double INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static double INumber.CreateSaturating(TOther value) { @@ -1026,7 +1050,7 @@ static double INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static double INumber.CreateTruncating(TOther value) { @@ -1093,31 +1117,31 @@ static double INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (double Quotient, double Remainder) INumber.DivRem(double left, double right) => (left / right, left % right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Max(double x, double y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Min(double x, double y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double INumber.Sign(double value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out double result) { @@ -1199,11 +1223,11 @@ static bool INumber.TryCreate(TOther value, out double result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out double result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out double result) => TryParse(s, style, provider, out result); @@ -1211,42 +1235,42 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, I // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out double result) - => TryParse(s, NumberStyles.Integer, provider, out result); + => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); // // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) - => Parse(s, NumberStyles.Integer, provider); + => Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out double result) - => TryParse(s, NumberStyles.Integer, provider, out result); + => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); // // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double ISubtractionOperators.operator -(double left, double right) => (double)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double ISubtractionOperators.operator -(double left, double right) // => checked((double)(left - right)); @@ -1254,11 +1278,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IUnaryNegationOperators.operator -(double value) => (double)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IUnaryNegationOperators.operator -(double value) // => checked((double)(-value)); @@ -1266,11 +1290,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IUnaryPlusOperators.operator +(double value) => (double)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IUnaryPlusOperators.operator +(double value) // => checked((double)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Enum.cs index ad0a6847d9c94c..62742587b69959 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Enum.cs @@ -879,6 +879,8 @@ private static bool TryParseRareEnum(RuntimeType enumType, ReadOnlySpan va private static bool TryParseByName(RuntimeType enumType, ReadOnlySpan value, bool ignoreCase, bool throwOnFailure, out ulong result) { + ReadOnlySpan originalValue = value; + // Find the field. Let's assume that these are always static classes because the class is an enum. EnumInfo enumInfo = GetEnumInfo(enumType); string[] enumNames = enumInfo.Names; @@ -952,7 +954,7 @@ private static bool TryParseByName(RuntimeType enumType, ReadOnlySpan valu if (throwOnFailure) { - throw new ArgumentException(SR.Format(SR.Arg_EnumValueNotFound, value.ToString())); + throw new ArgumentException(SR.Format(SR.Arg_EnumValueNotFound, originalValue.ToString())); } result = 0; diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs new file mode 100644 index 00000000000000..90512ca598bd81 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.iOS.cs @@ -0,0 +1,13 @@ +// 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.InteropServices; + +namespace System +{ + public static partial class Environment + { + // iOS/tvOS aren't allowed to call libproc APIs so return 0 here, this also matches what we returned in earlier releases + public static long WorkingSet => 0; + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs index be1b108e4e05c3..12f289c3beaef9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs @@ -47,8 +47,8 @@ internal static unsafe int GetLocaleInfoEx(string lpLocaleName, uint lcType, cha private string NlsGetLocaleInfo(LocaleStringData type) { Debug.Assert(ShouldUseUserOverrideNlsData); - Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected _sWindowsName to be populated by already"); - return NlsGetLocaleInfo(_sWindowsName, type); + Debug.Assert(_sRealName != null, "[CultureData.DoGetLocaleInfo] Expected _sRealName to be populated by already"); + return NlsGetLocaleInfo(_sRealName, type); } // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the @@ -74,15 +74,15 @@ private int NlsGetLocaleInfo(LocaleNumberData type) // Ask OS for data, note that we presume it returns success, so we have to know that // sWindowsName is valid before calling. - Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); - return GetLocaleInfoExInt(_sWindowsName, lctype); + Debug.Assert(_sRealName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sRealName to be populated already"); + return GetLocaleInfoExInt(_sRealName, lctype); } private int[] NlsGetLocaleInfo(LocaleGroupingData type) { Debug.Assert(ShouldUseUserOverrideNlsData); - Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); - return ConvertWin32GroupString(GetLocaleInfoFromLCType(_sWindowsName, (uint)type, _bUseOverrides)); + Debug.Assert(_sRealName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sRealName to be populated by already"); + return ConvertWin32GroupString(GetLocaleInfoFromLCType(_sRealName, (uint)type, _bUseOverrides)); } internal static bool NlsIsEnsurePredefinedLocaleName(string name) @@ -94,16 +94,16 @@ internal static bool NlsIsEnsurePredefinedLocaleName(string name) private string? NlsGetTimeFormatString() { Debug.Assert(ShouldUseUserOverrideNlsData); - Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); - return ReescapeWin32String(GetLocaleInfoFromLCType(_sWindowsName, Interop.Kernel32.LOCALE_STIMEFORMAT, _bUseOverrides)); + Debug.Assert(_sRealName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sRealName to be populated by already"); + return ReescapeWin32String(GetLocaleInfoFromLCType(_sRealName, Interop.Kernel32.LOCALE_STIMEFORMAT, _bUseOverrides)); } private int NlsGetFirstDayOfWeek() { Debug.Assert(ShouldUseUserOverrideNlsData); - Debug.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already"); + Debug.Assert(_sRealName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sRealName to be populated by already"); - int result = GetLocaleInfoExInt(_sWindowsName, Interop.Kernel32.LOCALE_IFIRSTDAYOFWEEK | (!_bUseOverrides ? Interop.Kernel32.LOCALE_NOUSEROVERRIDE : 0)); + int result = GetLocaleInfoExInt(_sRealName, Interop.Kernel32.LOCALE_IFIRSTDAYOFWEEK | (!_bUseOverrides ? Interop.Kernel32.LOCALE_NOUSEROVERRIDE : 0)); // Win32 and .NET disagree on the numbering for days of the week, so we have to convert. return ConvertFirstDayOfWeekMonToSun(result); @@ -529,7 +529,7 @@ internal bool NlsIsReplacementCulture for (int i = 0; i < context.strings.Count; i++) { - if (string.Equals(context.strings[i], _sWindowsName, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(context.strings[i], _sRealName, StringComparison.OrdinalIgnoreCase)) return true; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Windows.cs index 74854c3fd0b4ad..69de37e304589a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Windows.cs @@ -42,16 +42,17 @@ internal sealed partial class CultureData /// private unsafe bool InitCultureDataCore() { - if (!ShouldUseUserOverrideNlsData) + char* pBuffer = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH]; + if (!GlobalizationMode.UseNls) { - return InitIcuCultureDataCore(); + return InitIcuCultureDataCore() && + GetLocaleInfoEx(_sRealName, Interop.Kernel32.LOCALE_SNAME, pBuffer, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH) != 0; // Ensure the culture name is supported by Windows. } Debug.Assert(!GlobalizationMode.Invariant); int result; string realNameBuffer = _sRealName; - char* pBuffer = stackalloc char[Interop.Kernel32.LOCALE_NAME_MAX_LENGTH]; result = GetLocaleInfoEx(realNameBuffer, Interop.Kernel32.LOCALE_SNAME, pBuffer, Interop.Kernel32.LOCALE_NAME_MAX_LENGTH); @@ -120,7 +121,7 @@ private unsafe bool InitCultureDataCore() // We need the IETF name (sname) // If we aren't an alt sort locale then this is the same as the windows name. // If we are an alt sort locale then this is the same as the part before the _ in the windows name - // This is for like de-DE_phoneb and es-ES_tradnl that hsouldn't have the _ part + // This is for like de-DE_phoneb and es-ES_tradnl that shouldn't have the _ part result = GetLocaleInfoEx(realNameBuffer, Interop.Kernel32.LOCALE_ILANGUAGE | Interop.Kernel32.LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char)); if (result == 0) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index e72e7885566401..f8c1745c1e4994 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -62,8 +62,8 @@ Patterns Format Description Example "M" "0" month w/o leading zero 2 "MM" "00" month with leading zero 02 "MMM" short month name (abbreviation) Feb - "MMMM" full month name Febuary - "MMMM*" full month name Febuary + "MMMM" full month name February + "MMMM*" full month name February "y" "0" two digit year (year % 100) w/o leading zero 0 "yy" "00" two digit year (year % 100) with leading zero 00 @@ -734,7 +734,7 @@ private static StringBuilder FormatCustomized( break; case '\\': // Escaped character. Can be used to insert a character into the format string. - // For exmple, "\d" will insert the character 'd' into the string. + // For example, "\d" will insert the character 'd' into the string. // // NOTENOTE : we can remove this format character if we enforce the enforced quote // character rule. @@ -966,7 +966,7 @@ private static string ExpandPredefinedFormat(ReadOnlySpan format, ref Date // This format is not supported by DateTimeOffset throw new FormatException(SR.Format_InvalidString); } - // Universal time is always in Greogrian calendar. + // Universal time is always in Gregorian calendar. // // Change the Calendar to be Gregorian Calendar. // diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.cs index 1ed01badbf09ad..370e4589ad4d78 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.cs @@ -3806,7 +3806,7 @@ internal static string GetConsoleUICulture(string cultureName) return GetLocaleDataMappedCulture(cultureName, IcuLocaleDataParts.ConsoleLocaleIndex); } - // Returns index of the culture or -1 if it fail finding any match + // Returns index of the culture or less than 0 if it fail finding any match private static int SearchCultureName(string name) { if (name.Length > LocaleLongestName) @@ -3816,10 +3816,9 @@ private static int SearchCultureName(string name) for (int i = 0; i < name.Length; ++i) { char ch = name[i]; - if (ch > 'z') - return -1; - lower_case[i] = (byte)(ch | 0x20); + Debug.Assert(ch <= 'z'); + lower_case[i] = ((uint)(ch - 'A') <= 'Z' - 'A') ? (byte)(ch | 0x20) : (byte)ch; } ReadOnlySpan lname = lower_case; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index ee7c38e7777cfd..931e4b62e5a178 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -733,9 +733,9 @@ internal static void ValidateParseStyleInteger(NumberStyles style) if ((style & (InvalidNumberStyles | NumberStyles.AllowHexSpecifier)) != 0 && (style & ~NumberStyles.HexNumber) != 0) { - throwInvalid(style); + ThrowInvalid(style); - void throwInvalid(NumberStyles value) + static void ThrowInvalid(NumberStyles value) { if ((value & InvalidNumberStyles) != 0) { @@ -752,9 +752,9 @@ internal static void ValidateParseStyleFloatingPoint(NumberStyles style) // Check for undefined flags or hex number if ((style & (InvalidNumberStyles | NumberStyles.AllowHexSpecifier)) != 0) { - throwInvalid(style); + ThrowInvalid(style); - void throwInvalid(NumberStyles value) + static void ThrowInvalid(NumberStyles value) { if ((value & InvalidNumberStyles) != 0) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 1495d2a4ccfaf3..2abf1113eee083 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -1234,7 +1234,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(Guid left, Guid right) { if (left._a != right._a) @@ -1295,7 +1295,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re return false; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(Guid left, Guid right) { if (left._a != right._a) @@ -1356,7 +1356,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re return true; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(Guid left, Guid right) { if (left._a != right._a) @@ -1417,7 +1417,7 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re return false; } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(Guid left, Guid right) { if (left._a != right._a) @@ -1482,11 +1482,11 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(Guid left, Guid right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(Guid left, Guid right) => left != right; @@ -1494,11 +1494,11 @@ bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, Re // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Guid IParseable.Parse(string s, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out Guid result) => TryParse(s, out result); @@ -1506,11 +1506,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Guid ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out Guid result) => TryParse(s, out result); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index c42d7a4374e52f..9881cc8e48efa7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -241,7 +241,7 @@ public static bool IsSubnormal(Half value) public static Half Parse(string s) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseHalf(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo); + return Number.ParseHalf(s, DefaultParseStyle, NumberFormatInfo.CurrentInfo); } /// @@ -266,7 +266,7 @@ public static Half Parse(string s, NumberStyles style) public static Half Parse(string s, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); - return Number.ParseHalf(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider)); + return Number.ParseHalf(s, DefaultParseStyle, NumberFormatInfo.GetInstance(provider)); } /// @@ -707,11 +707,11 @@ private static double CreateDouble(bool sign, ushort exp, ulong sig) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IAdditionOperators.operator +(Half left, Half right) => (Half)((float)left + (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IAdditionOperators.operator +(Half left, Half right) // => checked((Half)((float)left + (float)right)); @@ -719,14 +719,14 @@ private static double CreateDouble(bool sign, ushort exp, ulong sig) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IAdditiveIdentity.AdditiveIdentity => PositiveZero; // // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(Half value) { uint bits = BitConverter.HalfToUInt16Bits(value); @@ -739,7 +739,7 @@ static bool IBinaryNumber.IsPow2(Half value) && (significand == MinSignificand); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBinaryNumber.Log2(Half value) => (Half)MathF.Log2((float)value); @@ -747,28 +747,28 @@ static Half IBinaryNumber.Log2(Half value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator &(Half left, Half right) { ushort bits = (ushort)(BitConverter.HalfToUInt16Bits(left) & BitConverter.HalfToUInt16Bits(right)); return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator |(Half left, Half right) { ushort bits = (ushort)(BitConverter.HalfToUInt16Bits(left) | BitConverter.HalfToUInt16Bits(right)); return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator ^(Half left, Half right) { ushort bits = (ushort)(BitConverter.HalfToUInt16Bits(left) ^ BitConverter.HalfToUInt16Bits(right)); return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IBitwiseOperators.operator ~(Half value) { ushort bits = (ushort)(~BitConverter.HalfToUInt16Bits(value)); @@ -779,19 +779,19 @@ static Half IBinaryNumber.Log2(Half value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(Half left, Half right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(Half left, Half right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(Half left, Half right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(Half left, Half right) => left >= right; @@ -799,7 +799,7 @@ static Half IBinaryNumber.Log2(Half value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IDecrementOperators.operator --(Half value) { var tmp = (float)value; @@ -807,7 +807,7 @@ static Half IBinaryNumber.Log2(Half value) return (Half)tmp; } - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IDecrementOperators.operator --(Half value) // { // var tmp = (float)value; @@ -819,11 +819,11 @@ static Half IBinaryNumber.Log2(Half value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(Half left, Half right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(Half left, Half right) => left != right; @@ -831,11 +831,11 @@ static Half IBinaryNumber.Log2(Half value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IDivisionOperators.operator /(Half left, Half right) => (Half)((float)left / (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IDivisionOperators.operator /(Half left, Half right) // => checked((Half)((float)left / (float)right)); @@ -843,59 +843,59 @@ static Half IBinaryNumber.Log2(Half value) // IFloatingPoint // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.E => (Half)MathF.E; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Epsilon => Epsilon; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.NaN => NaN; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.NegativeInfinity => NegativeInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.NegativeZero => NegativeZero; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Pi => (Half)MathF.PI; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.PositiveInfinity => PositiveInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Tau => (Half)MathF.Tau; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Acos(Half x) => (Half)MathF.Acos((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Acosh(Half x) => (Half)MathF.Acosh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Asin(Half x) => (Half)MathF.Asin((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Asinh(Half x) => (Half)MathF.Asinh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Atan(Half x) => (Half)MathF.Atan((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Atan2(Half y, Half x) => (Half)MathF.Atan2((float)y, (float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Atanh(Half x) => (Half)MathF.Atanh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.BitIncrement(Half x) { ushort bits = BitConverter.HalfToUInt16Bits(x); @@ -921,7 +921,7 @@ static Half IFloatingPoint.BitIncrement(Half x) return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.BitDecrement(Half x) { ushort bits = BitConverter.HalfToUInt16Bits(x); @@ -947,118 +947,143 @@ static Half IFloatingPoint.BitDecrement(Half x) return BitConverter.UInt16BitsToHalf(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Cbrt(Half x) => (Half)MathF.Cbrt((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Ceiling(Half x) => (Half)MathF.Ceiling((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.CopySign(Half x, Half y) => (Half)MathF.CopySign((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Cos(Half x) => (Half)MathF.Cos((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Cosh(Half x) => (Half)MathF.Cosh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Exp(Half x) => (Half)MathF.Exp((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Floor(Half x) => (Half)MathF.Floor((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.FusedMultiplyAdd(Half left, Half right, Half addend) => (Half)MathF.FusedMultiplyAdd((float)left, (float)right, (float)addend); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.IEEERemainder(Half left, Half right) => (Half)MathF.IEEERemainder((float)left, (float)right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TInteger IFloatingPoint.ILogB(Half x) => TInteger.Create(MathF.ILogB((float)x)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log(Half x) => (Half)MathF.Log((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log(Half x, Half newBase) => (Half)MathF.Log((float)x, (float)newBase); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log2(Half x) => (Half)MathF.Log2((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Log10(Half x) => (Half)MathF.Log10((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.MaxMagnitude(Half x, Half y) => (Half)MathF.MaxMagnitude((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.MinMagnitude(Half x, Half y) => (Half)MathF.MinMagnitude((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Pow(Half x, Half y) => (Half)MathF.Pow((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x) => (Half)MathF.Round((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x, TInteger digits) => (Half)MathF.Round((float)x, int.Create(digits)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x, MidpointRounding mode) => (Half)MathF.Round((float)x, mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Round(Half x, TInteger digits, MidpointRounding mode) => (Half)MathF.Round((float)x, int.Create(digits), mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.ScaleB(Half x, TInteger n) => (Half)MathF.ScaleB((float)x, int.Create(n)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Sin(Half x) => (Half)MathF.Sin((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Sinh(Half x) => (Half)MathF.Sinh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Sqrt(Half x) => (Half)MathF.Sqrt((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Tan(Half x) => (Half)MathF.Tan((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Tanh(Half x) => (Half)MathF.Tanh((float)x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IFloatingPoint.Truncate(Half x) => (Half)MathF.Truncate((float)x); + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsFinite(Half x) => IsFinite(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsInfinity(Half x) => IsInfinity(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNaN(Half x) => IsNaN(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNegative(Half x) => IsNegative(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNegativeInfinity(Half x) => IsNegativeInfinity(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNormal(Half x) => IsNormal(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsPositiveInfinity(Half x) => IsPositiveInfinity(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsSubnormal(Half x) => IsSubnormal(x); + + // static Half IFloatingPoint.AcosPi(Half x) // => (Half)MathF.AcosPi((float)x); // @@ -1129,7 +1154,7 @@ static Half IFloatingPoint.Truncate(Half x) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IIncrementOperators.operator ++(Half value) { var tmp = (float)value; @@ -1137,7 +1162,7 @@ static Half IFloatingPoint.Truncate(Half x) return (Half)tmp; } - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IIncrementOperators.operator ++(Half value) // { // var tmp = (float)value; @@ -1149,21 +1174,21 @@ static Half IFloatingPoint.Truncate(Half x) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IModulusOperators.operator %(Half left, Half right) => (Half)((float)left % (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IModulusOperators.operator %(Half left, Half right) // => checked((Half)((float)left % (float)right)); @@ -1171,18 +1196,18 @@ static Half IFloatingPoint.Truncate(Half x) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMultiplicativeIdentity.MultiplicativeIdentity => (Half)1.0f; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IMultiplyOperators.operator *(Half left, Half right) => (Half)((float)left * (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IMultiplyOperators.operator *(Half left, Half right) // => checked((Half)((float)left * (float)right)); @@ -1190,21 +1215,21 @@ static Half IFloatingPoint.Truncate(Half x) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.One => (Half)1.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Zero => PositiveZero; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Abs(Half value) => (Half)MathF.Abs((float)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Clamp(Half value, Half min, Half max) => (Half)Math.Clamp((float)value, (float)min, (float)max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static Half INumber.Create(TOther value) { @@ -1271,7 +1296,7 @@ static Half INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static Half INumber.CreateSaturating(TOther value) { @@ -1338,7 +1363,7 @@ static Half INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static Half INumber.CreateTruncating(TOther value) { @@ -1405,31 +1430,31 @@ static Half INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (Half Quotient, Half Remainder) INumber.DivRem(Half left, Half right) => ((Half, Half))((float)left / (float)right, (float)left % (float)right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Max(Half x, Half y) => (Half)MathF.Max((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Min(Half x, Half y) => (Half)MathF.Min((float)x, (float)y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half INumber.Sign(Half value) => (Half)MathF.Sign((float)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out Half result) { @@ -1511,11 +1536,11 @@ static bool INumber.TryCreate(TOther value, out Half result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out Half result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out Half result) => TryParse(s, style, provider, out result); @@ -1523,42 +1548,42 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out Half result) - => TryParse(s, NumberStyles.Integer, provider, out result); + => TryParse(s, DefaultParseStyle, provider, out result); // // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half ISignedNumber.NegativeOne => (Half)(-1.0f); // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) - => Parse(s, NumberStyles.Integer, provider); + => Parse(s, DefaultParseStyle, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out Half result) - => TryParse(s, NumberStyles.Integer, provider, out result); + => TryParse(s, DefaultParseStyle, provider, out result); // // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half ISubtractionOperators.operator -(Half left, Half right) => (Half)((float)left - (float)right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half ISubtractionOperators.operator -(Half left, Half right) // => checked((Half)((float)left - (float)right)); @@ -1566,11 +1591,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IUnaryNegationOperators.operator -(Half value) => (Half)(-(float)value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IUnaryNegationOperators.operator -(Half value) // => checked((Half)(-(float)value)); @@ -1578,11 +1603,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static Half IUnaryPlusOperators.operator +(Half value) => value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked Half IUnaryPlusOperators.operator +(Half value) // => checked(value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs index fb09cfac334c88..3b800fb629f668 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IAdditionOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will be added to . /// The type that contains the sum of and . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IAdditionOperators where TSelf : IAdditionOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs b/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs index 5b07145c328370..deecaa3273b694 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IAdditiveIdentity.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for getting the additive identity of a given type. /// The type that implements this interface. /// The type that contains the additive identify of . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IAdditiveIdentity where TSelf : IAdditiveIdentity { diff --git a/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs index d4d1a35d0e66f5..b811f83745c968 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IBitwiseOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will is used in the operation with . /// The type that contains the result of op . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBitwiseOperators where TSelf : IBitwiseOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs index 5bd4a22e28c96c..7576c9777b427c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IComparisonOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for comparing two values to determine relative order. /// The type that implements this interface. /// The type that will be compared with . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IComparisonOperators : IComparable, IComparable, diff --git a/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs index 9a240b14a9614d..aa61af7af8f4c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IDecrementOperators.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for decrementing a given value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IDecrementOperators where TSelf : IDecrementOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs index 4beba8cddbddf6..f8b7aaa72e97a8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IDivisionOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will divide . /// The type that contains the quotient of and . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IDivisionOperators where TSelf : IDivisionOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs index f6f8fa5050a970..b9695757447949 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IEqualityOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for comparing two values to determine equality. /// The type that implements this interface. /// The type that will be compared with . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IEqualityOperators : IEquatable where TSelf : IEqualityOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs b/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs index cb69e03fd771fa..0b9a2f5da83bd2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IFloatingPoint.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a floating-point type. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IFloatingPoint : ISignedNumber where TSelf : IFloatingPoint @@ -332,7 +332,7 @@ static abstract TSelf ScaleB(TSelf x, TInteger n) /// Defines a floating-point type that is represented in a base-2 format. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBinaryFloatingPoint : IBinaryNumber, IFloatingPoint diff --git a/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs index 5b4986a5fc22a6..ca036a24c75331 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IIncrementOperators.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for incrementing a given value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IIncrementOperators where TSelf : IIncrementOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IInteger.cs b/src/libraries/System.Private.CoreLib/src/System/IInteger.cs index 89ec036bb147a5..16b2079f3ae667 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IInteger.cs @@ -11,7 +11,7 @@ namespace System { /// Defines an integer type that is represented in a base-2 format. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBinaryInteger : IBinaryNumber, IShiftOperators diff --git a/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs b/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs index cc1eae37873940..38e2c534d1cf32 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IMinMaxValue.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for getting the minimum and maximum value of a type. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IMinMaxValue where TSelf : IMinMaxValue { diff --git a/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs index 24b5beae107e24..9ecebb4f79eae0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IModulusOperators.cs @@ -14,7 +14,7 @@ namespace System /// The type that will divide . /// The type that contains the modulus or remainder of and . /// This type represents the % in C# which is often used to compute the remainder and may differ from an actual modulo operation depending on the type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IModulusOperators where TSelf : IModulusOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs b/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs index 9560071ae51c91..86ba9371f71842 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IMultiplicativeIdentity.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for getting the multiplicative identity of a given type. /// The type that implements this interface. /// The type that contains the multiplicative identify of . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IMultiplicativeIdentity where TSelf : IMultiplicativeIdentity { diff --git a/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs index e9fc0fc1c1943c..1be00979235957 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IMultiplyOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will multiply . /// The type that contains the product of and . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IMultiplyOperators where TSelf : IMultiplyOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/INumber.cs b/src/libraries/System.Private.CoreLib/src/System/INumber.cs index c1a4f8b109c348..8ffa8429fd1a9d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/INumber.cs +++ b/src/libraries/System.Private.CoreLib/src/System/INumber.cs @@ -13,7 +13,7 @@ namespace System { /// Defines a number type. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface INumber : IAdditionOperators, IAdditiveIdentity, @@ -153,7 +153,7 @@ static abstract bool TryCreate(TOther value, out TSelf result) /// Defines a number that is represented in a base-2 format. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IBinaryNumber : IBitwiseOperators, INumber @@ -172,7 +172,7 @@ public interface IBinaryNumber /// Defines a number type which can represent both positive and negative values. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface ISignedNumber : INumber where TSelf : ISignedNumber @@ -183,7 +183,7 @@ public interface ISignedNumber /// Defines a number type which can only represent positive values, that is it cannot represent negative values. /// The type that implements the interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IUnsignedNumber : INumber where TSelf : IUnsignedNumber diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs index bcdbc292ab415b..c7c1434d69cbae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/BufferedStream.cs @@ -1222,11 +1222,12 @@ public override long Seek(long offset, SeekOrigin origin) // Otherwise we will throw away the buffer. This can only happen on read, as we flushed write data above. // The offset of the new/updated seek pointer within _buffer: - _readPos = (int)(newPos - (oldPos - _readPos)); + long readPos = (newPos - (oldPos - _readPos)); // If the offset of the updated seek pointer in the buffer is still legal, then we can keep using the buffer: - if (0 <= _readPos && _readPos < _readLen) + if (0 <= readPos && readPos < _readLen) { + _readPos = (int)readPos; // Adjust the seek pointer of the underlying stream to reflect the amount of useful bytes in the read buffer: _stream.Seek(_readLen - _readPos, SeekOrigin.Current); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index ff2a7bd9ef6286..0d614a2e9c9a7e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -333,15 +333,15 @@ public static byte[] ReadAllBytes(string path) // bufferSize == 1 used to avoid unnecessary buffer in FileStream using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, FileOptions.SequentialScan)) { - long fileLength = fs.Length; - if (fileLength > int.MaxValue) + long fileLength = 0; + if (fs.CanSeek && (fileLength = fs.Length) > int.MaxValue) { throw new IOException(SR.IO_FileTooLong2GB); } - else if (fileLength == 0) + if (fileLength == 0) { #if !MS_IO_REDIST - // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content. + // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content; also there is non-seekable file stream. // Thus we need to assume 0 doesn't mean empty. return ReadAllBytesUnknownLength(fs); #endif @@ -729,8 +729,8 @@ private static async Task InternalReadAllTextAsync(string path, Encoding bool returningInternalTask = false; try { - long fileLength = fs.Length; - if (fileLength > int.MaxValue) + long fileLength = 0L; + if (fs.CanSeek && (fileLength = fs.Length) > int.MaxValue) { var e = new IOException(SR.IO_FileTooLong2GB); #if !MS_IO_REDIST diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs index b60bb9d79e3a08..b97194b86c5f0b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs @@ -197,6 +197,11 @@ public FileStream(string path, FileStreamOptions options) } } + if (options.PreallocationSize > 0) + { + FileStreamHelpers.ValidateArgumentsForPreallocation(options.Mode, options.Access); + } + FileStreamHelpers.SerializationGuard(options.Access); _strategy = FileStreamHelpers.ChooseStrategy( diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs index aab00ededadfe7..fc4b2fec8dde10 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs @@ -571,16 +571,6 @@ public static string[] GetLogicalDrives() internal static void CreateSymbolicLink(string path, string pathToTarget, bool isDirectory) { string pathToTargetFullPath = PathInternal.GetLinkTargetFullPath(path, pathToTarget); - - // Fail if the target exists but is not consistent with the expected filesystem entry type - if (Interop.Sys.Stat(pathToTargetFullPath, out Interop.Sys.FileStatus targetInfo) == 0) - { - if (isDirectory != ((targetInfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)) - { - throw new IOException(SR.Format(SR.IO_InconsistentLinkType, path)); - } - } - Interop.CheckIo(Interop.Sys.SymLink(pathToTarget, path), path, isDirectory); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs index b92de0ad38ae9b..b1ba36322ad367 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs @@ -145,10 +145,9 @@ public static void MoveFile(string sourceFullPath, string destFullPath, bool ove } } - private static SafeFileHandle OpenHandle(string fullPath, bool asDirectory) + private static SafeFileHandle OpenHandleToWriteAttributes(string fullPath, bool asDirectory) { - string root = fullPath.Substring(0, PathInternal.GetRootLength(fullPath.AsSpan())); - if (root == fullPath && root[1] == Path.VolumeSeparatorChar) + if (fullPath.Length == PathInternal.GetRootLength(fullPath.AsSpan()) && fullPath[1] == Path.VolumeSeparatorChar) { // intentionally not fullpath, most upstack public APIs expose this as path. throw new ArgumentException(SR.Arg_PathIsVolume, "path"); @@ -156,7 +155,7 @@ private static SafeFileHandle OpenHandle(string fullPath, bool asDirectory) SafeFileHandle handle = Interop.Kernel32.CreateFile( fullPath, - Interop.Kernel32.GenericOperations.GENERIC_WRITE, + Interop.Kernel32.FileOperations.FILE_WRITE_ATTRIBUTES, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, asDirectory ? Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS : 0); @@ -382,7 +381,7 @@ private static unsafe void SetFileTime( long changeTime = -1, uint fileAttributes = 0) { - using (SafeFileHandle handle = OpenHandle(fullPath, asDirectory)) + using (SafeFileHandle handle = OpenHandleToWriteAttributes(fullPath, asDirectory)) { var basicInfo = new Interop.Kernel32.FILE_BASIC_INFO() { @@ -415,16 +414,6 @@ public static string[] GetLogicalDrives() internal static void CreateSymbolicLink(string path, string pathToTarget, bool isDirectory) { string pathToTargetFullPath = PathInternal.GetLinkTargetFullPath(path, pathToTarget); - - Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = default; - int errorCode = FillAttributeInfo(pathToTargetFullPath, ref data, returnErrorOnNotFound: true); - if (errorCode == Interop.Errors.ERROR_SUCCESS && - data.dwFileAttributes != -1 && - isDirectory != ((data.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0)) - { - throw new IOException(SR.Format(SR.IO_InconsistentLinkType, path)); - } - Interop.Kernel32.CreateSymbolicLink(path, pathToTarget, isDirectory); } @@ -499,37 +488,69 @@ internal static void CreateSymbolicLink(string path, string pathToTarget, bool i } Span bufferSpan = new(buffer); - success = MemoryMarshal.TryRead(bufferSpan, out Interop.Kernel32.REPARSE_DATA_BUFFER rdb); + success = MemoryMarshal.TryRead(bufferSpan, out Interop.Kernel32.SymbolicLinkReparseBuffer rbSymlink); Debug.Assert(success); - // Only symbolic links are supported at the moment. - if ((rdb.ReparseTag & Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_SYMLINK) == 0) + // We always use SubstituteName(Offset|Length) instead of PrintName(Offset|Length), + // the latter is just the display name of the reparse point and it can show something completely unrelated to the target. + + if (rbSymlink.ReparseTag == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_SYMLINK) { - return null; - } + int offset = sizeof(Interop.Kernel32.SymbolicLinkReparseBuffer) + rbSymlink.SubstituteNameOffset; + int length = rbSymlink.SubstituteNameLength; - // We use PrintName instead of SubstitutneName given that we don't want to return a NT path when the link wasn't created with such NT path. - // Unlike SubstituteName and GetFinalPathNameByHandle(), PrintName doesn't start with a prefix. - // Another nuance is that SubstituteName does not contain redundant path segments while PrintName does. - // PrintName can ONLY return a NT path if the link was created explicitly targeting a file/folder in such way. e.g: mklink /D linkName \??\C:\path\to\target. - int printNameNameOffset = sizeof(Interop.Kernel32.REPARSE_DATA_BUFFER) + rdb.ReparseBufferSymbolicLink.PrintNameOffset; - int printNameNameLength = rdb.ReparseBufferSymbolicLink.PrintNameLength; + Span targetPath = MemoryMarshal.Cast(bufferSpan.Slice(offset, length)); - Span targetPath = MemoryMarshal.Cast(bufferSpan.Slice(printNameNameOffset, printNameNameLength)); - Debug.Assert((rdb.ReparseBufferSymbolicLink.Flags & Interop.Kernel32.SYMLINK_FLAG_RELATIVE) == 0 || !PathInternal.IsExtended(targetPath)); + bool isRelative = (rbSymlink.Flags & Interop.Kernel32.SYMLINK_FLAG_RELATIVE) != 0; + if (!isRelative) + { + // Absolute target is in NT format and we need to clean it up before return it to the user. + if (targetPath.StartsWith(PathInternal.UncNTPathPrefix.AsSpan())) + { + // We need to prepend the Win32 equivalent of UNC NT prefix. + return Path.Join(PathInternal.UncPathPrefix.AsSpan(), targetPath.Slice(PathInternal.UncNTPathPrefix.Length)); + } - if (returnFullPath && (rdb.ReparseBufferSymbolicLink.Flags & Interop.Kernel32.SYMLINK_FLAG_RELATIVE) != 0) + return GetTargetPathWithoutNTPrefix(targetPath); + } + else if (returnFullPath) + { + return Path.Join(Path.GetDirectoryName(linkPath.AsSpan()), targetPath); + } + else + { + return targetPath.ToString(); + } + } + else if (rbSymlink.ReparseTag == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_MOUNT_POINT) { - // Target path is relative and is for ResolveLinkTarget(), we need to append the link directory. - return Path.Join(Path.GetDirectoryName(linkPath.AsSpan()), targetPath); + success = MemoryMarshal.TryRead(bufferSpan, out Interop.Kernel32.MountPointReparseBuffer rbMountPoint); + Debug.Assert(success); + + int offset = sizeof(Interop.Kernel32.MountPointReparseBuffer) + rbMountPoint.SubstituteNameOffset; + int length = rbMountPoint.SubstituteNameLength; + + Span targetPath = MemoryMarshal.Cast(bufferSpan.Slice(offset, length)); + + // Unlike symbolic links, mount point paths cannot be relative. + Debug.Assert(!PathInternal.IsPartiallyQualified(targetPath)); + // Mount points cannot point to a remote location. + Debug.Assert(!targetPath.StartsWith(PathInternal.UncNTPathPrefix.AsSpan())); + return GetTargetPathWithoutNTPrefix(targetPath); } - return targetPath.ToString(); + return null; } finally { ArrayPool.Shared.Return(buffer); } + + static string GetTargetPathWithoutNTPrefix(ReadOnlySpan targetPath) + { + Debug.Assert(targetPath.StartsWith(PathInternal.NTPathPrefix.AsSpan())); + return targetPath.Slice(PathInternal.NTPathPrefix.Length).ToString(); + } } private static unsafe string? GetFinalLinkTarget(string linkPath, bool isDirectory) @@ -539,8 +560,9 @@ internal static void CreateSymbolicLink(string path, string pathToTarget, bool i // The file or directory is not a reparse point. if ((data.dwFileAttributes & (uint)FileAttributes.ReparsePoint) == 0 || - // Only symbolic links are supported at the moment. - (data.dwReserved0 & Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_SYMLINK) == 0) + // Only symbolic links and mount points are supported at the moment. + (data.dwReserved0 != Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_SYMLINK && + data.dwReserved0 != Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_MOUNT_POINT)) { return null; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.NoniOS.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.NoniOS.cs new file mode 100644 index 00000000000000..b2a9a4b06a083e --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.NoniOS.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO +{ + public static partial class Path + { + private static string DefaultTempPath => "/tmp/"; + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs index 61786ad757a434..f3ec19941c21b2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.cs @@ -80,7 +80,6 @@ private static string RemoveLongPathPrefix(string path) public static string GetTempPath() { const string TempEnvVar = "TMPDIR"; - const string DefaultTempPath = "/tmp/"; // Get the temp path from the TMPDIR environment variable. // If it's not set, just return the default path. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.iOS.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.iOS.cs new file mode 100644 index 00000000000000..c1c4a7047eec5e --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Unix.iOS.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. + +using System; + +namespace System.IO +{ + public static partial class Path + { + private static string? s_defaultTempPath; + + private static string DefaultTempPath => + s_defaultTempPath ?? (s_defaultTempPath = Interop.Sys.SearchPathTempDirectory()) ?? + throw new InvalidOperationException(); + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs index b1767b35adea5a..48fb35304cd7d4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathInternal.Windows.cs @@ -46,10 +46,12 @@ internal static partial class PathInternal internal const string DirectorySeparatorCharAsString = "\\"; + internal const string NTPathPrefix = @"\??\"; internal const string ExtendedPathPrefix = @"\\?\"; internal const string UncPathPrefix = @"\\"; internal const string UncExtendedPrefixToInsert = @"?\UNC\"; internal const string UncExtendedPathPrefix = @"\\?\UNC\"; + internal const string UncNTPathPrefix = @"\??\UNC\"; internal const string DevicePathPrefix = @"\\.\"; internal const string ParentDirectoryPrefix = @"..\"; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs index 992dcc54f5be58..d922e89c13de5b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/RandomAccess.Unix.cs @@ -33,9 +33,30 @@ internal static unsafe int ReadAtOffset(SafeFileHandle handle, Span buffer // The Windows implementation uses ReadFile, which ignores the offset if the handle // isn't seekable. We do the same manually with PRead vs Read, in order to enable // the function to be used by FileStream for all the same situations. - int result = handle.CanSeek ? - Interop.Sys.PRead(handle, bufPtr, buffer.Length, fileOffset) : - Interop.Sys.Read(handle, bufPtr, buffer.Length); + int result; + if (handle.SupportsRandomAccess) + { + // Try pread for seekable files. + result = Interop.Sys.PRead(handle, bufPtr, buffer.Length, fileOffset); + if (result == -1) + { + // We need to fallback to the non-offset version for certain file types + // e.g: character devices (such as /dev/tty), pipes, and sockets. + Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo(); + + if (errorInfo.Error == Interop.Error.ENXIO || + errorInfo.Error == Interop.Error.ESPIPE) + { + handle.SupportsRandomAccess = false; + result = Interop.Sys.Read(handle, bufPtr, buffer.Length); + } + } + } + else + { + result = Interop.Sys.Read(handle, bufPtr, buffer.Length); + } + FileStreamHelpers.CheckFileCall(result, handle.Path); return result; } @@ -90,9 +111,29 @@ internal static unsafe void WriteAtOffset(SafeFileHandle handle, ReadOnlySpan ReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, - long fileOffset, CancellationToken cancellationToken) + // From https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfilescatter: + // "The file handle must be created with [...] the FILE_FLAG_OVERLAPPED and FILE_FLAG_NO_BUFFERING flags." + private static bool CanUseScatterGatherWindowsAPIs(SafeFileHandle handle) + => handle.IsAsync && ((handle.GetFileOptions() & SafeFileHandle.NoBuffering) != 0); + + // From the same source: + // "Each buffer must be at least the size of a system memory page and must be aligned on a system + // memory page size boundary. The system reads/writes one system memory page of data into/from each buffer." + // This method returns true if the buffers can be used by + // the Windows scatter/gather API, which happens when they are: + // 1. aligned at page size boundaries + // 2. exactly one page long each (our own requirement to prevent partial reads) + // 3. not bigger than 2^32 - 1 in total + // This function is also responsible for pinning the buffers if they + // are suitable and they must be unpinned after the I/O operation completes. + // It also returns a pointer with the segments to be passed to the + // Windows API, and the total size of the buffers that is needed as well. + // The pinned MemoryHandles and the pointer to the segments must be cleaned-up + // with the CleanupScatterGatherBuffers method. + private static unsafe bool TryPrepareScatterGatherBuffers(IReadOnlyList buffers, + THandler handler, [NotNullWhen(true)] out MemoryHandle[]? handlesToDispose, out IntPtr segmentsPtr, out int totalBytes) + where THandler : struct, IMemoryHandler { - if (!handle.IsAsync) - { - return ScheduleSyncReadScatterAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); - } + int pageSize = s_cachedPageSize; + Debug.Assert(BitOperations.IsPow2(pageSize), "Page size is not a power of two."); + // We take advantage of the fact that the page size is + // a power of two to avoid an expensive modulo operation. + long alignedAtPageSizeMask = pageSize - 1; + + int buffersCount = buffers.Count; + handlesToDispose = null; + segmentsPtr = IntPtr.Zero; + totalBytes = 0; + + long* segments = null; - if (CanUseScatterGatherWindowsAPIs(handle)) + bool success = false; + try { - long totalBytes = 0; - int buffersCount = buffers.Count; + long totalBytes64 = 0; for (int i = 0; i < buffersCount; i++) { - totalBytes += buffers[i].Length; + T buffer = buffers[i]; + int length = handler.GetLength(in buffer); + totalBytes64 += length; + if (length != pageSize || totalBytes64 > int.MaxValue) + { + return false; + } + + MemoryHandle handle = handler.Pin(in buffer); + long ptr = (long)handle.Pointer; + if ((ptr & alignedAtPageSizeMask) != 0) + { + handle.Dispose(); + return false; + } + + // We avoid allocations if there are no + // buffers or the first one is unacceptable. + (handlesToDispose ??= new MemoryHandle[buffersCount])[i] = handle; + if (segments == null) + { + // "The array must contain enough elements to store nNumberOfBytesToWrite + // bytes of data, and one element for the terminating NULL." + segments = (long*)NativeMemory.Alloc((nuint)buffersCount + 1, sizeof(long)); + segments[buffersCount] = 0; + } + segments[i] = ptr; } - if (totalBytes <= int.MaxValue) // the ReadFileScatter API uses int, not long + segmentsPtr = (IntPtr)segments; + totalBytes = (int)totalBytes64; + success = true; + return handlesToDispose != null; + } + finally + { + if (!success) { - return ReadScatterAtOffsetSingleSyscallAsync(handle, buffers, fileOffset, (int)totalBytes, cancellationToken); + CleanupScatterGatherBuffers(handlesToDispose, (IntPtr)segments); } } - - return ReadScatterAtOffsetMultipleSyscallsAsync(handle, buffers, fileOffset, cancellationToken); } - // From https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfilescatter: - // "The file handle must be created with the GENERIC_READ right, and the FILE_FLAG_OVERLAPPED and FILE_FLAG_NO_BUFFERING flags." - private static bool CanUseScatterGatherWindowsAPIs(SafeFileHandle handle) - => handle.IsAsync && ((handle.GetFileOptions() & SafeFileHandle.NoBuffering) != 0); - - private static async ValueTask ReadScatterAtOffsetSingleSyscallAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, int totalBytes, CancellationToken cancellationToken) + private static unsafe void CleanupScatterGatherBuffers(MemoryHandle[]? handlesToDispose, IntPtr segmentsPtr) { - int buffersCount = buffers.Count; - if (buffersCount == 1) + if (handlesToDispose != null) { - // we have to await it because we can't cast a VT to VT - return await ReadAtOffsetAsync(handle, buffers[0], fileOffset, cancellationToken).ConfigureAwait(false); + foreach (MemoryHandle handle in handlesToDispose) + { + handle.Dispose(); + } } - // "The array must contain enough elements to store nNumberOfBytesToWrite bytes of data, and one element for the terminating NULL. " - long[] fileSegments = new long[buffersCount + 1]; - fileSegments[buffersCount] = 0; + if (segmentsPtr != IntPtr.Zero) + { + NativeMemory.Free((void*)segmentsPtr); + } + } - MemoryHandle[] memoryHandles = new MemoryHandle[buffersCount]; - MemoryHandle pinnedSegments = fileSegments.AsMemory().Pin(); + private static ValueTask ReadScatterAtOffsetAsync(SafeFileHandle handle, IReadOnlyList> buffers, + long fileOffset, CancellationToken cancellationToken) + { + if (!handle.IsAsync) + { + return ScheduleSyncReadScatterAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); + } - try + if (CanUseScatterGatherWindowsAPIs(handle) + && TryPrepareScatterGatherBuffers(buffers, default(MemoryHandler), out MemoryHandle[]? handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)) { - for (int i = 0; i < buffersCount; i++) - { - Memory buffer = buffers[i]; - MemoryHandle memoryHandle = buffer.Pin(); - memoryHandles[i] = memoryHandle; + return ReadScatterAtOffsetSingleSyscallAsync(handle, handlesToDispose, segmentsPtr, fileOffset, totalBytes, cancellationToken); + } - unsafe // awaits can't be in an unsafe context - { - fileSegments[i] = new IntPtr(memoryHandle.Pointer).ToInt64(); - } - } + return ReadScatterAtOffsetMultipleSyscallsAsync(handle, buffers, fileOffset, cancellationToken); + } - return await ReadFileScatterAsync(handle, pinnedSegments, totalBytes, fileOffset, cancellationToken).ConfigureAwait(false); + private static async ValueTask ReadScatterAtOffsetSingleSyscallAsync(SafeFileHandle handle, MemoryHandle[] handlesToDispose, IntPtr segmentsPtr, long fileOffset, int totalBytes, CancellationToken cancellationToken) + { + try + { + return await ReadFileScatterAsync(handle, segmentsPtr, totalBytes, fileOffset, cancellationToken).ConfigureAwait(false); } finally { - foreach (MemoryHandle memoryHandle in memoryHandles) - { - memoryHandle.Dispose(); - } - pinnedSegments.Dispose(); + CleanupScatterGatherBuffers(handlesToDispose, segmentsPtr); } } - private static unsafe ValueTask ReadFileScatterAsync(SafeFileHandle handle, MemoryHandle pinnedSegments, int bytesToRead, long fileOffset, CancellationToken cancellationToken) + private static unsafe ValueTask ReadFileScatterAsync(SafeFileHandle handle, IntPtr segmentsPtr, int bytesToRead, long fileOffset, CancellationToken cancellationToken) { handle.EnsureThreadPoolBindingInitialized(); @@ -494,9 +556,9 @@ private static unsafe ValueTask ReadFileScatterAsync(SafeFileHandle handle, try { NativeOverlapped* nativeOverlapped = vts.PrepareForOperation(Memory.Empty, fileOffset); - Debug.Assert(pinnedSegments.Pointer != null); + Debug.Assert(segmentsPtr != IntPtr.Zero); - if (Interop.Kernel32.ReadFileScatter(handle, (long*)pinnedSegments.Pointer, bytesToRead, IntPtr.Zero, nativeOverlapped) == 0) + if (Interop.Kernel32.ReadFileScatter(handle, (long*)segmentsPtr, bytesToRead, IntPtr.Zero, nativeOverlapped) == 0) { // The operation failed, or it's pending. int errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); @@ -562,82 +624,28 @@ private static ValueTask WriteGatherAtOffsetAsync(SafeFileHandle handle, IReadOn return ScheduleSyncWriteGatherAtOffsetAsync(handle, buffers, fileOffset, cancellationToken); } - if (CanUseScatterGatherWindowsAPIs(handle)) + if (CanUseScatterGatherWindowsAPIs(handle) + && TryPrepareScatterGatherBuffers(buffers, default(ReadOnlyMemoryHandler), out MemoryHandle[]? handlesToDispose, out IntPtr segmentsPtr, out int totalBytes)) { - long totalBytes = 0; - for (int i = 0; i < buffers.Count; i++) - { - totalBytes += buffers[i].Length; - } - - if (totalBytes <= int.MaxValue) // the ReadFileScatter API uses int, not long - { - return WriteGatherAtOffsetSingleSyscallAsync(handle, buffers, fileOffset, (int)totalBytes, cancellationToken); - } + return WriteGatherAtOffsetSingleSyscallAsync(handle, handlesToDispose, segmentsPtr, fileOffset, totalBytes, cancellationToken); } return WriteGatherAtOffsetMultipleSyscallsAsync(handle, buffers, fileOffset, cancellationToken); } - private static async ValueTask WriteGatherAtOffsetMultipleSyscallsAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, CancellationToken cancellationToken) - { - long bytesWritten = 0; - int buffersCount = buffers.Count; - for (int i = 0; i < buffersCount; i++) - { - ReadOnlyMemory rom = buffers[i]; - await WriteAtOffsetAsync(handle, rom, fileOffset + bytesWritten, cancellationToken).ConfigureAwait(false); - bytesWritten += rom.Length; - } - } - - private static ValueTask WriteGatherAtOffsetSingleSyscallAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, int totalBytes, CancellationToken cancellationToken) + private static async ValueTask WriteGatherAtOffsetSingleSyscallAsync(SafeFileHandle handle, MemoryHandle[] handlesToDispose, IntPtr segmentsPtr, long fileOffset, int totalBytes, CancellationToken cancellationToken) { - if (buffers.Count == 1) + try { - return WriteAtOffsetAsync(handle, buffers[0], fileOffset, cancellationToken); + await WriteFileGatherAsync(handle, segmentsPtr, totalBytes, fileOffset, cancellationToken).ConfigureAwait(false); } - - return Core(handle, buffers, fileOffset, totalBytes, cancellationToken); - - static async ValueTask Core(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, int totalBytes, CancellationToken cancellationToken) + finally { - // "The array must contain enough elements to store nNumberOfBytesToWrite bytes of data, and one element for the terminating NULL. " - int buffersCount = buffers.Count; - long[] fileSegments = new long[buffersCount + 1]; - fileSegments[buffersCount] = 0; - - MemoryHandle[] memoryHandles = new MemoryHandle[buffersCount]; - MemoryHandle pinnedSegments = fileSegments.AsMemory().Pin(); - - try - { - for (int i = 0; i < buffersCount; i++) - { - ReadOnlyMemory buffer = buffers[i]; - MemoryHandle memoryHandle = buffer.Pin(); - memoryHandles[i] = memoryHandle; - - unsafe // awaits can't be in an unsafe context - { - fileSegments[i] = new IntPtr(memoryHandle.Pointer).ToInt64(); - } - } - - await WriteFileGatherAsync(handle, pinnedSegments, totalBytes, fileOffset, cancellationToken).ConfigureAwait(false); - } - finally - { - foreach (MemoryHandle memoryHandle in memoryHandles) - { - memoryHandle.Dispose(); - } - pinnedSegments.Dispose(); - } + CleanupScatterGatherBuffers(handlesToDispose, segmentsPtr); } } - private static unsafe ValueTask WriteFileGatherAsync(SafeFileHandle handle, MemoryHandle pinnedSegments, int bytesToWrite, long fileOffset, CancellationToken cancellationToken) + private static unsafe ValueTask WriteFileGatherAsync(SafeFileHandle handle, IntPtr segmentsPtr, int bytesToWrite, long fileOffset, CancellationToken cancellationToken) { handle.EnsureThreadPoolBindingInitialized(); @@ -645,10 +653,10 @@ private static unsafe ValueTask WriteFileGatherAsync(SafeFileHandle handle, Memo try { NativeOverlapped* nativeOverlapped = vts.PrepareForOperation(ReadOnlyMemory.Empty, fileOffset); - Debug.Assert(pinnedSegments.Pointer != null); + Debug.Assert(segmentsPtr != IntPtr.Zero); // Queue an async WriteFile operation. - if (Interop.Kernel32.WriteFileGather(handle, (long*)pinnedSegments.Pointer, bytesToWrite, IntPtr.Zero, nativeOverlapped) == 0) + if (Interop.Kernel32.WriteFileGather(handle, (long*)segmentsPtr, bytesToWrite, IntPtr.Zero, nativeOverlapped) == 0) { // The operation failed, or it's pending. int errorCode = FileStreamHelpers.GetLastWin32ErrorAndDisposeHandleIfInvalid(handle); @@ -679,15 +687,28 @@ private static unsafe ValueTask WriteFileGatherAsync(SafeFileHandle handle, Memo return new ValueTask(vts, vts.Version); } - private static unsafe NativeOverlapped* GetNativeOverlappedForAsyncHandle(ThreadPoolBoundHandle threadPoolBinding, long fileOffset, CallbackResetEvent resetEvent) + private static async ValueTask WriteGatherAtOffsetMultipleSyscallsAsync(SafeFileHandle handle, IReadOnlyList> buffers, long fileOffset, CancellationToken cancellationToken) + { + int buffersCount = buffers.Count; + for (int i = 0; i < buffersCount; i++) + { + ReadOnlyMemory rom = buffers[i]; + await WriteAtOffsetAsync(handle, rom, fileOffset, cancellationToken).ConfigureAwait(false); + fileOffset += rom.Length; + } + } + + private static unsafe NativeOverlapped* GetNativeOverlappedForAsyncHandle(SafeFileHandle handle, long fileOffset, CallbackResetEvent resetEvent) { // After SafeFileHandle is bound to ThreadPool, we need to use ThreadPoolBinding // to allocate a native overlapped and provide a valid callback. - NativeOverlapped* result = threadPoolBinding.AllocateNativeOverlapped(s_callback, resetEvent, null); + NativeOverlapped* result = handle.ThreadPoolBinding!.AllocateNativeOverlapped(s_callback, resetEvent, null); - // For pipes the offsets are ignored by the OS - result->OffsetLow = unchecked((int)fileOffset); - result->OffsetHigh = (int)(fileOffset >> 32); + if (handle.CanSeek) + { + result->OffsetLow = unchecked((int)fileOffset); + result->OffsetHigh = (int)(fileOffset >> 32); + } // From https://docs.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-getoverlappedresult: // "If the hEvent member of the OVERLAPPED structure is NULL, the system uses the state of the hFile handle to signal when the operation has been completed. @@ -750,5 +771,25 @@ internal unsafe void FreeNativeOverlapped(NativeOverlapped* pOverlapped) } } } + + // Abstracts away the type signature incompatibility between Memory and ReadOnlyMemory. + // TODO: Use abstract static methods when they become stable. + private interface IMemoryHandler + { + int GetLength(in T memory); + MemoryHandle Pin(in T memory); + } + + private readonly struct MemoryHandler : IMemoryHandler> + { + public int GetLength(in Memory memory) => memory.Length; + public MemoryHandle Pin(in Memory memory) => memory.Pin(); + } + + private readonly struct ReadOnlyMemoryHandler : IMemoryHandler> + { + public int GetLength(in ReadOnlyMemory memory) => memory.Length; + public MemoryHandle Pin(in ReadOnlyMemory memory) => memory.Pin(); + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs index 00d0d2a59b9a6a..9de42145c00ded 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/BufferedFileStreamStrategy.cs @@ -974,11 +974,12 @@ public override long Seek(long offset, SeekOrigin origin) // Otherwise we will throw away the buffer. This can only happen on read, as we flushed write data above. // The offset of the new/updated seek pointer within _buffer: - _readPos = (int)(newPos - (oldPos - _readPos)); + long readPos = (newPos - (oldPos - _readPos)); // If the offset of the updated seek pointer in the buffer is still legal, then we can keep using the buffer: - if (0 <= _readPos && _readPos < _readLen) + if (0 <= readPos && readPos < _readLen) { + _readPos = (int)readPos; // Adjust the seek pointer of the underlying stream to reflect the amount of useful bytes in the read buffer: _strategy.Seek(_readLen - _readPos, SeekOrigin.Current); } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs index 779acce9373717..5ba493ca9ca215 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.Windows.cs @@ -123,6 +123,16 @@ internal static void Unlock(SafeFileHandle handle, long position, long length) } internal static unsafe void SetFileLength(SafeFileHandle handle, long length) + { + if (!TrySetFileLength(handle, length, out int errorCode)) + { + throw errorCode == Interop.Errors.ERROR_INVALID_PARAMETER + ? new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_FileLengthTooBig) + : Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path); + } + } + + internal static unsafe bool TrySetFileLength(SafeFileHandle handle, long length, out int errorCode) { var eofInfo = new Interop.Kernel32.FILE_END_OF_FILE_INFO { @@ -135,11 +145,12 @@ internal static unsafe void SetFileLength(SafeFileHandle handle, long length) &eofInfo, (uint)sizeof(Interop.Kernel32.FILE_END_OF_FILE_INFO))) { - int errorCode = Marshal.GetLastPInvokeError(); - if (errorCode == Interop.Errors.ERROR_INVALID_PARAMETER) - throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_FileLengthTooBig); - throw Win32Marshal.GetExceptionForWin32Error(errorCode, handle.Path); + errorCode = Marshal.GetLastPInvokeError(); + return false; } + + errorCode = Interop.Errors.ERROR_SUCCESS; + return true; } internal static unsafe int ReadFileNative(SafeFileHandle handle, Span bytes, NativeOverlapped* overlapped, out int errorCode) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs index d86c70a621ca1a..3db2174d3fbd14 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Strategies/FileStreamHelpers.cs @@ -58,11 +58,6 @@ e is UnauthorizedAccessException || e is NotSupportedException || (e is ArgumentException && !(e is ArgumentNullException)); - internal static bool ShouldPreallocate(long preallocationSize, FileAccess access, FileMode mode) - => preallocationSize > 0 - && (access & FileAccess.Write) != 0 - && mode != FileMode.Open && mode != FileMode.Append; - internal static void ValidateArguments(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize) { if (path == null) @@ -125,9 +120,31 @@ internal static void ValidateArguments(string path, FileMode mode, FileAccess ac throw new ArgumentException(SR.Argument_InvalidAppendMode, nameof(access)); } + if (preallocationSize > 0) + { + ValidateArgumentsForPreallocation(mode, access); + } + SerializationGuard(access); } + internal static void ValidateArgumentsForPreallocation(FileMode mode, FileAccess access) + { + // The user will be writing into the preallocated space. + if ((access & FileAccess.Write) == 0) + { + throw new ArgumentException(SR.Argument_InvalidPreallocateAccess, nameof(access)); + } + + // Only allow preallocation for newly created/overwritten files. + // When we fail to preallocate, we'll remove the file. + if (mode != FileMode.Create && + mode != FileMode.CreateNew) + { + throw new ArgumentException(SR.Argument_InvalidPreallocateMode, nameof(mode)); + } + } + internal static void SerializationGuard(FileAccess access) { if ((access & FileAccess.Write) == FileAccess.Write) diff --git a/src/libraries/System.Private.CoreLib/src/System/IParseable.cs b/src/libraries/System.Private.CoreLib/src/System/IParseable.cs index 77064639e368ac..5a715cab0831af 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IParseable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IParseable.cs @@ -12,7 +12,7 @@ namespace System { /// Defines a mechanism for parsing a string to a value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IParseable where TSelf : IParseable { diff --git a/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs index 8ba4d810233dc6..ad0af7155d4fb0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IShiftOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for shifting a value by another value. /// The type that implements this interface. /// The type that contains the result of shifting by . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IShiftOperators where TSelf : IShiftOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs b/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs index 0998785f780ba3..15e7717435d960 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISpanFormattable.cs @@ -15,6 +15,7 @@ public interface ISpanFormattable : IFormattable /// /// An implementation of this interface should produce the same string of characters as an implementation of /// on the same type. + /// TryFormat should return false only if there is not enough space in the destination buffer. Any other failures should throw an exception. /// bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider); } diff --git a/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs b/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs index 6264fe15802926..34dad1427db4af 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISpanParseable.cs @@ -11,7 +11,7 @@ namespace System { /// Defines a mechanism for parsing a span of characters to a value. /// The type that implements this interface. - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface ISpanParseable : IParseable where TSelf : ISpanParseable { diff --git a/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs b/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs index f11da9d2f98125..5cbe1a634477f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ISubtractionOperators.cs @@ -13,7 +13,7 @@ namespace System /// The type that implements this interface. /// The type that will be subtracted from . /// The type that contains the difference of subtracted from . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface ISubtractionOperators where TSelf : ISubtractionOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs index 686887ce9c8fd8..5ccede089fe2c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IUnaryNegationOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for computing the unary negation of a value. /// The type that implements this interface. /// The type that contains the result of negating . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IUnaryNegationOperators where TSelf : IUnaryNegationOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs b/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs index a719ff5d0b11e8..2d4dd964136d08 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IUnaryPlusOperators.cs @@ -12,7 +12,7 @@ namespace System /// Defines a mechanism for computing the unary plus of a value. /// The type that implements this interface. /// The type that contains the result of negating . - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public interface IUnaryPlusOperators where TSelf : IUnaryPlusOperators { diff --git a/src/libraries/System.Private.CoreLib/src/System/Int16.cs b/src/libraries/System.Private.CoreLib/src/System/Int16.cs index 909b37f77b340b..c99007c0afca37 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int16.cs @@ -288,11 +288,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IAdditionOperators.operator +(short left, short right) => (short)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IAdditionOperators.operator +(short left, short right) // => checked((short)(left + right)); @@ -300,30 +300,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.LeadingZeroCount(short value) => (short)(BitOperations.LeadingZeroCount((ushort)value) - 16); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.PopCount(short value) => (short)BitOperations.PopCount((ushort)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.RotateLeft(short value, int rotateAmount) => (short)((value << (rotateAmount & 15)) | ((ushort)value >> ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.RotateRight(short value, int rotateAmount) => (short)(((ushort)value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryInteger.TrailingZeroCount(short value) => (byte)(BitOperations.TrailingZeroCount(value << 16) - 16); @@ -331,11 +331,11 @@ static short IBinaryInteger.TrailingZeroCount(short value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(short value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBinaryNumber.Log2(short value) { if (value < 0) @@ -349,19 +349,19 @@ static short IBinaryNumber.Log2(short value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator &(short left, short right) => (short)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator |(short left, short right) => (short)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator ^(short left, short right) => (short)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IBitwiseOperators.operator ~(short value) => (short)(~value); @@ -369,19 +369,19 @@ static short IBinaryNumber.Log2(short value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(short left, short right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(short left, short right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(short left, short right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(short left, short right) => left >= right; @@ -389,11 +389,11 @@ static short IBinaryNumber.Log2(short value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IDecrementOperators.operator --(short value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IDecrementOperators.operator --(short value) // => checked(--value); @@ -401,11 +401,11 @@ static short IBinaryNumber.Log2(short value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IDivisionOperators.operator /(short left, short right) => (short)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IDivisionOperators.operator /(short left, short right) // => checked((short)(left / right)); @@ -413,11 +413,11 @@ static short IBinaryNumber.Log2(short value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(short left, short right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(short left, short right) => left != right; @@ -425,11 +425,11 @@ static short IBinaryNumber.Log2(short value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IIncrementOperators.operator ++(short value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IIncrementOperators.operator ++(short value) // => checked(++value); @@ -437,21 +437,21 @@ static short IBinaryNumber.Log2(short value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IModulusOperators.operator %(short left, short right) => (short)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IModulusOperators.operator %(short left, short right) // => checked((short)(left % right)); @@ -459,18 +459,18 @@ static short IBinaryNumber.Log2(short value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IMultiplyOperators.operator *(short left, short right) => (short)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IMultiplyOperators.operator *(short left, short right) // => checked((short)(left * right)); @@ -478,21 +478,21 @@ static short IBinaryNumber.Log2(short value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Abs(short value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Clamp(short value, short min, short max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static short INumber.Create(TOther value) { @@ -559,7 +559,7 @@ static short INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static short INumber.CreateSaturating(TOther value) { @@ -643,7 +643,7 @@ static short INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static short INumber.CreateTruncating(TOther value) { @@ -710,31 +710,31 @@ static short INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (short Quotient, short Remainder) INumber.DivRem(short left, short right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Max(short x, short y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Min(short x, short y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short INumber.Sign(short value) => (short)Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out short result) { @@ -904,11 +904,11 @@ static bool INumber.TryCreate(TOther value, out short result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out short result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out short result) => TryParse(s, style, provider, out result); @@ -916,11 +916,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out short result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -928,15 +928,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IShiftOperators.operator <<(short value, int shiftAmount) => (short)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IShiftOperators.operator >>(short value, int shiftAmount) => (short)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static short IShiftOperators.operator >>>(short value, int shiftAmount) // => (short)((ushort)value >> shiftAmount); @@ -944,18 +944,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out short result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -963,11 +963,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short ISubtractionOperators.operator -(short left, short right) => (short)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short ISubtractionOperators.operator -(short left, short right) // => checked((short)(left - right)); @@ -975,11 +975,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IUnaryNegationOperators.operator -(short value) => (short)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IUnaryNegationOperators.operator -(short value) // => checked((short)(-value)); @@ -987,11 +987,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static short IUnaryPlusOperators.operator +(short value) => (short)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked short IUnaryPlusOperators.operator +(short value) // => checked((short)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Int32.cs b/src/libraries/System.Private.CoreLib/src/System/Int32.cs index 68c6a70cdb0438..5443b6fe289d68 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int32.cs @@ -280,11 +280,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IAdditionOperators.operator +(int left, int right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IAdditionOperators.operator +(int left, int right) // => checked(left + right); @@ -292,30 +292,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.LeadingZeroCount(int value) => BitOperations.LeadingZeroCount((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.PopCount(int value) => BitOperations.PopCount((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.RotateLeft(int value, int rotateAmount) => (int)BitOperations.RotateLeft((uint)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.RotateRight(int value, int rotateAmount) => (int)BitOperations.RotateRight((uint)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryInteger.TrailingZeroCount(int value) => BitOperations.TrailingZeroCount(value); @@ -323,11 +323,11 @@ static int IBinaryInteger.TrailingZeroCount(int value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(int value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBinaryNumber.Log2(int value) { if (value < 0) @@ -341,19 +341,19 @@ static int IBinaryNumber.Log2(int value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator &(int left, int right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator |(int left, int right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator ^(int left, int right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IBitwiseOperators.operator ~(int value) => ~value; @@ -361,19 +361,19 @@ static int IBinaryNumber.Log2(int value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(int left, int right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(int left, int right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(int left, int right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(int left, int right) => left >= right; @@ -381,11 +381,11 @@ static int IBinaryNumber.Log2(int value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IDecrementOperators.operator --(int value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IDecrementOperators.operator --(int value) // => checked(--value); @@ -393,11 +393,11 @@ static int IBinaryNumber.Log2(int value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IDivisionOperators.operator /(int left, int right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IDivisionOperators.operator /(int left, int right) // => checked(left / right); @@ -405,11 +405,11 @@ static int IBinaryNumber.Log2(int value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(int left, int right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(int left, int right) => left != right; @@ -417,11 +417,11 @@ static int IBinaryNumber.Log2(int value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IIncrementOperators.operator ++(int value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IIncrementOperators.operator ++(int value) // => checked(++value); @@ -429,21 +429,21 @@ static int IBinaryNumber.Log2(int value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IModulusOperators.operator %(int left, int right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IModulusOperators.operator %(int left, int right) // => checked(left % right); @@ -451,18 +451,18 @@ static int IBinaryNumber.Log2(int value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IMultiplyOperators.operator *(int left, int right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IMultiplyOperators.operator *(int left, int right) // => checked(left * right); @@ -470,21 +470,21 @@ static int IBinaryNumber.Log2(int value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Abs(int value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Clamp(int value, int min, int max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] internal static int Create(TOther value) where TOther : INumber { @@ -551,12 +551,12 @@ internal static int Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static int INumber.Create(TOther value) => Create(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static int INumber.CreateSaturating(TOther value) { @@ -636,7 +636,7 @@ static int INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static int INumber.CreateTruncating(TOther value) { @@ -703,31 +703,31 @@ static int INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (int Quotient, int Remainder) INumber.DivRem(int left, int right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Max(int x, int y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Min(int x, int y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int INumber.Sign(int value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out int result) { @@ -873,11 +873,11 @@ static bool INumber.TryCreate(TOther value, out int result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out int result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out int result) => TryParse(s, style, provider, out result); @@ -885,11 +885,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFor // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out int result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -897,15 +897,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvi // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IShiftOperators.operator <<(int value, int shiftAmount) => value << shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IShiftOperators.operator >>(int value, int shiftAmount) => value >> shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static int IShiftOperators.operator >>>(int value, int shiftAmount) // => (int)((uint)value >> shiftAmount); @@ -913,18 +913,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvi // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out int result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -932,11 +932,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int ISubtractionOperators.operator -(int left, int right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int ISubtractionOperators.operator -(int left, int right) // => checked(left - right); @@ -944,11 +944,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IUnaryNegationOperators.operator -(int value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IUnaryNegationOperators.operator -(int value) // => checked(-value); @@ -956,11 +956,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static int IUnaryPlusOperators.operator +(int value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked int IUnaryPlusOperators.operator +(int value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Int64.cs b/src/libraries/System.Private.CoreLib/src/System/Int64.cs index 1646cf96457eff..7839b8c1235947 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Int64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Int64.cs @@ -267,11 +267,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IAdditionOperators.operator +(long left, long right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IAdditionOperators.operator +(long left, long right) // => checked(left + right); @@ -279,30 +279,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.LeadingZeroCount(long value) => BitOperations.LeadingZeroCount((ulong)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.PopCount(long value) => BitOperations.PopCount((ulong)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.RotateLeft(long value, int rotateAmount) => (long)BitOperations.RotateLeft((ulong)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.RotateRight(long value, int rotateAmount) => (long)BitOperations.RotateRight((ulong)value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryInteger.TrailingZeroCount(long value) => BitOperations.TrailingZeroCount(value); @@ -310,11 +310,11 @@ static long IBinaryInteger.TrailingZeroCount(long value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(long value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBinaryNumber.Log2(long value) { if (value < 0) @@ -328,19 +328,19 @@ static long IBinaryNumber.Log2(long value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator &(long left, long right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator |(long left, long right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator ^(long left, long right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IBitwiseOperators.operator ~(long value) => ~value; @@ -348,19 +348,19 @@ static long IBinaryNumber.Log2(long value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(long left, long right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(long left, long right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(long left, long right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(long left, long right) => left >= right; @@ -368,11 +368,11 @@ static long IBinaryNumber.Log2(long value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IDecrementOperators.operator --(long value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IDecrementOperators.operator --(long value) // => checked(--value); @@ -380,11 +380,11 @@ static long IBinaryNumber.Log2(long value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IDivisionOperators.operator /(long left, long right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IDivisionOperators.operator /(long left, long right) // => checked(left / right); @@ -392,11 +392,11 @@ static long IBinaryNumber.Log2(long value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(long left, long right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(long left, long right) => left != right; @@ -404,11 +404,11 @@ static long IBinaryNumber.Log2(long value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IIncrementOperators.operator ++(long value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IIncrementOperators.operator ++(long value) // => checked(++value); @@ -416,21 +416,21 @@ static long IBinaryNumber.Log2(long value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IModulusOperators.operator %(long left, long right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IModulusOperators.operator %(long left, long right) // => checked(left % right); @@ -438,18 +438,18 @@ static long IBinaryNumber.Log2(long value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IMultiplyOperators.operator *(long left, long right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IMultiplyOperators.operator *(long left, long right) // => checked(left * right); @@ -457,21 +457,21 @@ static long IBinaryNumber.Log2(long value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Abs(long value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Clamp(long value, long min, long max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static long INumber.Create(TOther value) { @@ -538,7 +538,7 @@ static long INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static long INumber.CreateSaturating(TOther value) { @@ -613,7 +613,7 @@ static long INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static long INumber.CreateTruncating(TOther value) { @@ -680,31 +680,31 @@ static long INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (long Quotient, long Remainder) INumber.DivRem(long left, long right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Max(long x, long y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Min(long x, long y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long INumber.Sign(long value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out long result) { @@ -826,11 +826,11 @@ static bool INumber.TryCreate(TOther value, out long result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out long result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out long result) => TryParse(s, style, provider, out result); @@ -838,11 +838,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out long result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -850,15 +850,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IShiftOperators.operator <<(long value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IShiftOperators.operator >>(long value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static long IShiftOperators.operator >>>(long value, int shiftAmount) // => (long)((ulong)value >> (int)shiftAmount); @@ -866,18 +866,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out long result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -885,11 +885,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long ISubtractionOperators.operator -(long left, long right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long ISubtractionOperators.operator -(long left, long right) // => checked(left - right); @@ -897,11 +897,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IUnaryNegationOperators.operator -(long value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IUnaryNegationOperators.operator -(long value) // => checked(-value); @@ -909,11 +909,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static long IUnaryPlusOperators.operator +(long value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked long IUnaryPlusOperators.operator +(long value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index a9592617b2eb25..a5c01b9781f2c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -254,11 +254,11 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IAdditionOperators.operator +(nint left, nint right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IAdditionOperators.operator +(nint left, nint right) // => checked(left + right); @@ -266,14 +266,14 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.LeadingZeroCount(nint value) { if (Environment.Is64BitProcess) @@ -286,7 +286,7 @@ static nint IBinaryInteger.LeadingZeroCount(nint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.PopCount(nint value) { if (Environment.Is64BitProcess) @@ -299,7 +299,7 @@ static nint IBinaryInteger.PopCount(nint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.RotateLeft(nint value, int rotateAmount) { if (Environment.Is64BitProcess) @@ -312,7 +312,7 @@ static nint IBinaryInteger.RotateLeft(nint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.RotateRight(nint value, int rotateAmount) { @@ -326,7 +326,7 @@ static nint IBinaryInteger.RotateRight(nint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryInteger.TrailingZeroCount(nint value) { if (Environment.Is64BitProcess) @@ -343,11 +343,11 @@ static nint IBinaryInteger.TrailingZeroCount(nint value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(nint value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBinaryNumber.Log2(nint value) { if (value < 0) @@ -369,19 +369,19 @@ static nint IBinaryNumber.Log2(nint value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator &(nint left, nint right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator |(nint left, nint right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator ^(nint left, nint right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IBitwiseOperators.operator ~(nint value) => ~value; @@ -389,19 +389,19 @@ static nint IBinaryNumber.Log2(nint value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(nint left, nint right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(nint left, nint right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(nint left, nint right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(nint left, nint right) => left >= right; @@ -409,11 +409,11 @@ static nint IBinaryNumber.Log2(nint value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IDecrementOperators.operator --(nint value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IDecrementOperators.operator --(nint value) // => checked(--value); @@ -421,11 +421,11 @@ static nint IBinaryNumber.Log2(nint value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IDivisionOperators.operator /(nint left, nint right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IDivisionOperators.operator /(nint left, nint right) // => checked(left / right); @@ -433,11 +433,11 @@ static nint IBinaryNumber.Log2(nint value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(nint left, nint right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(nint left, nint right) => left != right; @@ -445,11 +445,11 @@ static nint IBinaryNumber.Log2(nint value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IIncrementOperators.operator ++(nint value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IIncrementOperators.operator ++(nint value) // => checked(++value); @@ -457,21 +457,21 @@ static nint IBinaryNumber.Log2(nint value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IModulusOperators.operator %(nint left, nint right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IModulusOperators.operator %(nint left, nint right) // => checked(left % right); @@ -479,18 +479,18 @@ static nint IBinaryNumber.Log2(nint value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IMultiplyOperators.operator *(nint left, nint right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IMultiplyOperators.operator *(nint left, nint right) // => checked(left * right); @@ -498,21 +498,21 @@ static nint IBinaryNumber.Log2(nint value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Abs(nint value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Clamp(nint value, nint min, nint max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nint INumber.Create(TOther value) { @@ -579,7 +579,7 @@ static nint INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nint INumber.CreateSaturating(TOther value) { @@ -657,7 +657,7 @@ static nint INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nint INumber.CreateTruncating(TOther value) { @@ -724,31 +724,31 @@ static nint INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (nint Quotient, nint Remainder) INumber.DivRem(nint left, nint right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Max(nint x, nint y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Min(nint x, nint y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint INumber.Sign(nint value) => Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out nint result) { @@ -886,11 +886,11 @@ static bool INumber.TryCreate(TOther value, out nint result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out nint result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out nint result) => TryParse(s, style, provider, out result); @@ -898,11 +898,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out nint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -910,15 +910,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IShiftOperators.operator <<(nint value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IShiftOperators.operator >>(nint value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static nint IShiftOperators.operator >>>(nint value, int shiftAmount) // => (nint)((nuint)value >> (int)shiftAmount); @@ -926,18 +926,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out nint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -945,11 +945,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint ISubtractionOperators.operator -(nint left, nint right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint ISubtractionOperators.operator -(nint left, nint right) // => checked(left - right); @@ -957,11 +957,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IUnaryNegationOperators.operator -(nint value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IUnaryNegationOperators.operator -(nint value) // => checked(-value); @@ -969,11 +969,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nint IUnaryPlusOperators.operator +(nint value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nint IUnaryPlusOperators.operator +(nint value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs index 408c83cb050585..f722e028106556 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -242,6 +242,8 @@ namespace System internal static partial class Number { internal const int DecimalPrecision = 29; // Decimal.DecCalc also uses this value + internal const string PreviewFeatureMessage = "Generic Math is in preview."; + internal const string PreviewFeatureUrl = "https://aka.ms/dotnet-warnings/generic-math-preview"; // SinglePrecision and DoublePrecision represent the maximum number of digits required // to guarantee that any given Single or Double can roundtrip. Some numbers may require diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs index 18d033b5c4394d..3198e9fd458027 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs @@ -66,7 +66,7 @@ internal string ToString(bool typed) result.Append('['); int count = array.Count; result.Append(count.ToString()); - result.Append(']'); + result.Append("] { "); for (int i = 0; i < count; i++) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs index 203bafd4d66c72..b09bb83a5a6870 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/NullabilityInfoContext.cs @@ -347,19 +347,23 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, ILi private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, IList customAttributes, int index) { NullabilityState state = NullabilityState.Unknown; + NullabilityInfo? elementState = null; + NullabilityInfo[] genericArgumentsState = Array.Empty(); + Type? underlyingType = type; if (type.IsValueType) { - if (Nullable.GetUnderlyingType(type) != null) + underlyingType = Nullable.GetUnderlyingType(type); + + if (underlyingType != null) { state = NullabilityState.Nullable; } else { + underlyingType = type; state = NullabilityState.NotNull; } - - return new NullabilityInfo(type, state, state, null, Array.Empty()); } else { @@ -368,32 +372,38 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, ILi state = GetNullableContext(memberInfo); } - NullabilityInfo? elementState = null; - NullabilityInfo[]? genericArgumentsState = null; - if (type.IsArray) { elementState = GetNullabilityInfo(memberInfo, type.GetElementType()!, customAttributes, index + 1); } - else if (type.IsGenericType) + } + + if (underlyingType.IsGenericType) + { + Type[] genericArguments = underlyingType.GetGenericArguments(); + genericArgumentsState = new NullabilityInfo[genericArguments.Length]; + + for (int i = 0, offset = 0; i < genericArguments.Length; i++) { - Type[] genericArguments = type.GetGenericArguments(); - genericArgumentsState = new NullabilityInfo[genericArguments.Length]; + Type t = Nullable.GetUnderlyingType(genericArguments[i]) ?? genericArguments[i]; - for (int i = 0; i < genericArguments.Length; i++) + if (!t.IsValueType || t.IsGenericType) { - genericArgumentsState[i] = GetNullabilityInfo(memberInfo, genericArguments[i], customAttributes, i + 1); + offset++; } - } - NullabilityInfo nullability = new NullabilityInfo(type, state, state, elementState, genericArgumentsState ?? Array.Empty()); - if (state != NullabilityState.Unknown) - { - TryLoadGenericMetaTypeNullability(memberInfo, nullability); + genericArgumentsState[i] = GetNullabilityInfo(memberInfo, genericArguments[i], customAttributes, index + offset); } + } + + NullabilityInfo nullability = new NullabilityInfo(type, state, state, elementState, genericArgumentsState); - return nullability; + if (!type.IsValueType && state != NullabilityState.Unknown) + { + TryLoadGenericMetaTypeNullability(memberInfo, nullability); } + + return nullability; } private static bool ParseNullableState(IList customAttributes, int index, ref NullabilityState state) @@ -472,7 +482,7 @@ private void CheckGenericParameters(NullabilityInfo nullability, MemberInfo meta { NullabilityState state = nullability.ReadState; - if (!ParseNullableState(metaType.GetCustomAttributesData(), 0, ref state)) + if (state == NullabilityState.NotNull && !ParseNullableState(metaType.GetCustomAttributesData(), 0, ref state)) { state = GetNullableContext(metaType); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs index 2630e0f2c1b7b0..a3820ba6d69b9e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeFeature.cs @@ -30,7 +30,7 @@ public static partial class RuntimeFeature /// /// Indicates that this version of runtime supports virtual static members of interfaces. /// - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] public const string VirtualStaticsInInterfaces = nameof(VirtualStaticsInInterfaces); /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs index e1f88f2af98512..17b15436642892 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/SkipLocalsInitAttribute.cs @@ -25,7 +25,12 @@ namespace System.Runtime.CompilerServices | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)] - public sealed class SkipLocalsInitAttribute : Attribute +#if SYSTEM_PRIVATE_CORELIB + public +#else + internal +#endif + sealed class SkipLocalsInitAttribute : Attribute { public SkipLocalsInitAttribute() { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs index e3cb842f2a5294..62d9a8d30e1a33 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NFloat.cs @@ -2,7 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Internal.Runtime.CompilerServices; #pragma warning disable SA1121 // We use our own aliases since they differ per platform #if TARGET_32BIT @@ -13,65 +17,691 @@ namespace System.Runtime.InteropServices { - /// - /// is an immutable value type that represents a floating type that has the same size - /// as the native integer size. - /// It is meant to be used as an exchange type at the managed/unmanaged boundary to accurately represent - /// in managed code unmanaged APIs that use a type alias for C or C++'s float on 32-bit platforms - /// or double on 64-bit platforms, such as the CGFloat type in libraries provided by Apple. - /// + /// Defines an immutable value type that represents a floating type that has the same size as the native integer size. + /// It is meant to be used as an exchange type at the managed/unmanaged boundary to accurately represent in managed code unmanaged APIs that use a type alias for C or C++'s float on 32-bit platforms or double on 64-bit platforms, such as the CGFloat type in libraries provided by Apple. [Intrinsic] - public readonly struct NFloat : IEquatable + public readonly struct NFloat + : IComparable, + IComparable, + IEquatable, + ISpanFormattable { + private const NumberStyles DefaultNumberStyles = NumberStyles.Float | NumberStyles.AllowThousands; + private readonly NativeType _value; - /// - /// Constructs an instance from a 32-bit floating point value. - /// - /// The floating-point vaule. + /// Constructs an instance from a 32-bit floating point value. + /// The floating-point value. + [NonVersionable] public NFloat(float value) { _value = value; } - /// - /// Constructs an instance from a 64-bit floating point value. - /// - /// The floating-point vaule. + /// Constructs an instance from a 64-bit floating point value. + /// The floating-point value. + [NonVersionable] public NFloat(double value) { _value = (NativeType)value; } - /// - /// The underlying floating-point value of this instance. - /// - public double Value => _value; + /// Represents the smallest positive NFloat value that is greater than zero. + public static NFloat Epsilon + { + [NonVersionable] + get => new NFloat(NativeType.Epsilon); + } + + /// Represents the largest finite value of a NFloat. + public static NFloat MaxValue + { + [NonVersionable] + get => new NFloat(NativeType.MaxValue); + } + + /// Represents the smallest finite value of a NFloat. + public static NFloat MinValue + { + [NonVersionable] + get => new NFloat(NativeType.MinValue); + } + + /// Represents a value that is not a number (NaN). + public static NFloat NaN + { + [NonVersionable] + get => new NFloat(NativeType.NaN); + } + + /// Represents negative infinity. + public static NFloat NegativeInfinity + { + [NonVersionable] + get => new NFloat(NativeType.NegativeInfinity); + } + + /// Represents positive infinity. + public static NFloat PositiveInfinity + { + [NonVersionable] + get => new NFloat(NativeType.PositiveInfinity); + } + + /// Gets the size, in bytes, of an NFloat. + public static int Size + { + [NonVersionable] + get => sizeof(NativeType); + } + + /// The underlying floating-point value of this instance. + public double Value + { + [NonVersionable] + get => _value; + } + + // + // Unary Arithmetic + // + + /// Computes the unary plus of a value. + /// The value for which to compute its unary plus. + /// The unary plus of . + [NonVersionable] + public static NFloat operator +(NFloat value) => value; + + /// Computes the unary negation of a value. + /// The value for which to compute its unary negation. + /// The unary negation of . + [NonVersionable] + public static NFloat operator -(NFloat value) => new NFloat(-value._value); + + /// Increments a value. + /// The value to increment. + /// The result of incrementing . + [NonVersionable] + public static NFloat operator ++(NFloat value) => new NFloat(value._value + 1); + + /// Decrements a value. + /// The value to decrement. + /// The result of decrementing . + [NonVersionable] + public static NFloat operator --(NFloat value) => new NFloat(value._value - 1); + + // + // Binary Arithmetic + // + + /// Adds two values together to compute their sum. + /// The value to which is added. + /// The value which is added to . + /// The sum of and . + [NonVersionable] + public static NFloat operator +(NFloat left, NFloat right) => new NFloat(left._value + right._value); + + /// Subtracts two values to compute their difference. + /// The value from which is subtracted. + /// The value which is subtracted from . + /// The difference of subtracted from . + [NonVersionable] + public static NFloat operator -(NFloat left, NFloat right) => new NFloat(left._value - right._value); + + /// Multiplies two values together to compute their product. + /// The value which multiplies. + /// The value which multiplies . + /// The product of divided-by . + [NonVersionable] + public static NFloat operator *(NFloat left, NFloat right) => new NFloat(left._value * right._value); + + /// Divides two values together to compute their quotient. + /// The value which divides. + /// The value which divides . + /// The quotient of divided-by . + [NonVersionable] + public static NFloat operator /(NFloat left, NFloat right) => new NFloat(left._value / right._value); + + /// Divides two values together to compute their remainder. + /// The value which divides. + /// The value which divides . + /// The remainder of divided-by . + [NonVersionable] + public static NFloat operator %(NFloat left, NFloat right) => new NFloat(left._value % right._value); + + // + // Comparisons + // + + /// Compares two values to determine equality. + /// The value to compare with . + /// The value to compare with . + /// true if is equal to ; otherwise, false. + [NonVersionable] + public static bool operator ==(NFloat left, NFloat right) => left._value == right._value; + + /// Compares two values to determine inequality. + /// The value to compare with . + /// The value to compare with . + /// true if is not equal to ; otherwise, false. + [NonVersionable] + public static bool operator !=(NFloat left, NFloat right) => left._value != right._value; + + /// Compares two values to determine which is less. + /// The value to compare with . + /// The value to compare with . + /// true if is less than ; otherwise, false. + [NonVersionable] + public static bool operator <(NFloat left, NFloat right) => left._value < right._value; + + /// Compares two values to determine which is less or equal. + /// The value to compare with . + /// The value to compare with . + /// true if is less than or equal to ; otherwise, false. + [NonVersionable] + public static bool operator <=(NFloat left, NFloat right) => left._value <= right._value; + + /// Compares two values to determine which is greater. + /// The value to compare with . + /// The value to compare with . + /// true if is greater than ; otherwise, false. + [NonVersionable] + public static bool operator >(NFloat left, NFloat right) => left._value > right._value; + + /// Compares two values to determine which is greater or equal. + /// The value to compare with . + /// The value to compare with . + /// true if is greater than or equal to ; otherwise, false. + [NonVersionable] + public static bool operator >=(NFloat left, NFloat right) => left._value >= right._value; + + // + // Explicit Convert To NFloat + // + + /// Explicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static explicit operator NFloat(decimal value) => new NFloat((NativeType)value); + + /// Explicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static explicit operator NFloat(double value) => new NFloat((NativeType)value); + + // + // Explicit Convert From NFloat + // + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator byte(NFloat value) => (byte)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator char(NFloat value) => (char)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator decimal(NFloat value) => (decimal)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator short(NFloat value) => (short)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator int(NFloat value) => (int)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator long(NFloat value) => (long)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator nint(NFloat value) => (nint)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator sbyte(NFloat value) => (sbyte)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + public static explicit operator float(NFloat value) => (float)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator ushort(NFloat value) => (ushort)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator uint(NFloat value) => (uint)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator ulong(NFloat value) => (ulong)(value._value); + + /// Explicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + [NonVersionable] + [CLSCompliant(false)] + public static explicit operator nuint(NFloat value) => (nuint)(value._value); + + // + // Implicit Convert To NFloat + // - /// - /// Returns a value indicating whether this instance is equal to a specified object. - /// - /// An object to compare with this instance. - /// true if is an instance of and equals the value of this instance; otherwise, false. - public override bool Equals([NotNullWhen(true)] object? o) => o is NFloat other && Equals(other); + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(byte value) => new NFloat((NativeType)value); - /// - /// Returns a value indicating whether this instance is equal to a specified value. - /// + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(char value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(short value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(int value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(long value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(nint value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(sbyte value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + public static implicit operator NFloat(float value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(ushort value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(uint value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(ulong value) => new NFloat((NativeType)value); + + /// Implicitly converts a value to its nearest representable native-sized floating-point value. + /// The value to convert. + /// converted to its nearest representable native-sized floating-point value. + [NonVersionable] + [CLSCompliant(false)] + public static implicit operator NFloat(nuint value) => new NFloat((NativeType)value); + + // + // Implicit Convert From NFloat + // + + /// Implicitly converts a native-sized floating-point value to its nearest representable value. + /// The value to convert. + /// converted to its nearest representable value. + public static implicit operator double(NFloat value) => (double)(value._value); + + /// Determines whether the specified value is finite (zero, subnormal, or normal). + /// The floating-point value. + /// true if the value is finite (zero, subnormal or normal); false otherwise. + [NonVersionable] + public static bool IsFinite(NFloat value) => NativeType.IsFinite(value._value); + + /// Determines whether the specified value is infinite (positive or negative infinity). + /// The floating-point value. + /// true if the value is infinite (positive or negative infinity); false otherwise. + [NonVersionable] + public static bool IsInfinity(NFloat value) => NativeType.IsInfinity(value._value); + + /// Determines whether the specified value is NaN (not a number). + /// The floating-point value. + /// true if the value is NaN (not a number); false otherwise. + [NonVersionable] + public static bool IsNaN(NFloat value) => NativeType.IsNaN(value._value); + + /// Determines whether the specified value is negative. + /// The floating-point value. + /// true if the value is negative; false otherwise. + [NonVersionable] + public static bool IsNegative(NFloat value) => NativeType.IsNegative(value._value); + + /// Determines whether the specified value is negative infinity. + /// The floating-point value. + /// true if the value is negative infinity; false otherwise. + [NonVersionable] + public static bool IsNegativeInfinity(NFloat value) => NativeType.IsNegativeInfinity(value._value); + + /// Determines whether the specified value is normal. + /// The floating-point value. + /// true if the value is normal; false otherwise. + [NonVersionable] + public static bool IsNormal(NFloat value) => NativeType.IsNormal(value._value); + + /// Determines whether the specified value is positive infinity. + /// The floating-point value. + /// true if the value is positive infinity; false otherwise. + [NonVersionable] + public static bool IsPositiveInfinity(NFloat value) => NativeType.IsPositiveInfinity(value._value); + + /// Determines whether the specified value is subnormal. + /// The floating-point value. + /// true if the value is subnormal; false otherwise. + [NonVersionable] + public static bool IsSubnormal(NFloat value) => NativeType.IsSubnormal(value._value); + + /// Converts the string representation of a number to its floating-point number equivalent. + /// A string that contains the number to convert. + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s) + { + var result = NativeType.Parse(s); + return new NFloat(result); + } + + /// Converts the string representation of a number in a specified style to its floating-point number equivalent. + /// A string that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// + /// is not a value. + /// -or- + /// includes the value. + /// + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s, NumberStyles style) + { + var result = NativeType.Parse(s, style); + return new NFloat(result); + } + + /// Converts the string representation of a number in a specified culture-specific format to its floating-point number equivalent. + /// A string that contains the number to convert. + /// An object that supplies culture-specific formatting information about . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s, IFormatProvider? provider) + { + var result = NativeType.Parse(s, provider); + return new NFloat(result); + } + + /// Converts the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A string that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// + /// is not a value. + /// -or- + /// includes the value. + /// + /// is null. + /// does not represent a number in a valid format. + public static NFloat Parse(string s, NumberStyles style, IFormatProvider? provider) + { + var result = NativeType.Parse(s, style, provider); + return new NFloat(result); + } + + /// Converts a character span that contains the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A character span that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// A floating-point number that is equivalent to the numeric value or symbol specified in . + /// + /// is not a value. + /// -or- + /// includes the value. + /// + /// does not represent a number in a valid format. + public static NFloat Parse(ReadOnlySpan s, NumberStyles style = DefaultNumberStyles, IFormatProvider? provider = null) + { + var result = NativeType.Parse(s, style, provider); + return new NFloat(result); + } + + /// Tries to convert the string representation of a number to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is null, , or is not in a valid format. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + public static bool TryParse([NotNullWhen(true)] string? s, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, out Unsafe.As(ref result)); + } + + /// Tries to convert a character span containing the string representation of a number to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is or is not in a valid format. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan s, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, out Unsafe.As(ref result)); + } + + /// Tries to convert the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is null, , or is not in a format compliant with , or if is not a valid combination of enumeration constants. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + /// + /// is not a value. + /// -or- + /// includes the value. + /// + public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, style, provider, out Unsafe.As(ref result)); + } + + /// Tries to convert a character span containing the string representation of a number in a specified style and culture-specific format to its floating-point number equivalent. + /// A read-only character span that contains the number to convert. + /// A bitwise combination of enumeration values that indicate the style elements that can be present in . + /// An object that supplies culture-specific formatting information about . + /// When this method returns, contains a floating-point number equivalent of the numeric value or symbol contained in if the conversion succeeded or zero if the conversion failed. The conversion fails if the is or is not in a format compliant with , or if is not a valid combination of enumeration constants. This parameter is passed uninitialized; any value originally supplied in result will be overwritten. + /// true if was converted successfully; otherwise, false. + /// + /// is not a value. + /// -or- + /// includes the value. + /// + public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out NFloat result) + { + Unsafe.SkipInit(out result); + return NativeType.TryParse(s, style, provider, out Unsafe.As(ref result)); + } + + /// Compares this instance to a specified object and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified object. + /// An object to compare, or null. + /// + /// A signed number indicating the relative values of this instance and . + /// + /// + /// Return Value + /// Description + /// + /// + /// Less than zero + /// This instance is less than , or this instance is not a number and is a number. + /// + /// + /// Zero + /// This instance is equal to , or both this instance and are not a number. + /// + /// + /// Greater than zero + /// This instance is greater than , or this instance is a number and is not a number or is null. + /// + /// + /// + /// is not a . + public int CompareTo(object? obj) + { + if (obj is NFloat other) + { + if (_value < other._value) return -1; + if (_value > other._value) return 1; + if (_value == other._value) return 0; + + // At least one of the values is NaN. + if (NativeType.IsNaN(_value)) + { + return NativeType.IsNaN(other._value) ? 0 : -1; + } + else + { + return 1; + } + } + else if (obj is null) + { + return 1; + } + + throw new ArgumentException(SR.Arg_MustBeNFloat); + } + + /// Compares this instance to a specified floating-point number and returns an integer that indicates whether the value of this instance is less than, equal to, or greater than the value of the specified floating-point number. + /// A floating-point number to compare. + /// + /// A signed number indicating the relative values of this instance and . + /// + /// + /// Return Value + /// Description + /// + /// + /// Less than zero + /// This instance is less than , or this instance is not a number and is a number. + /// + /// + /// Zero + /// This instance is equal to , or both this instance and are not a number. + /// + /// + /// Greater than zero + /// This instance is greater than , or this instance is a number and is not a number. + /// + /// + /// + public int CompareTo(NFloat other) => _value.CompareTo(other._value); + + /// Returns a value indicating whether this instance is equal to a specified object. + /// An object to compare with this instance. + /// true if is an instance of and equals the value of this instance; otherwise, false. + public override bool Equals([NotNullWhen(true)] object? obj) => (obj is NFloat other) && Equals(other); + + /// Returns a value indicating whether this instance is equal to a specified value. /// An value to compare to this instance. /// true if has the same value as this instance; otherwise, false. public bool Equals(NFloat other) => _value.Equals(other._value); - /// - /// Returns the hash code for this instance. - /// + /// Returns the hash code for this instance. /// A 32-bit signed integer hash code. public override int GetHashCode() => _value.GetHashCode(); - /// - /// Converts the numeric value of this instance to its equivalent string representation. - /// + /// Converts the numeric value of this instance to its equivalent string representation. /// The string representation of the value of this instance. public override string ToString() => _value.ToString(); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified format. + /// A numeric format string. + /// The string representation of the value of this instance as specified by . + /// is invalid. + public string ToString(string? format) => _value.ToString(format); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified culture-specific format information. + /// An object that supplies culture-specific formatting information. + /// The string representation of the value of this instance as specified by . + public string ToString(IFormatProvider? provider)=> _value.ToString(provider); + + /// Converts the numeric value of this instance to its equivalent string representation using the specified format and culture-specific format information. + /// A numeric format string. + /// An object that supplies culture-specific formatting information. + /// The string representation of the value of this instance as specified by and . + /// is invalid. + public string ToString(string? format, IFormatProvider? provider) => _value.ToString(format, provider); + + /// Tries to format the value of the current instance into the provided span of characters. + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// true if the formatting was successful; otherwise, false. + public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) => _value.TryFormat(destination, out charsWritten, format, provider); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs index 2edfd97a518ada..626ea6d189dee7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.PlatformNotSupported.cs @@ -7,7 +7,7 @@ namespace System.Runtime.Intrinsics.X86 { [CLSCompliant(false)] - [RequiresPreviewFeatures] + [RequiresPreviewFeatures("AvxVnni is in preview.")] public abstract class AvxVnni : Avx2 { internal AvxVnni() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs index d6bb750ebc89a6..fcefbeac02122f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/AvxVnni.cs @@ -8,7 +8,7 @@ namespace System.Runtime.Intrinsics.X86 { [Intrinsic] [CLSCompliant(false)] - [RequiresPreviewFeatures] + [RequiresPreviewFeatures("AvxVnni is in preview.")] public abstract class AvxVnni : Avx2 { internal AvxVnni() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index ce811d0cffd933..66167365219748 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -297,11 +297,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IAdditionOperators.operator +(sbyte left, sbyte right) => (sbyte)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IAdditionOperators.operator +(sbyte left, sbyte right) // => checked((sbyte)(left + right)); @@ -309,30 +309,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.LeadingZeroCount(sbyte value) => (sbyte)(BitOperations.LeadingZeroCount((byte)value) - 24); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.PopCount(sbyte value) => (sbyte)BitOperations.PopCount((byte)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.RotateLeft(sbyte value, int rotateAmount) => (sbyte)((value << (rotateAmount & 7)) | ((byte)value >> ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.RotateRight(sbyte value, int rotateAmount) => (sbyte)(((byte)value >> (rotateAmount & 7)) | (value << ((8 - rotateAmount) & 7))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryInteger.TrailingZeroCount(sbyte value) => (sbyte)(BitOperations.TrailingZeroCount(value << 24) - 24); @@ -340,11 +340,11 @@ static sbyte IBinaryInteger.TrailingZeroCount(sbyte value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(sbyte value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBinaryNumber.Log2(sbyte value) { if (value < 0) @@ -358,19 +358,19 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator &(sbyte left, sbyte right) => (sbyte)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator |(sbyte left, sbyte right) => (sbyte)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator ^(sbyte left, sbyte right) => (sbyte)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IBitwiseOperators.operator ~(sbyte value) => (sbyte)(~value); @@ -378,19 +378,19 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(sbyte left, sbyte right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(sbyte left, sbyte right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(sbyte left, sbyte right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(sbyte left, sbyte right) => left >= right; @@ -398,11 +398,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IDecrementOperators.operator --(sbyte value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IDecrementOperators.operator --(sbyte value) // => checked(--value); @@ -410,11 +410,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IDivisionOperators.operator /(sbyte left, sbyte right) => (sbyte)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IDivisionOperators.operator /(sbyte left, sbyte right) // => checked((sbyte)(left / right)); @@ -422,11 +422,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(sbyte left, sbyte right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(sbyte left, sbyte right) => left != right; @@ -434,11 +434,11 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IIncrementOperators.operator ++(sbyte value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IIncrementOperators.operator ++(sbyte value) // => checked(++value); @@ -446,21 +446,21 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IModulusOperators.operator %(sbyte left, sbyte right) => (sbyte)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IModulusOperators.operator %(sbyte left, sbyte right) // => checked((sbyte)(left % right)); @@ -468,18 +468,18 @@ static sbyte IBinaryNumber.Log2(sbyte value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IMultiplyOperators.operator *(sbyte left, sbyte right) => (sbyte)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IMultiplyOperators.operator *(sbyte left, sbyte right) // => checked((sbyte)(left * right)); @@ -487,21 +487,21 @@ static sbyte IBinaryNumber.Log2(sbyte value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Abs(sbyte value) => Math.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Clamp(sbyte value, sbyte min, sbyte max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static sbyte INumber.Create(TOther value) { @@ -568,7 +568,7 @@ static sbyte INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static sbyte INumber.CreateSaturating(TOther value) { @@ -655,7 +655,7 @@ static sbyte INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static sbyte INumber.CreateTruncating(TOther value) { @@ -722,31 +722,31 @@ static sbyte INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (sbyte Quotient, sbyte Remainder) INumber.DivRem(sbyte left, sbyte right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Max(sbyte x, sbyte y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Min(sbyte x, sbyte y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte INumber.Sign(sbyte value) => (sbyte)Math.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out sbyte result) { @@ -932,11 +932,11 @@ static bool INumber.TryCreate(TOther value, out sbyte result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out sbyte result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out sbyte result) => TryParse(s, style, provider, out result); @@ -944,11 +944,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out sbyte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -956,15 +956,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IShiftOperators.operator <<(sbyte value, int shiftAmount) => (sbyte)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IShiftOperators.operator >>(sbyte value, int shiftAmount) => (sbyte)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static sbyte IShiftOperators.operator >>>(sbyte value, int shiftAmount) // => (sbyte)((byte)value >> shiftAmount); @@ -972,18 +972,18 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out sbyte result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -991,11 +991,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte ISubtractionOperators.operator -(sbyte left, sbyte right) => (sbyte)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte ISubtractionOperators.operator -(sbyte left, sbyte right) // => checked((sbyte)(left - right)); @@ -1003,11 +1003,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IUnaryNegationOperators.operator -(sbyte value) => (sbyte)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IUnaryNegationOperators.operator -(sbyte value) // => checked((sbyte)(-value)); @@ -1015,11 +1015,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static sbyte IUnaryPlusOperators.operator +(sbyte value) => (sbyte)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked sbyte IUnaryPlusOperators.operator +(sbyte value) // => checked((sbyte)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 24150edb87230f..37abe72cd6bb2f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -447,11 +447,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IAdditionOperators.operator +(float left, float right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IAdditionOperators.operator +(float left, float right) // => checked(left + right); @@ -459,14 +459,14 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IAdditiveIdentity.AdditiveIdentity => 0.0f; // // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(float value) { uint bits = BitConverter.SingleToUInt32Bits(value); @@ -479,7 +479,7 @@ static bool IBinaryNumber.IsPow2(float value) && (significand == MinSignificand); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBinaryNumber.Log2(float value) => MathF.Log2(value); @@ -487,28 +487,28 @@ static float IBinaryNumber.Log2(float value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator &(float left, float right) { uint bits = BitConverter.SingleToUInt32Bits(left) & BitConverter.SingleToUInt32Bits(right); return BitConverter.UInt32BitsToSingle(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator |(float left, float right) { uint bits = BitConverter.SingleToUInt32Bits(left) | BitConverter.SingleToUInt32Bits(right); return BitConverter.UInt32BitsToSingle(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator ^(float left, float right) { uint bits = BitConverter.SingleToUInt32Bits(left) ^ BitConverter.SingleToUInt32Bits(right); return BitConverter.UInt32BitsToSingle(bits); } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IBitwiseOperators.operator ~(float value) { uint bits = ~BitConverter.SingleToUInt32Bits(value); @@ -519,19 +519,19 @@ static float IBinaryNumber.Log2(float value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(float left, float right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(float left, float right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(float left, float right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(float left, float right) => left >= right; @@ -539,11 +539,11 @@ static float IBinaryNumber.Log2(float value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IDecrementOperators.operator --(float value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IDecrementOperators.operator --(float value) // => checked(--value); @@ -551,11 +551,11 @@ static float IBinaryNumber.Log2(float value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IDivisionOperators.operator /(float left, float right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IDivisionOperators.operator /(float left, float right) // => checked(left / right); @@ -563,11 +563,11 @@ static float IBinaryNumber.Log2(float value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(float left, float right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(float left, float right) => left != right; @@ -575,178 +575,202 @@ static float IBinaryNumber.Log2(float value) // IFloatingPoint // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.E => MathF.E; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Epsilon => Epsilon; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.NaN => NaN; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.NegativeInfinity => NegativeInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.NegativeZero => -0.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Pi => MathF.PI; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.PositiveInfinity => PositiveInfinity; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Tau => MathF.Tau; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Acos(float x) => MathF.Acos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Acosh(float x) => MathF.Acosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Asin(float x) => MathF.Asin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Asinh(float x) => MathF.Asinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Atan(float x) => MathF.Atan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Atan2(float y, float x) => MathF.Atan2(y, x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Atanh(float x) => MathF.Atanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.BitIncrement(float x) => MathF.BitIncrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.BitDecrement(float x) => MathF.BitDecrement(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Cbrt(float x) => MathF.Cbrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Ceiling(float x) => MathF.Ceiling(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.CopySign(float x, float y) => MathF.CopySign(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Cos(float x) => MathF.Cos(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Cosh(float x) => MathF.Cosh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Exp(float x) => MathF.Exp(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Floor(float x) => MathF.Floor(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.FusedMultiplyAdd(float left, float right, float addend) => MathF.FusedMultiplyAdd(left, right, addend); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.IEEERemainder(float left, float right) => MathF.IEEERemainder(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TInteger IFloatingPoint.ILogB(float x) => TInteger.Create(MathF.ILogB(x)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log(float x) => MathF.Log(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log(float x, float newBase) => MathF.Log(x, newBase); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log2(float x) => MathF.Log2(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Log10(float x) => MathF.Log10(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.MaxMagnitude(float x, float y) => MathF.MaxMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.MinMagnitude(float x, float y) => MathF.MinMagnitude(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Pow(float x, float y) => MathF.Pow(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x) => MathF.Round(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x, TInteger digits) => MathF.Round(x, int.Create(digits)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x, MidpointRounding mode) => MathF.Round(x, mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Round(float x, TInteger digits, MidpointRounding mode) => MathF.Round(x, int.Create(digits), mode); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.ScaleB(float x, TInteger n) => MathF.ScaleB(x, int.Create(n)); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Sin(float x) => MathF.Sin(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Sinh(float x) => MathF.Sinh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Sqrt(float x) => MathF.Sqrt(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Tan(float x) => MathF.Tan(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Tanh(float x) => MathF.Tanh(x); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IFloatingPoint.Truncate(float x) => MathF.Truncate(x); + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsFinite(float x) => IsFinite(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsInfinity(float x) => IsInfinity(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNaN(float x) => IsNaN(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNegative(float x) => IsNegative(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNegativeInfinity(float x) => IsNegativeInfinity(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsNormal(float x) => IsNormal(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsPositiveInfinity(float x) => IsPositiveInfinity(x); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static bool IFloatingPoint.IsSubnormal(float x) => IsSubnormal(x); + // static float IFloatingPoint.AcosPi(float x) // => MathF.AcosPi(x); // @@ -817,11 +841,11 @@ static float IFloatingPoint.Truncate(float x) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IIncrementOperators.operator ++(float value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IIncrementOperators.operator ++(float value) // => checked(++value); @@ -829,21 +853,21 @@ static float IFloatingPoint.Truncate(float x) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IModulusOperators.operator %(float left, float right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IModulusOperators.operator %(float left, float right) // => checked(left % right); @@ -851,18 +875,18 @@ static float IFloatingPoint.Truncate(float x) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMultiplicativeIdentity.MultiplicativeIdentity => 1.0f; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IMultiplyOperators.operator *(float left, float right) => (float)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IMultiplyOperators.operator *(float left, float right) // => checked((float)(left * right)); @@ -870,21 +894,21 @@ static float IFloatingPoint.Truncate(float x) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.One => 1.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Zero => 0.0f; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Abs(float value) => MathF.Abs(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Clamp(float value, float min, float max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static float INumber.Create(TOther value) { @@ -951,7 +975,7 @@ static float INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static float INumber.CreateSaturating(TOther value) { @@ -1018,7 +1042,7 @@ static float INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static float INumber.CreateTruncating(TOther value) { @@ -1085,31 +1109,31 @@ static float INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (float Quotient, float Remainder) INumber.DivRem(float left, float right) => (left / right, left % right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Max(float x, float y) => MathF.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Min(float x, float y) => MathF.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float INumber.Sign(float value) => MathF.Sign(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out float result) { @@ -1191,11 +1215,11 @@ static bool INumber.TryCreate(TOther value, out float result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out float result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out float result) => TryParse(s, style, provider, out result); @@ -1203,42 +1227,42 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out float result) - => TryParse(s, NumberStyles.Integer, provider, out result); + => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); // // ISignedNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float ISignedNumber.NegativeOne => -1; // // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) - => Parse(s, NumberStyles.Integer, provider); + => Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out float result) - => TryParse(s, NumberStyles.Integer, provider, out result); + => TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, provider, out result); // // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float ISubtractionOperators.operator -(float left, float right) => (float)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float ISubtractionOperators.operator -(float left, float right) // => checked((float)(left - right)); @@ -1246,20 +1270,20 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IUnaryNegationOperators.operator -(float value) => (float)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IUnaryNegationOperators.operator -(float value) => checked((float)(-value)); // // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static float IUnaryPlusOperators.operator +(float value) => (float)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked float IUnaryPlusOperators.operator +(float value) => checked((float)(+value)); #endif // FEATURE_GENERIC_MATH } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index 54a7dc691cc0c8..3f60a1cd7ff7c7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -392,13 +392,24 @@ public bool TryReset() // to transition from canceled to non-canceled. if (_state == NotCanceledState) { - // If there is no timer, then we're free to reset. If there is a timer, then we need to first try - // to reset it to be infinite so that it won't fire, and then recognize that it could have already - // fired by the time we successfully changed it, and so check to see whether that's possibly the case. - // If we successfully reset it and it never fired, then we can be sure it won't trigger cancellation. - bool reset = - _timer is not TimerQueueTimer timer || - (timer.Change(Timeout.UnsignedInfinite, Timeout.UnsignedInfinite) && !timer._everQueued); + bool reset = false; + + try + { + // If there is no timer, then we're free to reset. If there is a timer, then we need to first try + // to reset it to be infinite so that it won't fire, and then recognize that it could have already + // fired by the time we successfully changed it, and so check to see whether that's possibly the case. + // If we successfully reset it and it never fired, then we can be sure it won't trigger cancellation. + reset = _timer is not TimerQueueTimer timer || + (timer.Change(Timeout.UnsignedInfinite, Timeout.UnsignedInfinite) && !timer._everQueued); + } + catch (ObjectDisposedException) + { + // Just eat the exception. There is no other way to tell that + // the timer has been disposed, and even if there were, there + // would not be a good way to deal with the observe/dispose + // race condition. + } if (reset) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs index bfa8ccd86802cd..246ed5b92f85a0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs @@ -745,7 +745,7 @@ private async Task WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int public ConfiguredNoThrowAwaiter(Task task) => _task = task; public ConfiguredNoThrowAwaiter GetAwaiter() => this; public bool IsCompleted => _task.IsCompleted; - public void GetResult() { } + public void GetResult() => _task.MarkExceptionsAsHandled(); public void UnsafeOnCompleted(Action continuation) => _task.ConfigureAwait(false).GetAwaiter().UnsafeOnCompleted(continuation); public void OnCompleted(Action continuation) => _task.ConfigureAwait(false).GetAwaiter().OnCompleted(continuation); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index 458c914773cbcd..8a21b34ddb01c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @@ -1863,6 +1863,12 @@ internal List GetExceptionDispatchInfos() return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null } + /// Marks any exceptions stored in the Task as having been handled. + internal void MarkExceptionsAsHandled() + { + Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.MarkAsHandled(calledFromFinalizer: false); + } + /// /// Throws an aggregate exception if the task contains exceptions. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs index 9b4fc5df0395ad..549147bacd9f3a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -389,6 +389,7 @@ public int Count } internal bool loggingEnabled; + private bool _dispatchTimeSensitiveWorkFirst; internal readonly ConcurrentQueue workItems = new ConcurrentQueue(); // SOS's ThreadPool command depends on this name internal readonly ConcurrentQueue? timeSensitiveWorkQueue = ThreadPool.SupportsTimeSensitiveWorkItems ? new ConcurrentQueue() : null; @@ -650,6 +651,21 @@ internal static bool Dispatch() int startTickCount = Environment.TickCount; object? workItem = null; +#pragma warning disable CS0162 // Unreachable code detected. SupportsTimeSensitiveWorkItems may be a constant in some runtimes. + if (ThreadPool.SupportsTimeSensitiveWorkItems) + { + // Alternate between checking for time-sensitive work or other work first, that way both sets of work items + // get a chance to run in situations where worker threads are starved and work items that run also take over + // the thread, sustaining starvation. For example, if time-sensitive work is always checked last here, timer + // callbacks may not run when worker threads are continually starved. + bool dispatchTimeSensitiveWorkFirst = workQueue._dispatchTimeSensitiveWorkFirst; + workQueue._dispatchTimeSensitiveWorkFirst = !dispatchTimeSensitiveWorkFirst; + if (dispatchTimeSensitiveWorkFirst) + { + workItem = workQueue.TryDequeueTimeSensitiveWorkItem(); + } + } +#pragma warning restore CS0162 // // Loop until our quantum expires or there is no work. diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs index d89c04fb675601..9fb102f3990ac8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeOnly.cs @@ -892,15 +892,13 @@ public string ToString(string? format, IFormatProvider? provider) return DateTimeFormat.TryFormat(ToDateTime(), destination, out charsWritten, format, provider); default: - charsWritten = 0; - return false; + throw new FormatException(SR.Argument_BadFormatSpecifier); } } if (!DateTimeFormat.IsValidCustomTimeFormat(format, throwOnError: false)) { - charsWritten = 0; - return false; + throw new FormatException(SR.Format(SR.Format_DateTimeOnlyContainsNoneDateParts, format.ToString(), nameof(TimeOnly))); } return DateTimeFormat.TryFormat(ToDateTime(), destination, out charsWritten, format, provider); @@ -911,19 +909,19 @@ public string ToString(string? format, IFormatProvider? provider) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(TimeOnly left, TimeOnly right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(TimeOnly left, TimeOnly right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(TimeOnly left, TimeOnly right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(TimeOnly left, TimeOnly right) => left >= right; @@ -931,11 +929,11 @@ public string ToString(string? format, IFormatProvider? provider) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(TimeOnly left, TimeOnly right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(TimeOnly left, TimeOnly right) => left != right; @@ -943,11 +941,11 @@ public string ToString(string? format, IFormatProvider? provider) // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeOnly IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out TimeOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -955,11 +953,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeOnly ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider, DateTimeStyles.None); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out TimeOnly result) => TryParse(s, provider, DateTimeStyles.None, out result); @@ -967,13 +965,20 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(TimeOnly left, TimeOnly right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(TimeOnly left, TimeOnly right) // => checked(left - right); + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static TimeOnly IMinMaxValue.MinValue => MinValue; + + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] + static TimeOnly IMinMaxValue.MaxValue => MaxValue; + #endif // FEATURE_GENERIC_MATH } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs index 6bc5341c8cc945..af9d162861febf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs @@ -510,11 +510,11 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditionOperators.operator +(TimeSpan left, TimeSpan right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IAdditionOperators.operator +(TimeSpan left, TimeSpan right) // => checked(left + right); @@ -522,26 +522,26 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IAdditiveIdentity.AdditiveIdentity => default; // // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(TimeSpan left, TimeSpan right) => left.operator <=(TimeSpan left, TimeSpan right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(TimeSpan left, TimeSpan right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(TimeSpan left, TimeSpan right) => left >= right; @@ -549,19 +549,19 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IDivisionOperators.operator /(TimeSpan left, double right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IDivisionOperators.operator /(TimeSpan left, double right) // => checked(left / right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IDivisionOperators.operator /(TimeSpan left, TimeSpan right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked double IDivisionOperators.operator /(TimeSpan left, TimeSpan right) // => checked(left / right); @@ -569,11 +569,11 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(TimeSpan left, TimeSpan right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(TimeSpan left, TimeSpan right) => left != right; @@ -581,28 +581,28 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IMinMaxValue.MaxValue => MaxValue; // // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static double IMultiplicativeIdentity.MultiplicativeIdentity => 1.0; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IMultiplyOperators.operator *(TimeSpan left, double right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IMultiplyOperators.operator *(TimeSpan left, double right) // => checked(left * right); @@ -610,11 +610,11 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out TimeSpan result) => TryParse(s, provider, out result); @@ -622,11 +622,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormat // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out TimeSpan result) => TryParse(s, provider, out result); @@ -634,11 +634,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan ISubtractionOperators.operator -(TimeSpan left, TimeSpan right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan ISubtractionOperators.operator -(TimeSpan left, TimeSpan right) // => checked(left - right); @@ -646,11 +646,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IUnaryNegationOperators.operator -(TimeSpan value) => -value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IUnaryNegationOperators.operator -(TimeSpan value) // => checked(-value); @@ -658,11 +658,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvi // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static TimeSpan IUnaryPlusOperators.operator +(TimeSpan value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked TimeSpan IUnaryPlusOperators.operator +(TimeSpan value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs index 5a80d7b448649d..e0c284b6c53522 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.FullGlobalizationData.Unix.cs @@ -24,6 +24,11 @@ public sealed partial class TimeZoneInfo // Main function that is called during construction to populate the three display names private static void TryPopulateTimeZoneDisplayNamesFromGlobalizationData(string timeZoneId, TimeSpan baseUtcOffset, ref string? standardDisplayName, ref string? daylightDisplayName, ref string? displayName) { + if (GlobalizationMode.Invariant) + { + return; + } + // Determine the culture to use CultureInfo uiCulture = CultureInfo.CurrentUICulture; if (uiCulture.Name.Length == 0) diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs index 53baf4eb65111f..23c1044e1983cd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.Android.cs @@ -193,6 +193,7 @@ private sealed class AndroidTzData private string[] _ids; private int[] _byteOffsets; private int[] _lengths; + private bool[] _isBackwards; private string _tzFileDir; private string _tzFilePath; @@ -230,7 +231,7 @@ public AndroidTzData() foreach (var tzFileDir in tzFileDirList) { string tzFilePath = Path.Combine(tzFileDir, TimeZoneFileName); - if (LoadData(tzFilePath)) + if (LoadData(tzFileDir, tzFilePath)) { _tzFileDir = tzFileDir; _tzFilePath = tzFilePath; @@ -241,10 +242,62 @@ public AndroidTzData() throw new TimeZoneNotFoundException(SR.TimeZoneNotFound_ValidTimeZoneFileMissing); } + // On some versions of Android, the tzdata file may still contain backward timezone ids. + // We attempt to use tzlookup.xml, which is available on some versions of Android to help + // validate non-backward timezone ids + // tzlookup.xml is an autogenerated file that contains timezone ids in this form: + // + // + // + // + // Australia/Sydney + // ... + // ... + // Australia/Eucla + // + // + // ... + // ... + // ... + // + // + // + // + // Once the timezone cache is populated with the IDs, we reference tzlookup id tags + // to determine if an id is backwards and label it as such if they are. + private void FilterBackwardIDs(string tzFileDir, out HashSet tzLookupIDs) + { + tzLookupIDs = new HashSet(); + try + { + using (StreamReader sr = File.OpenText(Path.Combine(tzFileDir, "tzlookup.xml"))) + { + string? tzLookupLine; + while (sr.Peek() >= 0) + { + if (!(tzLookupLine = sr.ReadLine())!.AsSpan().TrimStart().StartsWith("') + 1; + int idLength = tzLookupLine.LastIndexOf(" or the end tag are not found + continue; + } + string id = tzLookupLine.Substring(idStart, idLength); + tzLookupIDs.Add(id); + } + } + } + catch {} + } + [MemberNotNullWhen(true, nameof(_ids))] [MemberNotNullWhen(true, nameof(_byteOffsets))] [MemberNotNullWhen(true, nameof(_lengths))] - private bool LoadData(string path) + [MemberNotNullWhen(true, nameof(_isBackwards))] + private bool LoadData(string tzFileDir, string path) { if (!File.Exists(path)) { @@ -254,7 +307,7 @@ private bool LoadData(string path) { using (FileStream fs = File.OpenRead(path)) { - LoadTzFile(fs); + LoadTzFile(tzFileDir, fs); } return true; } @@ -266,7 +319,8 @@ private bool LoadData(string path) [MemberNotNull(nameof(_ids))] [MemberNotNull(nameof(_byteOffsets))] [MemberNotNull(nameof(_lengths))] - private void LoadTzFile(Stream fs) + [MemberNotNull(nameof(_isBackwards))] + private void LoadTzFile(string tzFileDir, Stream fs) { const int HeaderSize = 24; Span buffer = stackalloc byte[HeaderSize]; @@ -274,7 +328,7 @@ private void LoadTzFile(Stream fs) ReadTzDataIntoBuffer(fs, 0, buffer); LoadHeader(buffer, out int indexOffset, out int dataOffset); - ReadIndex(fs, indexOffset, dataOffset); + ReadIndex(tzFileDir, fs, indexOffset, dataOffset); } private void LoadHeader(Span buffer, out int indexOffset, out int dataOffset) @@ -303,16 +357,17 @@ private void LoadHeader(Span buffer, out int indexOffset, out int dataOffs [MemberNotNull(nameof(_ids))] [MemberNotNull(nameof(_byteOffsets))] [MemberNotNull(nameof(_lengths))] - private void ReadIndex(Stream fs, int indexOffset, int dataOffset) + [MemberNotNull(nameof(_isBackwards))] + private void ReadIndex(string tzFileDir, Stream fs, int indexOffset, int dataOffset) { int indexSize = dataOffset - indexOffset; const int entrySize = 52; // Data entry size int entryCount = indexSize / entrySize; - _byteOffsets = new int[entryCount]; _ids = new string[entryCount]; _lengths = new int[entryCount]; - + _isBackwards = new bool[entryCount]; + FilterBackwardIDs(tzFileDir, out HashSet tzLookupIDs); for (int i = 0; i < entryCount; ++i) { LoadEntryAt(fs, indexOffset + (entrySize*i), out string id, out int byteOffset, out int length); @@ -320,6 +375,7 @@ private void ReadIndex(Stream fs, int indexOffset, int dataOffset) _byteOffsets[i] = byteOffset + dataOffset; _ids[i] = id; _lengths[i] = length; + _isBackwards[i] = !tzLookupIDs.Contains(id); if (length < 24) // Header Size { @@ -372,7 +428,25 @@ private void LoadEntryAt(Stream fs, long position, out string id, out int byteOf public string[] GetTimeZoneIds() { - return _ids; + int numTimeZoneIDs = 0; + for (int i = 0; i < _ids.Length; i++) + { + if (!_isBackwards[i]) + { + numTimeZoneIDs++; + } + } + string[] nonBackwardsTZIDs = new string[numTimeZoneIDs]; + var index = 0; + for (int i = 0; i < _ids.Length; i++) + { + if (!_isBackwards[i]) + { + nonBackwardsTZIDs[index] = _ids[i]; + index++; + } + } + return nonBackwardsTZIDs; } public string GetTimeZoneDirectory() diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs index ee0baa1e7ec805..c1e1b2e1025576 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs @@ -85,7 +85,8 @@ private TimeZoneInfo CreateLocal() timeZone._standardDisplayName, timeZone._daylightDisplayName, timeZone._adjustmentRules, - disableDaylightSavingTime: false); + disableDaylightSavingTime: false, + timeZone.HasIanaId); _localTimeZone = timeZone; } @@ -1954,7 +1955,7 @@ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool else { value = new TimeZoneInfo(match!._id, match._baseUtcOffset, match._displayName, match._standardDisplayName, - match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false); + match._daylightDisplayName, match._adjustmentRules, disableDaylightSavingTime: false, match.HasIanaId); } } else diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs index 49c08cc99fab3c..839e31b64b366c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt16.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt16.cs @@ -279,11 +279,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IAdditionOperators.operator +(ushort left, ushort right) => (ushort)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IAdditionOperators.operator +(ushort left, ushort right) // => checked((ushort)(left + right)); @@ -291,30 +291,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.LeadingZeroCount(ushort value) => (ushort)(BitOperations.LeadingZeroCount(value) - 16); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.PopCount(ushort value) => (ushort)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.RotateLeft(ushort value, int rotateAmount) => (ushort)((value << (rotateAmount & 15)) | (value >> ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.RotateRight(ushort value, int rotateAmount) => (ushort)((value >> (rotateAmount & 15)) | (value << ((16 - rotateAmount) & 15))); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryInteger.TrailingZeroCount(ushort value) => (ushort)(BitOperations.TrailingZeroCount(value << 16) - 16); @@ -322,11 +322,11 @@ static ushort IBinaryInteger.TrailingZeroCount(ushort value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(ushort value) => BitOperations.IsPow2((uint)value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBinaryNumber.Log2(ushort value) => (ushort)BitOperations.Log2(value); @@ -334,19 +334,19 @@ static ushort IBinaryNumber.Log2(ushort value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator &(ushort left, ushort right) => (ushort)(left & right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator |(ushort left, ushort right) => (ushort)(left | right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator ^(ushort left, ushort right) => (ushort)(left ^ right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IBitwiseOperators.operator ~(ushort value) => (ushort)(~value); @@ -354,19 +354,19 @@ static ushort IBinaryNumber.Log2(ushort value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(ushort left, ushort right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(ushort left, ushort right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(ushort left, ushort right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(ushort left, ushort right) => left >= right; @@ -374,11 +374,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IDecrementOperators.operator --(ushort value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IDecrementOperators.operator --(ushort value) // => checked(--value); @@ -386,11 +386,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IDivisionOperators.operator /(ushort left, ushort right) => (ushort)(left / right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IDivisionOperators.operator /(ushort left, ushort right) // => checked((ushort)(left / right)); @@ -398,11 +398,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(ushort left, ushort right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(ushort left, ushort right) => left != right; @@ -410,11 +410,11 @@ static ushort IBinaryNumber.Log2(ushort value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IIncrementOperators.operator ++(ushort value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IIncrementOperators.operator ++(ushort value) // => checked(++value); @@ -422,21 +422,21 @@ static ushort IBinaryNumber.Log2(ushort value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IModulusOperators.operator %(ushort left, ushort right) => (ushort)(left % right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IModulusOperators.operator %(ushort left, ushort right) // => checked((ushort)(left % right)); @@ -444,18 +444,18 @@ static ushort IBinaryNumber.Log2(ushort value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IMultiplyOperators.operator *(ushort left, ushort right) => (ushort)(left * right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IMultiplyOperators.operator *(ushort left, ushort right) // => checked((ushort)(left * right)); @@ -463,21 +463,21 @@ static ushort IBinaryNumber.Log2(ushort value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Abs(ushort value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Clamp(ushort value, ushort min, ushort max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ushort INumber.Create(TOther value) { @@ -544,7 +544,7 @@ static ushort INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ushort INumber.CreateSaturating(TOther value) { @@ -628,7 +628,7 @@ static ushort INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ushort INumber.CreateTruncating(TOther value) { @@ -695,31 +695,31 @@ static ushort INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (ushort Quotient, ushort Remainder) INumber.DivRem(ushort left, ushort right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Max(ushort x, ushort y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Min(ushort x, ushort y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort INumber.Sign(ushort value) => (ushort)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out ushort result) { @@ -889,11 +889,11 @@ static bool INumber.TryCreate(TOther value, out ushort result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ushort result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out ushort result) => TryParse(s, style, provider, out result); @@ -901,11 +901,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, I // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out ushort result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -913,15 +913,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPr // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IShiftOperators.operator <<(ushort value, int shiftAmount) => (ushort)(value << shiftAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IShiftOperators.operator >>(ushort value, int shiftAmount) => (ushort)(value >> shiftAmount); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static ushort IShiftOperators.operator >>>(ushort value, int shiftAmount) // => (ushort)(value >> shiftAmount); @@ -929,11 +929,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPr // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out ushort result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -941,11 +941,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort ISubtractionOperators.operator -(ushort left, ushort right) => (ushort)(left - right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort ISubtractionOperators.operator -(ushort left, ushort right) // => checked((ushort)(left - right)); @@ -953,11 +953,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IUnaryNegationOperators.operator -(ushort value) => (ushort)(-value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IUnaryNegationOperators.operator -(ushort value) // => checked((ushort)(-value)); @@ -965,11 +965,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvide // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ushort IUnaryPlusOperators.operator +(ushort value) => (ushort)(+value); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ushort IUnaryPlusOperators.operator +(ushort value) // => checked((ushort)(+value)); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs index 70f073b1e15bf5..29fc05a976d71d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt32.cs @@ -265,11 +265,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IAdditionOperators.operator +(uint left, uint right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IAdditionOperators.operator +(uint left, uint right) // => checked(left + right); @@ -277,30 +277,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.LeadingZeroCount(uint value) => (uint)BitOperations.LeadingZeroCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.PopCount(uint value) => (uint)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.RotateLeft(uint value, int rotateAmount) => BitOperations.RotateLeft(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.RotateRight(uint value, int rotateAmount) => BitOperations.RotateRight(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryInteger.TrailingZeroCount(uint value) => (uint)BitOperations.TrailingZeroCount(value); @@ -308,11 +308,11 @@ static uint IBinaryInteger.TrailingZeroCount(uint value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(uint value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBinaryNumber.Log2(uint value) => (uint)BitOperations.Log2(value); @@ -320,19 +320,19 @@ static uint IBinaryNumber.Log2(uint value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator &(uint left, uint right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator |(uint left, uint right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator ^(uint left, uint right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IBitwiseOperators.operator ~(uint value) => ~value; @@ -340,19 +340,19 @@ static uint IBinaryNumber.Log2(uint value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(uint left, uint right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(uint left, uint right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(uint left, uint right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(uint left, uint right) => left >= right; @@ -360,11 +360,11 @@ static uint IBinaryNumber.Log2(uint value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IDecrementOperators.operator --(uint value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IDecrementOperators.operator --(uint value) // => checked(--value); @@ -372,11 +372,11 @@ static uint IBinaryNumber.Log2(uint value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IDivisionOperators.operator /(uint left, uint right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IDivisionOperators.operator /(uint left, uint right) // => checked(left / right); @@ -384,11 +384,11 @@ static uint IBinaryNumber.Log2(uint value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(uint left, uint right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(uint left, uint right) => left != right; @@ -396,11 +396,11 @@ static uint IBinaryNumber.Log2(uint value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IIncrementOperators.operator ++(uint value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IIncrementOperators.operator ++(uint value) // => checked(++value); @@ -408,21 +408,21 @@ static uint IBinaryNumber.Log2(uint value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IModulusOperators.operator %(uint left, uint right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IModulusOperators.operator %(uint left, uint right) // => checked(left % right); @@ -430,18 +430,18 @@ static uint IBinaryNumber.Log2(uint value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IMultiplyOperators.operator *(uint left, uint right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IMultiplyOperators.operator *(uint left, uint right) // => checked(left * right); @@ -449,21 +449,21 @@ static uint IBinaryNumber.Log2(uint value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Abs(uint value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Clamp(uint value, uint min, uint max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint INumber.Create(TOther value) { @@ -530,7 +530,7 @@ static uint INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint INumber.CreateSaturating(TOther value) { @@ -612,7 +612,7 @@ static uint INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static uint INumber.CreateTruncating(TOther value) { @@ -679,31 +679,31 @@ static uint INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (uint Quotient, uint Remainder) INumber.DivRem(uint left, uint right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Max(uint x, uint y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Min(uint x, uint y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint INumber.Sign(uint value) => (uint)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out uint result) { @@ -865,11 +865,11 @@ static bool INumber.TryCreate(TOther value, out uint result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out uint result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out uint result) => TryParse(s, style, provider, out result); @@ -877,11 +877,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFo // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out uint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -889,15 +889,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IShiftOperators.operator <<(uint value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IShiftOperators.operator >>(uint value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static uint IShiftOperators.operator >>>(uint value, int shiftAmount) // => value >> (int)shiftAmount; @@ -905,11 +905,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProv // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out uint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -917,11 +917,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint ISubtractionOperators.operator -(uint left, uint right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint ISubtractionOperators.operator -(uint left, uint right) // => checked(left - right); @@ -929,11 +929,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IUnaryNegationOperators.operator -(uint value) => 0u - value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IUnaryNegationOperators.operator -(uint value) // => checked(0u - value); @@ -941,11 +941,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static uint IUnaryPlusOperators.operator +(uint value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked uint IUnaryPlusOperators.operator +(uint value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs index 6b2a45f1a8ebec..7c5628bfebaeb8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UInt64.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UInt64.cs @@ -264,11 +264,11 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IAdditionOperators.operator +(ulong left, ulong right) => left + right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IAdditionOperators.operator +(ulong left, ulong right) // => checked(left + right); @@ -276,30 +276,30 @@ object IConvertible.ToType(Type type, IFormatProvider? provider) // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.LeadingZeroCount(ulong value) => (ulong)BitOperations.LeadingZeroCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.PopCount(ulong value) => (ulong)BitOperations.PopCount(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.RotateLeft(ulong value, int rotateAmount) => BitOperations.RotateLeft(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.RotateRight(ulong value, int rotateAmount) => BitOperations.RotateRight(value, rotateAmount); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryInteger.TrailingZeroCount(ulong value) => (ulong)BitOperations.TrailingZeroCount(value); @@ -307,11 +307,11 @@ static ulong IBinaryInteger.TrailingZeroCount(ulong value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(ulong value) => BitOperations.IsPow2(value); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBinaryNumber.Log2(ulong value) => (ulong)BitOperations.Log2(value); @@ -319,19 +319,19 @@ static ulong IBinaryNumber.Log2(ulong value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator &(ulong left, ulong right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator |(ulong left, ulong right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator ^(ulong left, ulong right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IBitwiseOperators.operator ~(ulong value) => ~value; @@ -339,19 +339,19 @@ static ulong IBinaryNumber.Log2(ulong value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(ulong left, ulong right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(ulong left, ulong right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(ulong left, ulong right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(ulong left, ulong right) => left >= right; @@ -359,11 +359,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IDecrementOperators.operator --(ulong value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IDecrementOperators.operator --(ulong value) // => checked(--value); @@ -371,11 +371,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IDivisionOperators.operator /(ulong left, ulong right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IDivisionOperators.operator /(ulong left, ulong right) // => checked(left / right); @@ -383,11 +383,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(ulong left, ulong right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(ulong left, ulong right) => left != right; @@ -395,11 +395,11 @@ static ulong IBinaryNumber.Log2(ulong value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IIncrementOperators.operator ++(ulong value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IIncrementOperators.operator ++(ulong value) // => checked(++value); @@ -407,21 +407,21 @@ static ulong IBinaryNumber.Log2(ulong value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IModulusOperators.operator %(ulong left, ulong right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IModulusOperators.operator %(ulong left, ulong right) // => checked(left % right); @@ -429,18 +429,18 @@ static ulong IBinaryNumber.Log2(ulong value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IMultiplyOperators.operator *(ulong left, ulong right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IMultiplyOperators.operator *(ulong left, ulong right) // => checked(left * right); @@ -448,21 +448,21 @@ static ulong IBinaryNumber.Log2(ulong value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Abs(ulong value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Clamp(ulong value, ulong min, ulong max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ulong INumber.Create(TOther value) { @@ -529,7 +529,7 @@ static ulong INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ulong INumber.CreateSaturating(TOther value) { @@ -607,7 +607,7 @@ static ulong INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static ulong INumber.CreateTruncating(TOther value) { @@ -674,31 +674,31 @@ static ulong INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (ulong Quotient, ulong Remainder) INumber.DivRem(ulong left, ulong right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Max(ulong x, ulong y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Min(ulong x, ulong y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong INumber.Sign(ulong value) => (ulong)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out ulong result) { @@ -844,11 +844,11 @@ static bool INumber.TryCreate(TOther value, out ulong result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out ulong result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out ulong result) => TryParse(s, style, provider, out result); @@ -856,11 +856,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out ulong result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -868,15 +868,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IShiftOperators.operator <<(ulong value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IShiftOperators.operator >>(ulong value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static ulong IShiftOperators.operator >>>(ulong value, int shiftAmount) // => value >> (int)shiftAmount; @@ -884,11 +884,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out ulong result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -896,11 +896,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong ISubtractionOperators.operator -(ulong left, ulong right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong ISubtractionOperators.operator -(ulong left, ulong right) // => checked(left - right); @@ -908,11 +908,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IUnaryNegationOperators.operator -(ulong value) => 0UL - value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IUnaryNegationOperators.operator -(ulong value) // => checked(0UL - value); @@ -920,11 +920,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static ulong IUnaryPlusOperators.operator +(ulong value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked ulong IUnaryPlusOperators.operator +(ulong value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index b413125474f556..39e8609e8da070 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -246,11 +246,11 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IAdditionOperators.operator +(nuint left, nuint right) => (nuint)(left + right); - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IAdditionOperators.operator +(nuint left, nuint right) // => checked((nuint)(left + right)); @@ -258,14 +258,14 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro // IAdditiveIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IAdditiveIdentity.AdditiveIdentity => 0; // // IBinaryInteger // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.LeadingZeroCount(nuint value) { if (Environment.Is64BitProcess) @@ -278,7 +278,7 @@ static nuint IBinaryInteger.LeadingZeroCount(nuint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.PopCount(nuint value) { if (Environment.Is64BitProcess) @@ -291,7 +291,7 @@ static nuint IBinaryInteger.PopCount(nuint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.RotateLeft(nuint value, int rotateAmount) { if (Environment.Is64BitProcess) @@ -304,7 +304,7 @@ static nuint IBinaryInteger.RotateLeft(nuint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.RotateRight(nuint value, int rotateAmount) { if (Environment.Is64BitProcess) @@ -317,7 +317,7 @@ static nuint IBinaryInteger.RotateRight(nuint value, int rotateAmount) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryInteger.TrailingZeroCount(nuint value) { if (Environment.Is64BitProcess) @@ -334,7 +334,7 @@ static nuint IBinaryInteger.TrailingZeroCount(nuint value) // IBinaryNumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IBinaryNumber.IsPow2(nuint value) { if (Environment.Is64BitProcess) @@ -347,7 +347,7 @@ static bool IBinaryNumber.IsPow2(nuint value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBinaryNumber.Log2(nuint value) { if (Environment.Is64BitProcess) @@ -364,19 +364,19 @@ static nuint IBinaryNumber.Log2(nuint value) // IBitwiseOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator &(nuint left, nuint right) => left & right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator |(nuint left, nuint right) => left | right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator ^(nuint left, nuint right) => left ^ right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IBitwiseOperators.operator ~(nuint value) => ~value; @@ -384,19 +384,19 @@ static nuint IBinaryNumber.Log2(nuint value) // IComparisonOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <(nuint left, nuint right) => left < right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator <=(nuint left, nuint right) => left <= right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >(nuint left, nuint right) => left > right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IComparisonOperators.operator >=(nuint left, nuint right) => left >= right; @@ -404,11 +404,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IDecrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IDecrementOperators.operator --(nuint value) => --value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IDecrementOperators.operator --(nuint value) // => checked(--value); @@ -416,11 +416,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IDivisionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IDivisionOperators.operator /(nuint left, nuint right) => left / right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IDivisionOperators.operator /(nuint left, nuint right) // => checked(left / right); @@ -428,11 +428,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IEqualityOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator ==(nuint left, nuint right) => left == right; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IEqualityOperators.operator !=(nuint left, nuint right) => left != right; @@ -440,11 +440,11 @@ static nuint IBinaryNumber.Log2(nuint value) // IIncrementOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IIncrementOperators.operator ++(nuint value) => ++value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IIncrementOperators.operator ++(nuint value) // => checked(++value); @@ -452,21 +452,21 @@ static nuint IBinaryNumber.Log2(nuint value) // IMinMaxValue // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMinMaxValue.MinValue => MinValue; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMinMaxValue.MaxValue => MaxValue; // // IModulusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IModulusOperators.operator %(nuint left, nuint right) => left % right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IModulusOperators.operator %(nuint left, nuint right) // => checked(left % right); @@ -474,18 +474,18 @@ static nuint IBinaryNumber.Log2(nuint value) // IMultiplicativeIdentity // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMultiplicativeIdentity.MultiplicativeIdentity => 1; // // IMultiplyOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IMultiplyOperators.operator *(nuint left, nuint right) => left * right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IMultiplyOperators.operator *(nuint left, nuint right) // => checked(left * right); @@ -493,21 +493,21 @@ static nuint IBinaryNumber.Log2(nuint value) // INumber // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.One => 1; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Zero => 0; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Abs(nuint value) => value; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Clamp(nuint value, nuint min, nuint max) => Math.Clamp(value, min, max); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nuint INumber.Create(TOther value) { @@ -574,7 +574,7 @@ static nuint INumber.Create(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nuint INumber.CreateSaturating(TOther value) { @@ -655,7 +655,7 @@ static nuint INumber.CreateSaturating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static nuint INumber.CreateTruncating(TOther value) { @@ -722,31 +722,31 @@ static nuint INumber.CreateTruncating(TOther value) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static (nuint Quotient, nuint Remainder) INumber.DivRem(nuint left, nuint right) => Math.DivRem(left, right); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Max(nuint x, nuint y) => Math.Max(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Min(nuint x, nuint y) => Math.Min(x, y); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Parse(string s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider) => Parse(s, style, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint INumber.Sign(nuint value) => (nuint)((value == 0) ? 0 : 1); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumber.TryCreate(TOther value, out nuint result) { @@ -900,11 +900,11 @@ static bool INumber.TryCreate(TOther value, out nuint result) } } - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out nuint result) => TryParse(s, style, provider, out result); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out nuint result) => TryParse(s, style, provider, out result); @@ -912,11 +912,11 @@ static bool INumber.TryParse(ReadOnlySpan s, NumberStyles style, IF // IParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IParseable.Parse(string s, IFormatProvider? provider) => Parse(s, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out nuint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -924,15 +924,15 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // IShiftOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IShiftOperators.operator <<(nuint value, int shiftAmount) => value << (int)shiftAmount; - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IShiftOperators.operator >>(nuint value, int shiftAmount) => value >> (int)shiftAmount; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static nuint IShiftOperators.operator >>>(nuint value, int shiftAmount) // => value >> (int)shiftAmount; @@ -940,11 +940,11 @@ static bool IParseable.TryParse([NotNullWhen(true)] string? s, IFormatPro // ISpanParseable // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint ISpanParseable.Parse(ReadOnlySpan s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider); - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider? provider, out nuint result) => TryParse(s, NumberStyles.Integer, provider, out result); @@ -952,11 +952,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // ISubtractionOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint ISubtractionOperators.operator -(nuint left, nuint right) => left - right; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint ISubtractionOperators.operator -(nuint left, nuint right) // => checked(left - right); @@ -964,11 +964,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryNegationOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IUnaryNegationOperators.operator -(nuint value) => (nuint)0 - value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IUnaryNegationOperators.operator -(nuint value) // => checked((nuint)0 - value); @@ -976,11 +976,11 @@ static bool ISpanParseable.TryParse(ReadOnlySpan s, IFormatProvider // IUnaryPlusOperators // - [RequiresPreviewFeatures] + [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] static nuint IUnaryPlusOperators.operator +(nuint value) => +value; - // [RequiresPreviewFeatures] + // [RequiresPreviewFeatures(Number.PreviewFeatureMessage, Url = Number.PreviewFeatureUrl)] // static checked nuint IUnaryPlusOperators.operator +(nuint value) // => checked(+value); #endif // FEATURE_GENERIC_MATH diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs index 74f4d0c0e0930c..30d2deda9e19d8 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/DataContractJsonSerializer.cs @@ -20,30 +20,25 @@ namespace System.Runtime.Serialization.Json public sealed class DataContractJsonSerializer : XmlObjectSerializer { - private const char BACK_SLASH = '\\'; - private const char FORWARD_SLASH = '/'; - private const char HIGH_SURROGATE_START = (char)0xd800; - private const char LOW_SURROGATE_END = (char)0xdfff; - private const char MAX_CHAR = (char)0xfffe; - private const char WHITESPACE = ' '; - - internal IList? knownTypeList; internal DataContractDictionary? knownDataContracts; - private readonly EmitTypeInformation _emitTypeInformation; + private EmitTypeInformation _emitTypeInformation; private ReadOnlyCollection? _knownTypeCollection; - private readonly int _maxItemsInObjectGraph; - private readonly bool _serializeReadOnlyTypes; - private readonly DateTimeFormat? _dateTimeFormat; - private readonly bool _useSimpleDictionaryFormat; + private int _maxItemsInObjectGraph; + private bool _serializeReadOnlyTypes; + private DateTimeFormat? _dateTimeFormat; + private bool _useSimpleDictionaryFormat; + private bool _ignoreExtensionDataObject; + private DataContract? _rootContract; // post-surrogate + private XmlDictionaryString? _rootName; + private bool _rootNameRequiresMapping; + private Type _rootType; - private readonly DataContractJsonSerializerImpl _serializer; - private readonly bool _ignoreExtensionDataObject; [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public DataContractJsonSerializer(Type type) + : this(type, (IEnumerable?)null) { - _serializer = new DataContractJsonSerializerImpl(type); } [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -60,8 +55,8 @@ public DataContractJsonSerializer(Type type, XmlDictionaryString? rootName) [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public DataContractJsonSerializer(Type type, IEnumerable? knownTypes) + : this(type, null, knownTypes, int.MaxValue, false, false) { - _serializer = new DataContractJsonSerializerImpl(type, knownTypes); } [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -72,478 +67,25 @@ public DataContractJsonSerializer(Type type, string? rootName, IEnumerable [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public DataContractJsonSerializer(Type type, XmlDictionaryString? rootName, IEnumerable? knownTypes) + : this(type, rootName, knownTypes, int.MaxValue, false, false) { - _serializer = new DataContractJsonSerializerImpl(type, rootName, knownTypes); } [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] public DataContractJsonSerializer(Type type, DataContractJsonSerializerSettings? settings) { - _serializer = new DataContractJsonSerializerImpl(type, settings); - } - - public bool IgnoreExtensionDataObject - { - get { return _ignoreExtensionDataObject; } - } - - public ReadOnlyCollection KnownTypes - { - get - { - if (_knownTypeCollection == null) - { - if (knownTypeList != null) - { - _knownTypeCollection = new ReadOnlyCollection(knownTypeList); - } - else - { - _knownTypeCollection = new ReadOnlyCollection(Type.EmptyTypes); - } - } - return _knownTypeCollection; - } - } - - internal override DataContractDictionary? KnownDataContracts - { - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - get - { - if (this.knownDataContracts == null && this.knownTypeList != null) - { - // This assignment may be performed concurrently and thus is a race condition. - // It's safe, however, because at worse a new (and identical) dictionary of - // data contracts will be created and re-assigned to this field. Introduction - // of a lock here could lead to deadlocks. - this.knownDataContracts = XmlObjectSerializerContext.GetDataContractsForKnownTypes(this.knownTypeList); - } - return this.knownDataContracts; - } - } - - public int MaxItemsInObjectGraph - { - get { return _maxItemsInObjectGraph; } - } - - public DateTimeFormat? DateTimeFormat - { - get - { - return _dateTimeFormat; - } - } - - public EmitTypeInformation EmitTypeInformation - { - get - { - return _emitTypeInformation; - } - } - - public bool SerializeReadOnlyTypes - { - get - { - return _serializeReadOnlyTypes; - } - } - - - public bool UseSimpleDictionaryFormat - { - get - { - return _useSimpleDictionaryFormat; - } - } - - internal static void CheckIfTypeIsReference(DataContract dataContract) - { - if (dataContract.IsReference) - { - throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( - XmlObjectSerializer.CreateSerializationException(SR.Format( - SR.JsonUnsupportedForIsReference, - DataContract.GetClrTypeFullName(dataContract.UnderlyingType), - dataContract.IsReference))); - } - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - internal static DataContract GetDataContract(DataContract declaredTypeContract, Type declaredType, Type objectType) - { - DataContract contract = DataContractSerializer.GetDataContract(declaredTypeContract, declaredType, objectType); - CheckIfTypeIsReference(contract); - return contract; - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteObject(Stream stream, object? graph) - { - _serializer.WriteObject(stream, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteObject(XmlWriter writer, object? graph) - { - _serializer.WriteObject(writer, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteObject(XmlDictionaryWriter writer, object? graph) - { - _serializer.WriteObject(writer, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override object? ReadObject(Stream stream) - { - return _serializer.ReadObject(stream); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override object? ReadObject(XmlReader reader) - { - return _serializer.ReadObject(reader); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override object? ReadObject(XmlReader reader, bool verifyObjectName) - { - return _serializer.ReadObject(reader, verifyObjectName); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override object? ReadObject(XmlDictionaryReader reader) - { - return _serializer.ReadObject(reader); - } - - private List GetKnownTypesFromContext(XmlObjectSerializerContext context, IList? serializerKnownTypeList) - { - List knownTypesList = new List(); - if (context != null) - { - List stableNames = new List(); - Dictionary[] entries = context.scopedKnownTypes.dataContractDictionaries; - if (entries != null) - { - for (int i = 0; i < entries.Length; i++) - { - Dictionary entry = entries[i]; - if (entry != null) - { - foreach (KeyValuePair pair in entry) - { - if (!stableNames.Contains(pair.Key)) - { - stableNames.Add(pair.Key); - knownTypesList.Add(pair.Value.UnderlyingType); - } - } - } - } - } - if (serializerKnownTypeList != null) - { - knownTypesList.AddRange(serializerKnownTypeList); - } - } - return knownTypesList; - } - - internal static void InvokeOnSerializing(object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context) - { - if (contract is ClassDataContract classContract) - { - if (classContract.BaseContract != null) - InvokeOnSerializing(value, classContract.BaseContract, context); - if (classContract.OnSerializing != null) - { - bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null); - try - { - classContract.OnSerializing.Invoke(value, new object[] { context.GetStreamingContext() }); - } - catch (SecurityException securityException) - { - if (memberAccessFlag) - { - classContract.RequiresMemberAccessForWrite(securityException); - } - else - { - throw; - } - } - catch (TargetInvocationException targetInvocationException) - { - if (targetInvocationException.InnerException == null) - throw; - //We are catching the TIE here and throws the inner exception only, - //this is needed to have a consistent exception story in all serializers - throw targetInvocationException.InnerException; - } - } - } - } - - internal static void InvokeOnSerialized(object value, DataContract contract, XmlObjectSerializerWriteContextComplexJson context) - { - if (contract is ClassDataContract classContract) - { - if (classContract.BaseContract != null) - InvokeOnSerialized(value, classContract.BaseContract, context); - if (classContract.OnSerialized != null) - { - bool memberAccessFlag = classContract.RequiresMemberAccessForWrite(null); - try - { - classContract.OnSerialized.Invoke(value, new object[] { context.GetStreamingContext() }); - } - catch (SecurityException securityException) - { - if (memberAccessFlag) - { - classContract.RequiresMemberAccessForWrite(securityException); - } - else - { - throw; - } - } - catch (TargetInvocationException targetInvocationException) - { - if (targetInvocationException.InnerException == null) - throw; - //We are catching the TIE here and throws the inner exception only, - //this is needed to have a consistent exception story in all serializers - throw targetInvocationException.InnerException; - } - } - } - } - - internal static void InvokeOnDeserializing(object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context) - { - if (contract is ClassDataContract classContract) - { - if (classContract.BaseContract != null) - InvokeOnDeserializing(value, classContract.BaseContract, context); - if (classContract.OnDeserializing != null) - { - bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null); - try - { - classContract.OnDeserializing.Invoke(value, new object[] { context.GetStreamingContext() }); - } - catch (SecurityException securityException) - { - if (memberAccessFlag) - { - classContract.RequiresMemberAccessForRead(securityException); - } - else - { - throw; - } - } - catch (TargetInvocationException targetInvocationException) - { - if (targetInvocationException.InnerException == null) - throw; - //We are catching the TIE here and throws the inner exception only, - //this is needed to have a consistent exception story in all serializers - throw targetInvocationException.InnerException; - } - } - } - } - - internal static void InvokeOnDeserialized(object value, DataContract contract, XmlObjectSerializerReadContextComplexJson context) - { - if (contract is ClassDataContract classContract) - { - if (classContract.BaseContract != null) - InvokeOnDeserialized(value, classContract.BaseContract, context); - if (classContract.OnDeserialized != null) - { - bool memberAccessFlag = classContract.RequiresMemberAccessForRead(null); - try - { - classContract.OnDeserialized.Invoke(value, new object[] { context.GetStreamingContext() }); - } - catch (SecurityException securityException) - { - if (memberAccessFlag) - { - classContract.RequiresMemberAccessForRead(securityException); - } - else - { - throw; - } - } - catch (TargetInvocationException targetInvocationException) - { - if (targetInvocationException.InnerException == null) - throw; - //We are catching the TIE here and throws the inner exception only, - //this is needed to have a consistent exception story in all serializers - throw targetInvocationException.InnerException; - } - } - } - } - - internal static bool CharacterNeedsEscaping(char ch) - { - return (ch == FORWARD_SLASH || ch == JsonGlobals.QuoteChar || ch < WHITESPACE || ch == BACK_SLASH - || (ch >= HIGH_SURROGATE_START && (ch <= LOW_SURROGATE_END || ch >= MAX_CHAR))); - } - - internal static bool CheckIfJsonNameRequiresMapping(string jsonName) - { - if (jsonName != null) + if (settings == null) { - if (!DataContract.IsValidNCName(jsonName)) - { - return true; - } - - for (int i = 0; i < jsonName.Length; i++) - { - if (CharacterNeedsEscaping(jsonName[i])) - { - return true; - } - } + settings = new DataContractJsonSerializerSettings(); } - return false; - } - - internal static bool CheckIfJsonNameRequiresMapping(XmlDictionaryString jsonName) - { - return (jsonName == null) ? false : CheckIfJsonNameRequiresMapping(jsonName.Value); - } - internal static string ConvertXmlNameToJsonName(string xmlName) - { - return XmlConvert.DecodeName(xmlName); - } - - internal static XmlDictionaryString? ConvertXmlNameToJsonName(XmlDictionaryString? xmlName) - { - return (xmlName == null) ? null : new XmlDictionary().Add(ConvertXmlNameToJsonName(xmlName.Value)); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - internal static object? ReadJsonValue(DataContract contract, XmlReaderDelegator reader, XmlObjectSerializerReadContextComplexJson context) - { - return JsonDataContract.GetJsonDataContract(contract).ReadJsonValue(reader, context); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - internal static void WriteJsonValue(JsonDataContract contract, XmlWriterDelegator writer, object graph, XmlObjectSerializerWriteContextComplexJson context, RuntimeTypeHandle declaredTypeHandle) - { - contract.WriteJsonValue(writer, graph, context, declaredTypeHandle); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteStartObject(XmlWriter writer, object? graph) - { - _serializer.WriteStartObject(writer, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteStartObject(XmlDictionaryWriter writer, object? graph) - { - _serializer.WriteStartObject(writer, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteObjectContent(XmlWriter writer, object? graph) - { - _serializer.WriteObjectContent(writer, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteObjectContent(XmlDictionaryWriter writer, object? graph) - { - _serializer.WriteObjectContent(writer, graph); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteEndObject(XmlWriter writer) - { - _serializer.WriteEndObject(writer); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override void WriteEndObject(XmlDictionaryWriter writer) - { - _serializer.WriteEndObject(writer); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override object? ReadObject(XmlDictionaryReader reader, bool verifyObjectName) - { - return _serializer.ReadObject(reader, verifyObjectName); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override bool IsStartObject(XmlReader reader) - { - return _serializer.IsStartObject(reader); - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public override bool IsStartObject(XmlDictionaryReader reader) - { - return _serializer.IsStartObject(reader); - } - } - - internal sealed class DataContractJsonSerializerImpl : XmlObjectSerializer - { - internal IList? knownTypeList; - internal DataContractDictionary? knownDataContracts; - private EmitTypeInformation _emitTypeInformation; - private bool _ignoreExtensionDataObject; - private ReadOnlyCollection? _knownTypeCollection; - private int _maxItemsInObjectGraph; - private DataContract? _rootContract; // post-surrogate - private XmlDictionaryString? _rootName; - private bool _rootNameRequiresMapping; - private Type _rootType; - private bool _serializeReadOnlyTypes; - private DateTimeFormat? _dateTimeFormat; - private bool _useSimpleDictionaryFormat; - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public DataContractJsonSerializerImpl(Type type) - : this(type, (IEnumerable?)null) - { - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public DataContractJsonSerializerImpl(Type type, IEnumerable? knownTypes) - : this(type, null, knownTypes, int.MaxValue, false, false) - { - } - - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public DataContractJsonSerializerImpl(Type type, XmlDictionaryString? rootName, IEnumerable? knownTypes) - : this(type, rootName, knownTypes, int.MaxValue, false, false) - { + XmlDictionaryString? rootName = (settings.RootName == null) ? null : new XmlDictionary(1).Add(settings.RootName); + Initialize(type, rootName, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject, + settings.EmitTypeInformation, settings.SerializeReadOnlyTypes, settings.DateTimeFormat, settings.UseSimpleDictionaryFormat); } [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - internal DataContractJsonSerializerImpl(Type type, + internal DataContractJsonSerializer(Type type, XmlDictionaryString? rootName, IEnumerable? knownTypes, int maxItemsInObjectGraph, @@ -554,17 +96,9 @@ internal DataContractJsonSerializerImpl(Type type, Initialize(type, rootName, knownTypes, maxItemsInObjectGraph, ignoreExtensionDataObject, emitTypeInformation, false, null, false); } - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - public DataContractJsonSerializerImpl(Type type, DataContractJsonSerializerSettings? settings) + public bool IgnoreExtensionDataObject { - if (settings == null) - { - settings = new DataContractJsonSerializerSettings(); - } - - XmlDictionaryString? rootName = (settings.RootName == null) ? null : new XmlDictionary(1).Add(settings.RootName); - Initialize(type, rootName, settings.KnownTypes, settings.MaxItemsInObjectGraph, settings.IgnoreExtensionDataObject, - settings.EmitTypeInformation, settings.SerializeReadOnlyTypes, settings.DateTimeFormat, settings.UseSimpleDictionaryFormat); + get { return _ignoreExtensionDataObject; } } public ReadOnlyCollection KnownTypes @@ -603,16 +137,16 @@ internal override DataContractDictionary? KnownDataContracts } } - internal int MaxItemsInObjectGraph + public int MaxItemsInObjectGraph { get { return _maxItemsInObjectGraph; } } - internal bool AlwaysEmitTypeInformation + public DateTimeFormat? DateTimeFormat { get { - return _emitTypeInformation == EmitTypeInformation.Always; + return _dateTimeFormat; } } @@ -632,13 +166,6 @@ public bool SerializeReadOnlyTypes } } - public DateTimeFormat? DateTimeFormat - { - get - { - return _dateTimeFormat; - } - } public bool UseSimpleDictionaryFormat { @@ -893,7 +420,7 @@ internal override bool InternalIsStartObject(XmlReaderDelegator reader) DataContract contract = RootContract; if (contract.IsPrimitive && object.ReferenceEquals(contract.UnderlyingType, _rootType))// handle Nullable differently { - return DataContractJsonSerializerImpl.ReadJsonValue(contract, xmlReader, null); + return DataContractJsonSerializer.ReadJsonValue(contract, xmlReader, null); } XmlObjectSerializerReadContextComplexJson context = XmlObjectSerializerReadContextComplexJson.CreateContext(this, contract); @@ -926,11 +453,6 @@ internal override void InternalWriteObjectContent(XmlWriterDelegator writer, obj Type declaredType = contract.UnderlyingType; Type graphType = (graph == null) ? declaredType : graph.GetType(); - //if (dataContractSurrogate != null) - //{ - // graph = DataContractSerializer.SurrogateToDataContractType(dataContractSurrogate, graph, declaredType, ref graphType); - //} - if (graph == null) { WriteJsonNull(writer); @@ -947,13 +469,13 @@ internal override void InternalWriteObjectContent(XmlWriterDelegator writer, obj } else { - DataContractJsonSerializerImpl.WriteJsonValue(JsonDataContract.GetJsonDataContract(contract), writer, graph, null, declaredType.TypeHandle); // XmlObjectSerializerWriteContextComplexJson + DataContractJsonSerializer.WriteJsonValue(JsonDataContract.GetJsonDataContract(contract), writer, graph, null, declaredType.TypeHandle); // XmlObjectSerializerWriteContextComplexJson } } else { XmlObjectSerializerWriteContextComplexJson context = XmlObjectSerializerWriteContextComplexJson.CreateContext(this, RootContract); - contract = DataContractJsonSerializerImpl.GetDataContract(contract, declaredType, graphType); + contract = DataContractJsonSerializer.GetDataContract(contract, declaredType, graphType); if (contract.CanContainReferences) { context.OnHandleReference(writer, graph, true); // canContainCyclicReference @@ -1057,7 +579,11 @@ internal static void CheckIfTypeIsReference(DataContract dataContract) { if (dataContract.IsReference) { - throw XmlObjectSerializer.CreateSerializationException(SR.Format(SR.JsonUnsupportedForIsReference, DataContract.GetClrTypeFullName(dataContract.UnderlyingType), dataContract.IsReference)); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + XmlObjectSerializer.CreateSerializationException(SR.Format( + SR.JsonUnsupportedForIsReference, + DataContract.GetClrTypeFullName(dataContract.UnderlyingType), + dataContract.IsReference))); } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs index 148b3eebd7d2b1..6ff59d9eaa7f2b 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonClassDataContract.cs @@ -21,12 +21,6 @@ public JsonClassDataContract(ClassDataContract traditionalDataContract) _helper = (base.Helper as JsonClassDataContractCriticalHelper)!; } - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - private JsonFormatClassReaderDelegate CreateJsonFormatReaderDelegate() - { - return new ReflectionJsonClassReader(TraditionalClassDataContract).ReflectionReadClass; - } - internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate { [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -41,7 +35,7 @@ internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate JsonFormatClassReaderDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { - tempDelegate = CreateJsonFormatReaderDelegate(); + tempDelegate = new ReflectionJsonClassReader(TraditionalClassDataContract).ReflectionReadClass; } else { @@ -57,12 +51,6 @@ internal JsonFormatClassReaderDelegate JsonFormatReaderDelegate } } - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - private JsonFormatClassWriterDelegate CreateJsonFormatWriterDelegate() - { - return new ReflectionJsonFormatWriter().ReflectionWriteClass; - } - internal JsonFormatClassWriterDelegate JsonFormatWriterDelegate { [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -77,7 +65,7 @@ internal JsonFormatClassWriterDelegate JsonFormatWriterDelegate JsonFormatClassWriterDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { - tempDelegate = CreateJsonFormatWriterDelegate(); + tempDelegate = new ReflectionJsonFormatWriter().ReflectionWriteClass; } else { @@ -171,7 +159,7 @@ private void CopyMembersAndCheckDuplicateNames() else { memberTable.Add(_traditionalClassDataContract.MemberNames[i].Value, null); - decodedMemberNames[i] = DataContractJsonSerializerImpl.ConvertXmlNameToJsonName(_traditionalClassDataContract.MemberNames[i]); + decodedMemberNames[i] = DataContractJsonSerializer.ConvertXmlNameToJsonName(_traditionalClassDataContract.MemberNames[i]); } } _memberNames = decodedMemberNames; diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs index 8fe2e96c10c4a6..0ed183e05624d4 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonCollectionDataContract.cs @@ -21,12 +21,6 @@ public JsonCollectionDataContract(CollectionDataContract traditionalDataContract _helper = (base.Helper as JsonCollectionDataContractCriticalHelper)!; } - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - private JsonFormatCollectionReaderDelegate CreateJsonFormatReaderDelegate() - { - return new ReflectionJsonCollectionReader().ReflectionReadCollection; - } - internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate { [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -41,7 +35,7 @@ internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate JsonFormatCollectionReaderDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { - tempDelegate = CreateJsonFormatReaderDelegate(); + tempDelegate = new ReflectionJsonCollectionReader().ReflectionReadCollection; } else { @@ -57,12 +51,6 @@ internal JsonFormatCollectionReaderDelegate JsonFormatReaderDelegate } } - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - private JsonFormatGetOnlyCollectionReaderDelegate CreateJsonFormatGetOnlyReaderDelegate() - { - return new ReflectionJsonCollectionReader().ReflectionReadGetOnlyCollection; - } - internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelegate { [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -83,7 +71,7 @@ internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelega JsonFormatGetOnlyCollectionReaderDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { - tempDelegate = CreateJsonFormatGetOnlyReaderDelegate(); + tempDelegate = new ReflectionJsonCollectionReader().ReflectionReadGetOnlyCollection; } else { @@ -99,13 +87,6 @@ internal JsonFormatGetOnlyCollectionReaderDelegate JsonFormatGetOnlyReaderDelega } } - [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] - private JsonFormatCollectionWriterDelegate CreateJsonFormatWriterDelegate() - { - return new ReflectionJsonFormatWriter().ReflectionWriteCollection; - } - - internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate { [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -120,7 +101,7 @@ internal JsonFormatCollectionWriterDelegate JsonFormatWriterDelegate JsonFormatCollectionWriterDelegate tempDelegate; if (DataContractSerializer.Option == SerializationOption.ReflectionOnly) { - tempDelegate = CreateJsonFormatWriterDelegate(); + tempDelegate = new ReflectionJsonFormatWriter().ReflectionWriteCollection; } else { diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs index fa2b5ae042a800..44b0bda31e9942 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs @@ -439,8 +439,7 @@ private void InitForReading(Stream inputStream, Encoding? expectedEncoding) { try { - //this.stream = new BufferedStream(inputStream); - _stream = inputStream; + _stream = new BufferedStream(inputStream); SupportedEncoding expectedEnc = GetSupportedEncoding(expectedEncoding); SupportedEncoding dataEnc = ReadEncoding(); @@ -472,8 +471,7 @@ private void InitForReading(Stream inputStream, Encoding? expectedEncoding) private void InitForWriting(Stream outputStream, Encoding writeEncoding) { _encoding = writeEncoding; - //this.stream = new BufferedStream(outputStream); - _stream = outputStream; + _stream = new BufferedStream(outputStream); // Set the encoding code _encodingCode = GetSupportedEncoding(writeEncoding); diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs index d7f05cd947be5b..fa3a0fea90b17c 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatGeneratorStatics.cs @@ -13,6 +13,8 @@ namespace System.Runtime.Serialization { public static class JsonFormatGeneratorStatics { + private static MethodInfo? s_boxPointer; + private static PropertyInfo? s_collectionItemNameProperty; private static ConstructorInfo? s_extensionDataObjectCtor; @@ -59,6 +61,8 @@ public static class JsonFormatGeneratorStatics private static PropertyInfo? s_typeHandleProperty; + private static MethodInfo? s_unboxPointer; + private static PropertyInfo? s_useSimpleDictionaryFormatReadProperty; private static PropertyInfo? s_useSimpleDictionaryFormatWriteProperty; @@ -81,6 +85,19 @@ public static class JsonFormatGeneratorStatics private static MethodInfo? s_getJsonMemberNameMethod; + public static MethodInfo BoxPointer + { + get + { + if (s_boxPointer == null) + { + s_boxPointer = typeof(Pointer).GetMethod("Box"); + Debug.Assert(s_boxPointer != null); + } + return s_boxPointer; + } + } + public static PropertyInfo CollectionItemNameProperty { get @@ -349,6 +366,18 @@ public static PropertyInfo TypeHandleProperty return s_typeHandleProperty; } } + public static MethodInfo UnboxPointer + { + get + { + if (s_unboxPointer == null) + { + s_unboxPointer = typeof(Pointer).GetMethod("Unbox"); + Debug.Assert(s_unboxPointer != null); + } + return s_unboxPointer; + } + } public static PropertyInfo UseSimpleDictionaryFormatReadProperty { get diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs index 9f2bad8787fb11..13be22414a5cb9 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatReaderGenerator.cs @@ -563,7 +563,14 @@ private void InternalDeserialize(LocalBuilder value, Type type, string name) _ilg.Load(string.Empty); _ilg.Call(XmlFormatGeneratorStatics.InternalDeserializeMethod); - _ilg.ConvertValue(Globals.TypeOfObject, type); + if (type.IsPointer) + { + _ilg.Call(JsonFormatGeneratorStatics.UnboxPointer); + } + else + { + _ilg.ConvertValue(Globals.TypeOfObject, type); + } _ilg.Stloc(value); } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs index a76f91878baa0a..94089b749f4c3f 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonFormatWriterGenerator.cs @@ -107,6 +107,10 @@ internal JsonFormatCollectionWriterDelegate GenerateCollectionWriter(CollectionD } } InitArgs(collectionContract.UnderlyingType); + if (collectionContract.IsReadOnlyContract) + { + ThrowIfCannotSerializeReadOnlyTypes(collectionContract); + } WriteCollection(collectionContract); return (JsonFormatCollectionWriterDelegate)_ilg.EndMethod(); } @@ -162,6 +166,23 @@ private void InitArgs(Type objType) _ilg.Stloc(_objectLocal); } + private void ThrowIfCannotSerializeReadOnlyTypes(CollectionDataContract classContract) + { + ThrowIfCannotSerializeReadOnlyTypes(XmlFormatGeneratorStatics.CollectionSerializationExceptionMessageProperty); + } + + private void ThrowIfCannotSerializeReadOnlyTypes(PropertyInfo serializationExceptionMessageProperty) + { + _ilg.Load(_contextArg); + _ilg.LoadMember(XmlFormatGeneratorStatics.SerializeReadOnlyTypesProperty); + _ilg.IfNot(); + _ilg.Load(_dataContractArg); + _ilg.LoadMember(serializationExceptionMessageProperty); + _ilg.Load(null); + _ilg.Call(XmlFormatGeneratorStatics.ThrowInvalidDataContractExceptionMethod); + _ilg.EndIf(); + } + private void InvokeOnSerializing(ClassDataContract classContract) { if (classContract.BaseContract != null) @@ -243,7 +264,7 @@ private int WriteMembers(ClassDataContract classContract, LocalBuilder? extensio _ilg.IfNotDefaultValue(memberValue); } - bool requiresNameAttribute = DataContractJsonSerializerImpl.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]); + bool requiresNameAttribute = DataContractJsonSerializer.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]); if (requiresNameAttribute || !TryWritePrimitive(memberType, memberValue, member.MemberInfo, arrayItemIndex: null, name: null, nameIndex: i + _childElementIndex)) { // Note: DataContractSerializer has member-conflict logic here to deal with the schema export @@ -554,7 +575,7 @@ private bool TryWritePrimitiveArray(Type type, Type itemType, LocalBuilder value return false; string? writeArrayMethod = null; - switch (itemType.GetTypeCode()) + switch (Type.GetTypeCode(itemType)) { case TypeCode.Boolean: writeArrayMethod = "WriteJsonBooleanArray"; @@ -616,6 +637,15 @@ private void WriteObjectAttribute() private void WriteValue(LocalBuilder memberValue) { Type memberType = memberValue.LocalType; + if (memberType.IsPointer) + { + _ilg.Load(memberValue); + _ilg.Load(memberType); + _ilg.Call(JsonFormatGeneratorStatics.BoxPointer); + memberType = typeof(System.Reflection.Pointer); + memberValue = _ilg.DeclareLocal(memberType, "memberValueRefPointer"); + _ilg.Store(memberValue); + } bool isNullableOfT = (memberType.IsGenericType && memberType.GetGenericTypeDefinition() == Globals.TypeOfNullable); if (memberType.IsValueType && !isNullableOfT) @@ -739,7 +769,7 @@ private void WriteStartElement(LocalBuilder? nameLocal, int nameIndex) // namespace _ilg.Load(null); - if (nameLocal != null && nameLocal.LocalType == Globals.TypeOfString) + if (nameLocal != null && nameLocal.LocalType == typeof(string)) { _ilg.Call(JsonFormatGeneratorStatics.WriteStartElementStringMethod); } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs index 40e34203e1559a..d7e72a18d01c63 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs @@ -44,7 +44,7 @@ public JsonObjectDataContract(DataContract traditionalDataContract) break; case JsonGlobals.arrayString: // Read as object array - return DataContractJsonSerializerImpl.ReadJsonValue(DataContract.GetDataContract(Globals.TypeOfObjectArray), jsonReader, context); + return DataContractJsonSerializer.ReadJsonValue(DataContract.GetDataContract(Globals.TypeOfObjectArray), jsonReader, context); default: throw XmlObjectSerializer.CreateSerializationException(SR.Format(SR.JsonUnexpectedAttributeValue, contentMode)); } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ReflectionJsonFormatWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ReflectionJsonFormatWriter.cs index 10aff105f6b92f..aea41cb1bdf6fa 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ReflectionJsonFormatWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/ReflectionJsonFormatWriter.cs @@ -243,7 +243,7 @@ protected override int ReflectionWriteMembers(XmlWriterDelegator xmlWriter, obje { memberValue = ReflectionGetMemberValue(obj, member); } - bool requiresNameAttribute = DataContractJsonSerializerImpl.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]); + bool requiresNameAttribute = DataContractJsonSerializer.CheckIfXmlNameRequiresMapping(classContract.MemberNames![i]); PrimitiveDataContract? primitiveContract = member.MemberPrimitiveContract; if (requiresNameAttribute || !ReflectionTryWritePrimitive(xmlWriter, context, memberType, memberValue, memberNames[i + childElementIndex] /*name*/, null/*ns*/, primitiveContract)) { diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonReader.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonReader.cs index 21c65485619221..a4faf4835350ce 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonReader.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonReader.cs @@ -337,7 +337,7 @@ private bool IsReadingComplexText } } - protected override void Dispose(bool disposing) + public override void Close() { OnXmlDictionaryReaderClose? onClose = _onReaderClose; _onReaderClose = null; @@ -353,7 +353,8 @@ protected override void Dispose(bool disposing) throw new InvalidOperationException(SR.GenericCallbackException, e); } } - base.Dispose(disposing); + + base.Close(); } public override void EndCanonicalization() diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs index d52d1fabaf4a34..8ce76f7b50f282 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlJsonWriter.cs @@ -193,7 +193,7 @@ private static BinHexEncoding BinHexEncoding private bool WrittenNameWithMapping => (_nameState & NameState.WrittenNameWithMapping) == NameState.WrittenNameWithMapping; - protected override void Dispose(bool disposing) + public override void Close() { if (!IsClosed) { @@ -219,7 +219,7 @@ protected override void Dispose(bool disposing) } } - base.Dispose(disposing); + base.Close(); } public override void Flush() @@ -262,21 +262,20 @@ public void SetOutput(Stream stream, Encoding encoding, bool ownsStream) { throw new ArgumentNullException(nameof(encoding)); } - Encoding? tempEncoding = encoding; - if (tempEncoding.WebName != Encoding.UTF8.WebName) + if (encoding.WebName != Encoding.UTF8.WebName) { - stream = new JsonEncodingStreamWrapper(stream, tempEncoding, false); + stream = new JsonEncodingStreamWrapper(stream, encoding, false); } else { - tempEncoding = null; + encoding = null!; } if (_nodeWriter == null) { _nodeWriter = new JsonNodeWriter(); } - _nodeWriter.SetOutput(stream, ownsStream, tempEncoding); + _nodeWriter.SetOutput(stream, ownsStream, encoding); InitializeWriter(); } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs index d571c7325c48c6..a43cb274d4cdad 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerReadContextComplexJson.cs @@ -7,8 +7,6 @@ using System.Reflection; using System.Xml; using System.Runtime.Serialization; -using DataContractDictionary = System.Collections.Generic.Dictionary; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization.Json @@ -19,8 +17,8 @@ internal sealed class XmlObjectSerializerReadContextComplexJson : XmlObjectSeria private readonly DateTimeFormat? _dateTimeFormat; private readonly bool _useSimpleDictionaryFormat; - internal XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract) - : base(serializer, serializer.MaxItemsInObjectGraph, default(StreamingContext), false) + internal XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract) + : base(serializer, serializer.MaxItemsInObjectGraph, new StreamingContext(StreamingContextStates.All), serializer.IgnoreExtensionDataObject) { this.rootTypeDataContract = rootTypeDataContract; this.serializerKnownTypeList = serializer.knownTypeList; @@ -28,7 +26,7 @@ internal XmlObjectSerializerReadContextComplexJson(DataContractJsonSerializerImp _useSimpleDictionaryFormat = serializer.UseSimpleDictionaryFormat; } - internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract) + internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract) { return new XmlObjectSerializerReadContextComplexJson(serializer, rootTypeDataContract); } @@ -36,7 +34,7 @@ internal static XmlObjectSerializerReadContextComplexJson CreateContext(DataCont [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] protected override object? ReadDataContractValue(DataContract dataContract, XmlReaderDelegator reader) { - return DataContractJsonSerializerImpl.ReadJsonValue(dataContract, reader, this); + return DataContractJsonSerializer.ReadJsonValue(dataContract, reader, this); } [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] @@ -135,6 +133,11 @@ private IDataNode ReadNumericalPrimitiveExtensionDataValue(XmlReaderDelegator xm }; } + internal override int GetArraySize() + { + return -1; + } + internal override void ReadAttributes(XmlReaderDelegator xmlReader) { if (attributes == null) @@ -238,6 +241,21 @@ internal static XmlQualifiedName ParseQualifiedName(string qname) return new XmlQualifiedName(name, ns); } + protected override bool IsReadingCollectionExtensionData(XmlReaderDelegator xmlReader) + { + return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.arrayString; + } + + protected override bool IsReadingClassExtensionData(XmlReaderDelegator xmlReader) + { + return xmlReader.GetAttribute(JsonGlobals.typeString) == JsonGlobals.objectString; + } + + protected override XmlReaderDelegator CreateReaderDelegatorForReader(XmlReader xmlReader) + { + return new JsonReaderDelegator(xmlReader, this._dateTimeFormat); + } + [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] internal override DataContract GetDataContract(RuntimeTypeHandle typeHandle, Type? type) { @@ -323,5 +341,11 @@ private static bool IsBitSet(byte[] bytes, int bitIndex) { return BitFlagsGenerator.IsBitSet(bytes, bitIndex); } + + [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] + protected override DataContract? ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName) + { + return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract!); + } } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs index 6519fba2a7b89d..f107c5b7c56d3b 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/XmlObjectSerializerWriteContextComplexJson.cs @@ -8,7 +8,6 @@ using System.Reflection; using System.Collections; using System.IO; -using DataContractDictionary = System.Collections.Generic.Dictionary; using System.Diagnostics.CodeAnalysis; namespace System.Runtime.Serialization.Json @@ -19,13 +18,13 @@ internal sealed class XmlObjectSerializerWriteContextComplexJson : XmlObjectSeri private bool _perCallXsiTypeAlreadyEmitted; private readonly bool _useSimpleDictionaryFormat; - internal static XmlObjectSerializerWriteContextComplexJson CreateContext(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract) + internal static XmlObjectSerializerWriteContextComplexJson CreateContext(DataContractJsonSerializer serializer, DataContract rootTypeDataContract) { return new XmlObjectSerializerWriteContextComplexJson(serializer, rootTypeDataContract); } - internal XmlObjectSerializerWriteContextComplexJson(DataContractJsonSerializerImpl serializer, DataContract rootTypeDataContract) - : base(serializer, serializer.MaxItemsInObjectGraph, default(StreamingContext), false) + internal XmlObjectSerializerWriteContextComplexJson(DataContractJsonSerializer serializer, DataContract rootTypeDataContract) + : base(serializer, serializer.MaxItemsInObjectGraph, new StreamingContext(StreamingContextStates.All), serializer.IgnoreExtensionDataObject) { _emitXsiType = serializer.EmitTypeInformation; this.rootTypeDataContract = rootTypeDataContract; @@ -50,16 +49,6 @@ public bool UseSimpleDictionaryFormat } } - internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, string clrTypeName, string clrAssemblyName) - { - return false; - } - - internal override bool WriteClrTypeInfo(XmlWriterDelegator xmlWriter, DataContract dataContract) - { - return false; - } - internal override void WriteArraySize(XmlWriterDelegator xmlWriter, int size) { //Noop @@ -161,12 +150,12 @@ protected override void WriteDataContractValue(DataContract dataContract, XmlWri WriteTypeInfo(xmlWriter, jsonDataContract.TypeName!); } _perCallXsiTypeAlreadyEmitted = false; - DataContractJsonSerializerImpl.WriteJsonValue(jsonDataContract, xmlWriter, obj, this, declaredTypeHandle); + DataContractJsonSerializer.WriteJsonValue(jsonDataContract, xmlWriter, obj, this, declaredTypeHandle); } protected override void WriteNull(XmlWriterDelegator xmlWriter) { - DataContractJsonSerializerImpl.WriteJsonNull(xmlWriter); + DataContractJsonSerializer.WriteJsonNull(xmlWriter); } internal XmlDictionaryString CollectionItemName @@ -384,5 +373,39 @@ internal override DataContract GetDataContract(int id, RuntimeTypeHandle typeHan DataContractJsonSerializer.CheckIfTypeIsReference(dataContract); return dataContract; } + + [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] + protected override DataContract? ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName) + { + return XmlObjectSerializerWriteContextComplexJson.ResolveJsonDataContractFromRootDataContract(this, typeQName, rootTypeDataContract!); + } + + [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] + internal static DataContract? ResolveJsonDataContractFromRootDataContract(XmlObjectSerializerContext context, XmlQualifiedName typeQName, DataContract rootTypeDataContract) + { + if (rootTypeDataContract.StableName == typeQName) + return rootTypeDataContract; + + CollectionDataContract? collectionContract = rootTypeDataContract as CollectionDataContract; + while (collectionContract != null) + { + DataContract itemContract; + if (collectionContract.ItemType.IsGenericType + && collectionContract.ItemType.GetGenericTypeDefinition() == typeof(KeyValue<,>)) + { + itemContract = context.GetDataContract(Globals.TypeOfKeyValuePair.MakeGenericType(collectionContract.ItemType.GetGenericArguments())); + } + else + { + itemContract = context.GetDataContract(context.GetSurrogatedType(collectionContract.ItemType)); + } + if (itemContract.StableName == typeQName) + { + return itemContract; + } + collectionContract = itemContract as CollectionDataContract; + } + return null; + } } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializerContext.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializerContext.cs index 9323ae87acaa25..4ef27435c85afe 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializerContext.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlObjectSerializerContext.cs @@ -281,24 +281,28 @@ internal bool IsKnownType(DataContract dataContract, Type? declaredType) if (rootTypeDataContract.StableName == qname) dataContract = rootTypeDataContract; else - { - CollectionDataContract? collectionContract = rootTypeDataContract as CollectionDataContract; - while (collectionContract != null) - { - DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType)); - if (itemContract.StableName == qname) - { - dataContract = itemContract; - break; - } - collectionContract = itemContract as CollectionDataContract; - } - } + dataContract = ResolveDataContractFromRootDataContract(qname); } } return dataContract; } + [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] + protected virtual DataContract? ResolveDataContractFromRootDataContract(XmlQualifiedName typeQName) + { + CollectionDataContract? collectionContract = rootTypeDataContract as CollectionDataContract; + while (collectionContract != null) + { + DataContract itemContract = GetDataContract(GetSurrogatedType(collectionContract.ItemType)); + if (itemContract.StableName == typeQName) + { + return itemContract; + } + collectionContract = itemContract as CollectionDataContract; + } + return null; + } + [RequiresUnreferencedCode(DataContract.SerializerTrimmerWarning)] internal void PushKnownTypes(DataContract dc) { diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System.Private.Runtime.InteropServices.JavaScript.Tests.csproj b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System.Private.Runtime.InteropServices.JavaScript.Tests.csproj index fe9348f4678320..8c552fccec58c0 100644 --- a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System.Private.Runtime.InteropServices.JavaScript.Tests.csproj +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System.Private.Runtime.InteropServices.JavaScript.Tests.csproj @@ -17,6 +17,14 @@ + + + + + + + + diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Simple/SimpleTest.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Simple/SimpleTest.cs new file mode 100644 index 00000000000000..18318330ffcf67 --- /dev/null +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Simple/SimpleTest.cs @@ -0,0 +1,66 @@ +// 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.Threading.Tasks; + +namespace System.Runtime.InteropServices.JavaScript.Tests +{ + public static class SimpleTest + { + public static async Task Test() + { + var tests = new List>(); + tests.Add(TimerTests.T0_NoTimer); + tests.Add(TimerTests.T1_OneTimer); + tests.Add(TimerTests.T2_SecondTimerEarlier); + tests.Add(TimerTests.T3_SecondTimerLater); + tests.Add(TimerTests.T5_FiveTimers); + + try + { + Console.WriteLine("SimpleMain start test!"); + var failures = 0; + var failureNames = new List(); + foreach (var test in tests) + { + var failed = await RunTest(test); + if (failed != null) + { + failureNames.Add(failed); + failures++; + } + } + + foreach (var failure in failureNames) + { + Console.WriteLine(failure); + } + Console.WriteLine($"{Environment.NewLine}=== TEST EXECUTION SUMMARY ==={Environment.NewLine}Total: {tests.Count}, Failed: {failures}"); + return failures; + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + return -1; + } + } + + private static async Task RunTest(Func action) + { + try + { + Console.WriteLine("[STRT] " + action.Method.Name); + await action(); + Console.WriteLine("[DONE] " + action.Method.Name); + return null; + } + catch (Exception ex) + { + var message="[FAIL] "+action.Method.Name + " " + ex.Message; + Console.WriteLine(message); + return message; + } + } + } +} diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Simple/TimerTests.cs b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Simple/TimerTests.cs new file mode 100644 index 00000000000000..3f7f7ac8add77c --- /dev/null +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/System/Runtime/InteropServices/JavaScript/Simple/TimerTests.cs @@ -0,0 +1,192 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.Runtime.InteropServices.JavaScript.Tests +{ + public static class TimerTests + { + static JSObject _timersHelper = (JSObject)Runtime.GetGlobalObject("timersHelper"); + static Function _installWrapper = (Function)_timersHelper.GetObjectProperty("install"); + static Function _getRegisterCount = (Function)_timersHelper.GetObjectProperty("getRegisterCount"); + static Function _getHitCount = (Function)_timersHelper.GetObjectProperty("getHitCount"); + static Function _cleanupWrapper = (Function)_timersHelper.GetObjectProperty("cleanup"); + + static public async Task T0_NoTimer() + { + try + { + _installWrapper.Call(); + + var setCounter = (int)_getRegisterCount.Call(); + Assert.Equal(0, setCounter); + } + finally + { + await WaitForCleanup(); + } + } + + static public async Task T1_OneTimer() + { + int wasCalled = 0; + Timer? timer = null; + try + { + _installWrapper.Call(); + + timer = new Timer((_) => + { + Console.WriteLine("In timer"); + wasCalled++; + }, null, 10, 0); + + var setCounter = (int)_getRegisterCount.Call(); + Assert.True(0 == wasCalled, $"wasCalled: {wasCalled}"); + Assert.True(1 == setCounter, $"setCounter: {setCounter}"); + } + finally + { + await WaitForCleanup(); + Assert.True(1 == wasCalled, $"wasCalled: {wasCalled}"); + timer?.Dispose(); + } + } + + static public async Task T2_SecondTimerEarlier() + { + int wasCalled = 0; + Timer? timer1 = null; + Timer? timer2 = null; + try + { + _installWrapper.Call(); + + timer1 = new Timer((_) => + { + Console.WriteLine("In timer1"); + wasCalled++; + }, null, 10, 0); + timer2 = new Timer((_) => + { + Console.WriteLine("In timer2"); + wasCalled++; + }, null, 5, 0); + + var setCounter = (int)_getRegisterCount.Call(); + Assert.True(2 == setCounter, $"setCounter: {setCounter}"); + Assert.True(0 == wasCalled, $"wasCalled: {wasCalled}"); + + } + finally + { + await WaitForCleanup(); + Assert.True(2 == wasCalled, $"wasCalled: {wasCalled}"); + timer1?.Dispose(); + timer2?.Dispose(); + } + } + + static public async Task T3_SecondTimerLater() + { + int wasCalled = 0; + Timer? timer1 = null; + Timer? timer2 = null; + try + { + _installWrapper.Call(); + + timer1 = new Timer((_) => + { + Console.WriteLine("In timer1"); + wasCalled++; + }, null, 10, 0); + timer2 = new Timer((_) => + { + Console.WriteLine("In timer2"); + wasCalled++; + }, null, 20, 0); + + var setCounter = (int)_getRegisterCount.Call(); + Assert.True(0 == wasCalled, $"wasCalled: {wasCalled}"); + Assert.True(1 == setCounter, $"setCounter: {setCounter}"); + } + finally + { + await WaitForCleanup(); + Assert.True(2 == wasCalled, $"wasCalled: {wasCalled}"); + timer1?.Dispose(); + timer2?.Dispose(); + } + } + + static public async Task T5_FiveTimers() + { + int wasCalled = 0; + Timer? timer1 = null; + Timer? timer2 = null; + Timer? timer3 = null; + Timer? timer4 = null; + Timer? timer5 = null; + try + { + _installWrapper.Call(); + + timer1 = new Timer((_) => + { + Console.WriteLine("In timer1"); + wasCalled++; + }, null, 800, 0); + timer2 = new Timer((_) => + { + Console.WriteLine("In timer2"); + wasCalled++; + }, null, 600, 0); + timer3 = new Timer((_) => + { + Console.WriteLine("In timer3"); + wasCalled++; + }, null, 400, 0); + timer4 = new Timer((_) => + { + Console.WriteLine("In timer4"); + wasCalled++; + }, null, 200, 0); + timer5 = new Timer((_) => + { + Console.WriteLine("In timer5"); + wasCalled++; + }, null, 000, 0); + + var setCounter = (int)_getRegisterCount.Call(); + Assert.True(0 == wasCalled, $"wasCalled: {wasCalled}"); + Assert.True(5 == setCounter, $"setCounter: {setCounter}"); + } + finally + { + await WaitForCleanup(); + var hitCounter = (int)_getHitCount.Call(); + var setCounter = (int)_getRegisterCount.Call(); + Assert.True(5 == wasCalled, $"wasCalled: {wasCalled}"); + Assert.True(8 == hitCounter, $"hitCounter: {hitCounter}"); + Assert.True(12 == setCounter, $"setCounter: {setCounter}"); + timer1?.Dispose(); + timer2?.Dispose(); + timer3?.Dispose(); + timer4?.Dispose(); + timer5?.Dispose(); + } + } + + static private async Task WaitForCleanup() + { + Console.WriteLine("wait for cleanup begin"); + await Task.Delay(1000); + _cleanupWrapper.Call(); + Console.WriteLine("wait for cleanup end"); + } + } +} diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/simple.html b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/simple.html new file mode 100644 index 00000000000000..59acbcfcd1cd1e --- /dev/null +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/simple.html @@ -0,0 +1,14 @@ + + + + + + TESTS + + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/simple.js b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/simple.js new file mode 100644 index 00000000000000..bd9f900aafebf6 --- /dev/null +++ b/src/libraries/System.Private.Runtime.InteropServices.JavaScript/tests/simple.js @@ -0,0 +1,79 @@ +class TimersHelper { + install() { + const measuredCallbackName = "mono_wasm_set_timeout_exec"; + globalThis.registerCounter = 0; + globalThis.hitCounter = 0; + console.log("install") + if (!globalThis.originalSetTimeout) { + globalThis.originalSetTimeout = globalThis.setTimeout; + } + globalThis.setTimeout = (cb, time) => { + var start = Date.now().valueOf(); + if (cb.name === measuredCallbackName) { + globalThis.registerCounter++; + console.log(`registerCounter: ${globalThis.registerCounter} now:${start} delay:${time}`) + } + return globalThis.originalSetTimeout(() => { + if (cb.name === measuredCallbackName) { + var hit = Date.now().valueOf(); + globalThis.hitCounter++; + var delta = hit - start; + console.log(`hitCounter: ${globalThis.hitCounter} now:${hit} delay:${time} delta:${delta}`) + } + cb(); + }, time); + }; + } + + getRegisterCount() { + console.log(`registerCounter: ${globalThis.registerCounter} `) + return globalThis.registerCounter; + } + + getHitCount() { + console.log(`hitCounter: ${globalThis.hitCounter} `) + return globalThis.hitCounter; + } + + cleanup() { + console.log(`cleanup registerCounter: ${globalThis.registerCounter} hitCounter: ${globalThis.hitCounter} `) + globalThis.setTimeout = globalThis.originalSetTimeout; + } +} + +globalThis.timersHelper = new TimersHelper(); + +var Module = { + + config: null, + + preInit: async function() { + await MONO.mono_wasm_load_config("./mono-config.json"); // sets Module.config implicitly + }, + + // Called when the runtime is initialized and wasm is ready + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error) { + console.log("No config found"); + return; + } + + Module.config.loaded_cb = function () { + try { + BINDING.call_static_method("[System.Private.Runtime.InteropServices.JavaScript.Tests] System.Runtime.InteropServices.JavaScript.Tests.SimpleTest:Test", []); + } catch (error) { + throw (error); + } + }; + Module.config.fetch_file_cb = function (asset) { + return fetch (asset, { credentials: 'same-origin' }); + } + + try + { + MONO.mono_load_runtime_and_bcl_args (Module.config); + } catch (error) { + throw(error); + } + }, +}; diff --git a/src/libraries/System.Private.Uri/src/Resources/Strings.resx b/src/libraries/System.Private.Uri/src/Resources/Strings.resx index 92a87cd44ccaa1..9975314e3d97c3 100644 --- a/src/libraries/System.Private.Uri/src/Resources/Strings.resx +++ b/src/libraries/System.Private.Uri/src/Resources/Strings.resx @@ -198,4 +198,7 @@ UriParser's base InitializeAndValidate may only be called once on a single Uri instance and only from an override of InitializeAndValidate. + + GetComponents() may not be used for Path/Query on a Uri instance created with UriCreationOptions.DangerousDisablePathAndQueryCanonicalization. + \ No newline at end of file diff --git a/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj b/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj index 4b63c5b3cb3061..ce5a97d87051bf 100644 --- a/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj +++ b/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj @@ -24,6 +24,7 @@ + diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index ad6efdba8540d1..7d1b4d72201a38 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -121,6 +121,11 @@ internal enum Flags : ulong IriCanonical = 0x78000000000, UnixPath = 0x100000000000, + /// + /// Disables any validation/normalization past the authority. Fragments will always be empty. GetComponents will throw for Path/Query. + /// + DisablePathAndQueryCanonicalization = 0x200000000000, + /// /// Used to ensure that InitializeAndValidate is only called once per Uri instance and only from an override of InitializeAndValidate /// @@ -267,6 +272,8 @@ internal static bool IriParsingStatic(UriParser? syntax) return syntax is null || syntax.InFact(UriSyntaxFlags.AllowIriParsing); } + internal bool DisablePathAndQueryCanonicalization => (_flags & Flags.DisablePathAndQueryCanonicalization) != 0; + internal bool UserDrivenParsing { get @@ -410,6 +417,20 @@ public Uri(string uriString, UriKind uriKind) DebugSetLeftCtor(); } + /// + /// Initializes a new instance of the class with the specified URI and additional . + /// + /// A string that identifies the resource to be represented by the instance. + /// Options that control how the is created and behaves. + public Uri(string uriString, in UriCreationOptions creationOptions) + { + if (uriString is null) + throw new ArgumentNullException(nameof(uriString)); + + CreateThis(uriString, false, UriKind.Absolute, in creationOptions); + DebugSetLeftCtor(); + } + // // Uri(Uri, string) // @@ -1639,6 +1660,9 @@ public override bool Equals([NotNullWhen(true)] object? comparand) // canonicalize the comparand, making comparison possible if (obj is null) { + if (DisablePathAndQueryCanonicalization) + return false; + if (!(comparand is string s)) return false; @@ -1649,6 +1673,9 @@ public override bool Equals([NotNullWhen(true)] object? comparand) return false; } + if (DisablePathAndQueryCanonicalization != obj.DisablePathAndQueryCanonicalization) + return false; + if (ReferenceEquals(OriginalString, obj.OriginalString)) { return true; @@ -2553,7 +2580,7 @@ private unsafe void GetHostViaCustomSyntax() // internal string GetParts(UriComponents uriParts, UriFormat formatAs) { - return GetComponents(uriParts, formatAs); + return InternalGetComponents(uriParts, formatAs); } private string GetEscapedParts(UriComponents uriParts) @@ -3158,9 +3185,6 @@ private unsafe void ParseRemaining() idx = _info.Offset.Path; origIdx = _info.Offset.Path; - //Some uris do not have a query - // When '?' is passed as delimiter, then it's special case - // so both '?' and '#' will work as delimiters if (buildIriStringFromPath) { DebugAssertInCtor(); @@ -3180,6 +3204,45 @@ private unsafe void ParseRemaining() _info.Offset.Path = (ushort)_string.Length; idx = _info.Offset.Path; + } + + // If the user explicitly disabled canonicalization, only figure out the offsets + if (DisablePathAndQueryCanonicalization) + { + if (buildIriStringFromPath) + { + DebugAssertInCtor(); + _string += _originalUnicodeString.Substring(origIdx); + } + + string str = _string; + + if (IsImplicitFile || (syntaxFlags & UriSyntaxFlags.MayHaveQuery) == 0) + { + idx = str.Length; + } + else + { + idx = str.IndexOf('?'); + if (idx == -1) + { + idx = str.Length; + } + } + + _info.Offset.Query = (ushort)idx; + _info.Offset.Fragment = (ushort)str.Length; // There is no fragment in UseRawTarget mode + _info.Offset.End = (ushort)str.Length; + + goto Done; + } + + //Some uris do not have a query + // When '?' is passed as delimiter, then it's special case + // so both '?' and '#' will work as delimiters + if (buildIriStringFromPath) + { + DebugAssertInCtor(); int offset = origIdx; if (IsImplicitFile || ((syntaxFlags & (UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHaveFragment)) == 0)) diff --git a/src/libraries/System.Private.Uri/src/System/UriCreationOptions.cs b/src/libraries/System.Private.Uri/src/System/UriCreationOptions.cs new file mode 100644 index 00000000000000..2d0ee84d08b218 --- /dev/null +++ b/src/libraries/System.Private.Uri/src/System/UriCreationOptions.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System +{ + /// + /// Options that control how a is created and behaves. + /// + public struct UriCreationOptions + { + private bool _disablePathAndQueryCanonicalization; + + /// + /// Disables validation and normalization of the Path and Query. + /// No transformations of the URI past the Authority will take place. + /// instances created with this option do not support s. + /// may not be used for or . + /// Be aware that disabling canonicalization also means that reserved characters will not be escaped, + /// which may corrupt the HTTP request and makes the application subject to request smuggling. + /// Only set this option if you have ensured that the URI string is already sanitized. + /// + public bool DangerousDisablePathAndQueryCanonicalization + { + readonly get => _disablePathAndQueryCanonicalization; + set => _disablePathAndQueryCanonicalization = value; + } + } +} diff --git a/src/libraries/System.Private.Uri/src/System/UriExt.cs b/src/libraries/System.Private.Uri/src/System/UriExt.cs index a644dfa566699a..070e11a7f987f3 100644 --- a/src/libraries/System.Private.Uri/src/System/UriExt.cs +++ b/src/libraries/System.Private.Uri/src/System/UriExt.cs @@ -13,7 +13,7 @@ public partial class Uri // // All public ctors go through here // - private void CreateThis(string? uri, bool dontEscape, UriKind uriKind) + private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCreationOptions creationOptions = default) { DebugAssertInCtor(); @@ -31,6 +31,9 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind) if (dontEscape) _flags |= Flags.UserEscaped; + if (creationOptions.DangerousDisablePathAndQueryCanonicalization) + _flags |= Flags.DisablePathAndQueryCanonicalization; + ParsingError err = ParseScheme(_string, ref _flags, ref _syntax!); InitializeUri(err, uriKind, out UriFormatException? e); @@ -259,6 +262,26 @@ public static bool TryCreate([NotNullWhen(true)] string? uriString, UriKind uriK return e is null && result != null; } + /// + /// Creates a new using the specified instance and . + /// + /// The string representation of the . + /// Options that control how the is created and behaves. + /// The constructed . + /// if the was successfully created; otherwise, . + public static bool TryCreate([NotNullWhen(true)] string? uriString, in UriCreationOptions creationOptions, [NotNullWhen(true)] out Uri? result) + { + if (uriString is null) + { + result = null; + return false; + } + UriFormatException? e = null; + result = CreateHelper(uriString, false, UriKind.Absolute, ref e, in creationOptions); + result?.DebugSetLeftCtor(); + return e is null && result != null; + } + public static bool TryCreate(Uri? baseUri, string? relativeUri, [NotNullWhen(true)] out Uri? result) { if (TryCreate(relativeUri, UriKind.RelativeOrAbsolute, out Uri? relativeLink)) @@ -309,6 +332,16 @@ public static bool TryCreate(Uri? baseUri, Uri? relativeUri, [NotNullWhen(true)] } public string GetComponents(UriComponents components, UriFormat format) + { + if (DisablePathAndQueryCanonicalization && (components & (UriComponents.Path | UriComponents.Query)) != 0) + { + throw new InvalidOperationException(SR.net_uri_GetComponentsCalledWhenCanonicalizationDisabled); + } + + return InternalGetComponents(components, format); + } + + private string InternalGetComponents(UriComponents components, UriFormat format) { if (((components & UriComponents.SerializationInfoString) != 0) && components != UriComponents.SerializationInfoString) throw new ArgumentOutOfRangeException(nameof(components), components, SR.net_uri_NotJustSerialization); @@ -590,7 +623,7 @@ private Uri(Flags flags, UriParser? uriParser, string uri) // // a Uri.TryCreate() method goes through here. // - internal static Uri? CreateHelper(string uriString, bool dontEscape, UriKind uriKind, ref UriFormatException? e) + internal static Uri? CreateHelper(string uriString, bool dontEscape, UriKind uriKind, ref UriFormatException? e, in UriCreationOptions creationOptions = default) { // if (!Enum.IsDefined(typeof(UriKind), uriKind)) -- We currently believe that Enum.IsDefined() is too slow // to be used here. @@ -606,6 +639,9 @@ private Uri(Flags flags, UriParser? uriParser, string uri) if (dontEscape) flags |= Flags.UserEscaped; + if (creationOptions.DangerousDisablePathAndQueryCanonicalization) + flags |= Flags.DisablePathAndQueryCanonicalization; + // We won't use User factory for these errors if (err != ParsingError.None) { diff --git a/src/libraries/System.Private.Uri/src/System/UriScheme.cs b/src/libraries/System.Private.Uri/src/System/UriScheme.cs index d9d96ab59ea3cb..7c39a6c44a336e 100644 --- a/src/libraries/System.Private.Uri/src/System/UriScheme.cs +++ b/src/libraries/System.Private.Uri/src/System/UriScheme.cs @@ -146,6 +146,9 @@ protected virtual string GetComponents(Uri uri, UriComponents components, UriFor if (!uri.IsAbsoluteUri) throw new InvalidOperationException(SR.net_uri_NotAbsolute); + if (uri.DisablePathAndQueryCanonicalization && (components & (UriComponents.Path | UriComponents.Query)) != 0) + throw new InvalidOperationException(SR.net_uri_GetComponentsCalledWhenCanonicalizationDisabled); + return uri.GetComponentsHelper(components, format); } diff --git a/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj b/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj index 8f07bb90af1ffe..21bb5200471aa1 100644 --- a/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj +++ b/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj @@ -17,6 +17,7 @@ + diff --git a/src/libraries/System.Private.Uri/tests/FunctionalTests/UriCreationOptionsTest.cs b/src/libraries/System.Private.Uri/tests/FunctionalTests/UriCreationOptionsTest.cs new file mode 100644 index 00000000000000..3f7438738f0bf9 --- /dev/null +++ b/src/libraries/System.Private.Uri/tests/FunctionalTests/UriCreationOptionsTest.cs @@ -0,0 +1,294 @@ +// 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; + +namespace System.PrivateUri.Tests +{ + public class UriCreationOptionsTest + { + [Fact] + public void UriCreationOptions_HasReasonableDefaults() + { + UriCreationOptions options = default; + + Assert.False(options.DangerousDisablePathAndQueryCanonicalization); + } + + [Fact] + public void UriCreationOptions_StoresCorrectValues() + { + var options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }; + Assert.True(options.DangerousDisablePathAndQueryCanonicalization); + + options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = false }; + Assert.False(options.DangerousDisablePathAndQueryCanonicalization); + } + + public static IEnumerable DisableCanonicalization_TestData() + { + var schemes = new string[] { "http", "hTTp", " http", "https" }; + var hosts = new string[] { "foo", "f\u00F6\u00F6.com" }; + var ports = new string[] { ":80", ":443", ":0123", ":", "" }; + + var pathAndQueries = new string[] + { + "", + " ", + "a b", + "a%20b", + "?a b", + "?a%20b", + "foo/./", + "foo/../", + "//\\//", + "%41", + "A?%41=%42", + "?%41=%42", + "? ", + }; + + var fragments = new string[] { "", "#", "#/foo ? %20%41/..//\\a" }; + var unicodeInPathModes = new int[] { 0, 1, 2, 3 }; + var pathDelimiters = new string[] { "", "/" }; + + // Get various combinations of paths with unicode characters and delimiters + string[] rawTargets = pathAndQueries + .SelectMany(pq => fragments.Select(fragment => pq + fragment)) + .SelectMany(pqf => unicodeInPathModes.Select(unicodeMode => unicodeMode switch + { + 0 => pqf, + 1 => "\u00F6" + pqf, + 2 => pqf + "\u00F6", + _ => pqf.Insert(pqf.Length / 2, "\u00F6") + })) + .ToHashSet() + .SelectMany(pqf => pathDelimiters.Select(delimiter => delimiter + pqf)) + .Where(target => target.StartsWith('/') || target.StartsWith('?')) // Can't see where the authority ends and the path starts otherwise + .ToArray(); + + foreach (string scheme in schemes) + { + foreach (string host in hosts) + { + foreach (string port in ports) + { + foreach (string rawTarget in rawTargets) + { + string uriString = $"{scheme}://{host}{port}{rawTarget}"; + + int expectedPort = port.Length > 1 ? int.Parse(port.AsSpan(1)) : new Uri($"{scheme}://foo").Port; + + string expectedQuery = rawTarget.Contains('?') ? rawTarget.Substring(rawTarget.IndexOf('?')) : ""; + + string expectedPath = rawTarget.Substring(0, rawTarget.Length - expectedQuery.Length); + + yield return new object[] { uriString, host, expectedPort, expectedPath, expectedQuery }; + } + } + } + } + } + + [Theory] + [MemberData(nameof(DisableCanonicalization_TestData))] + public void DisableCanonicalization_IsRespected(string uriString, string expectedHost, int expectedPort, string expectedPath, string expectedQuery) + { + var options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }; + + var uri = new Uri(uriString, options); + DoAsserts(uri); + + Assert.True(Uri.TryCreate(uriString, options, out uri)); + DoAsserts(uri); + + void DoAsserts(Uri uri) + { + Assert.Equal(new Uri($"http://{expectedHost}").Host, uri.Host); + Assert.Equal(new Uri($"http://{expectedHost}").IdnHost, uri.IdnHost); + + Assert.Equal(expectedPort, uri.Port); + + Assert.Same(uri.AbsolutePath, uri.AbsolutePath); + Assert.Equal(expectedPath, uri.AbsolutePath); + + Assert.Same(uri.Query, uri.Query); + Assert.Equal(expectedQuery, uri.Query); + + string expectedPathAndQuery = expectedPath + expectedQuery; + Assert.Same(uri.PathAndQuery, uri.PathAndQuery); + Assert.Equal(expectedPathAndQuery, uri.PathAndQuery); + + Assert.Same(uri.Fragment, uri.Fragment); + Assert.Empty(uri.Fragment); // Fragment is always empty if DisableCanonicalization is set + } + } + + [Fact] + public void DisableCanonicalization_OnlyEqualToUrisWithMatchingFlag() + { + const string AbsoluteUri = "http://host"; + const string Path = "/foo"; + + var absolute = new Uri(AbsoluteUri + Path, new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = false }); + var absoluteRaw = new Uri(AbsoluteUri + Path, new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }); + NotEqual(absolute, absoluteRaw); + Equal(absolute, absolute); + Equal(absoluteRaw, absoluteRaw); + + var absoluteRawCopy = new Uri(AbsoluteUri + Path, new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }); + Equal(absoluteRaw, absoluteRawCopy); + + var absoluteRawDifferentPath = new Uri(AbsoluteUri + "/bar", new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }); + NotEqual(absoluteRaw, absoluteRawDifferentPath); + + var absoluteRawSameAuthority = new Uri(AbsoluteUri + ":80" + Path, new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }); + Equal(absoluteRaw, absoluteRawSameAuthority); + + static void Equal(Uri left, Uri right) + { + Assert.True(left.Equals(right)); + Assert.True(right.Equals(left)); + Assert.Equal(left.GetHashCode(), right.GetHashCode()); + } + + static void NotEqual(Uri left, Uri right) + { + Assert.False(left.Equals(right)); + Assert.False(right.Equals(left)); + } + } + + private const string FilePathRawData = "//\\A%41 %20\u00F6/.././%5C%2F#%42?%43#%44"; + + public static IEnumerable ImplicitFilePaths_TestData() + { + yield return Entry("C:/"); + yield return Entry("C|/"); + + yield return Entry(@"//foo"); + yield return Entry(@"\/foo"); + yield return Entry(@"/\foo"); + yield return Entry(@"\\foo"); + + if (!PlatformDetection.IsWindows) + { + yield return Entry("/foo"); + } + + static object[] Entry(string filePath) => new object[] { $"{filePath}/{FilePathRawData}" }; + } + + [Theory] + [MemberData(nameof(ImplicitFilePaths_TestData))] + public void DisableCanonicalization_WorksWithFileUris(string implicitFilePath) + { + var options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }; + + var uri = new Uri(implicitFilePath, options); + DoAsserts(uri); + + Assert.True(Uri.TryCreate(implicitFilePath, options, out uri)); + DoAsserts(uri); + + static void DoAsserts(Uri uri) + { + Assert.True(uri.IsAbsoluteUri); + Assert.True(uri.IsFile); + Assert.Contains(FilePathRawData, uri.AbsolutePath); + Assert.Contains(FilePathRawData, uri.AbsoluteUri); + Assert.Contains(FilePathRawData, uri.ToString()); + } + } + + [Theory] + [InlineData("http")] + [InlineData("https")] + [InlineData("ftp")] + [InlineData("file")] + [InlineData("custom-unknown")] + [InlineData("custom-registered")] + public void DisableCanonicalization_WorksWithDifferentSchemes(string scheme) + { + if (scheme == "custom-registered") + { + scheme += "DisableCanonicalization"; + UriParser.Register(new HttpStyleUriParser(), scheme, defaultPort: Random.Shared.Next(-1, 65536)); + } + + string uriString = $"{scheme}://host/p%41th?a=%42#fragm%45nt"; + var options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }; + + var referenceUri = new Uri(uriString); + + var uri = new Uri(uriString, options); + DoAsserts(uri); + + Assert.True(Uri.TryCreate(uriString, options, out uri)); + DoAsserts(uri); + + void DoAsserts(Uri uri) + { + Assert.Same(referenceUri.Scheme, uri.Scheme); + Assert.Equal(referenceUri.Host, uri.Host); + Assert.Equal(referenceUri.IdnHost, uri.IdnHost); + Assert.Equal(referenceUri.Authority, uri.Authority); + Assert.Equal(referenceUri.Port, uri.Port); + Assert.Equal(referenceUri.IsDefaultPort, uri.IsDefaultPort); + + string referencePath = "/pAth"; + string referenceQuery = "?a=B"; + string path = "/p%41th"; + string query = "?a=%42#fragm%45nt"; + + if (scheme == "ftp") // No query + { + referencePath += referenceQuery.Replace("?", "%3F"); + path += query; + + referenceQuery = string.Empty; + query = string.Empty; + } + + Assert.Equal(referencePath, referenceUri.AbsolutePath); + Assert.Equal(path, uri.AbsolutePath); + + Assert.Equal(referenceQuery, referenceUri.Query); + Assert.Equal(query, uri.Query); + + Assert.Equal(referencePath + referenceQuery, referenceUri.PathAndQuery); + Assert.Equal(path + query, uri.PathAndQuery); + + Assert.Equal("#fragmEnt", referenceUri.Fragment); + Assert.Empty(uri.Fragment); + + _ = referenceUri.GetComponents(UriComponents.AbsoluteUri, UriFormat.UriEscaped); + Assert.Throws(() => uri.GetComponents(UriComponents.Path, UriFormat.UriEscaped)); + } + } + + [Theory] + [InlineData(UriFormat.UriEscaped)] + [InlineData(UriFormat.Unescaped)] + [InlineData(UriFormat.SafeUnescaped)] + public void DisableCanonicalization_GetComponentsThrowsForPathAndQuery(UriFormat format) + { + var uri = new Uri("http://host/foo?bar=abc#fragment", new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true }); + + Assert.Equal("http", uri.GetComponents(UriComponents.Scheme, format)); + Assert.Equal("host", uri.GetComponents(UriComponents.Host, format)); + Assert.Equal("80", uri.GetComponents(UriComponents.StrongPort, format)); + Assert.Empty(uri.GetComponents(UriComponents.Fragment, format)); + + Assert.Throws(() => uri.GetComponents(UriComponents.Path, format)); + Assert.Throws(() => uri.GetComponents(UriComponents.Query, format)); + Assert.Throws(() => uri.GetComponents(UriComponents.PathAndQuery, format)); + Assert.Throws(() => uri.GetComponents(UriComponents.AbsoluteUri, format)); + } + + + private sealed class CustomUriParser : UriParser { } + } +} diff --git a/src/libraries/System.Private.Xml/src/Resources/Strings.resx b/src/libraries/System.Private.Xml/src/Resources/Strings.resx index d19dc6ec4eb314..112359dfecba8c 100644 --- a/src/libraries/System.Private.Xml/src/Resources/Strings.resx +++ b/src/libraries/System.Private.Xml/src/Resources/Strings.resx @@ -2787,6 +2787,9 @@ Type '{0}' is not serializable. + + Type '{0}' is from an AssemblyLoadContext which is incompatible with that which contains this XmlSerializer. + Invalid XmlSerializerAssemblyAttribute usage. Please use {0} property or {1} property. diff --git a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj index 2afc279cf5f805..648245cdb49703 100644 --- a/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj +++ b/src/libraries/System.Private.Xml/src/System.Private.Xml.csproj @@ -446,6 +446,7 @@ + @@ -565,6 +566,7 @@ + diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs index 8fdeed7b60b770..c3df77a5a2bc3f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/Compilation.cs @@ -11,6 +11,8 @@ using System.Globalization; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.Loader; namespace System.Xml.Serialization { @@ -149,79 +151,82 @@ internal void InitAssemblyMethods(XmlMapping[] xmlMappings) contract = null; string? serializerName = null; - // check to see if we loading explicit pre-generated assembly - object[] attrs = type.GetCustomAttributes(typeof(System.Xml.Serialization.XmlSerializerAssemblyAttribute), false); - if (attrs.Length == 0) + using (AssemblyLoadContext.EnterContextualReflection(type.Assembly)) { - // Guess serializer name: if parent assembly signed use strong name - AssemblyName name = type.Assembly.GetName(); - serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace); - // use strong name - name.Name = serializerName; - name.CodeBase = null; - name.CultureInfo = CultureInfo.InvariantCulture; - - try - { - serializer = Assembly.Load(name); - } - catch (Exception e) - { - if (e is OutOfMemoryException) + // check to see if we loading explicit pre-generated assembly + object[] attrs = type.GetCustomAttributes(typeof(System.Xml.Serialization.XmlSerializerAssemblyAttribute), false); + if (attrs.Length == 0) + { + // Guess serializer name: if parent assembly signed use strong name + AssemblyName name = type.Assembly.GetName(); + serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace); + // use strong name + name.Name = serializerName; + name.CodeBase = null; + name.CultureInfo = CultureInfo.InvariantCulture; + + try { - throw; + serializer = Assembly.Load(name); } - } - - serializer ??= LoadAssemblyByPath(type, serializerName); - - if (serializer == null) - { - if (XmlSerializer.Mode == SerializationMode.PreGenOnly) + catch (Exception e) { - throw new Exception(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName)); + if (e is OutOfMemoryException) + { + throw; + } } - return null; - } + serializer ??= LoadAssemblyByPath(type, serializerName); - if (!IsSerializerVersionMatch(serializer, type, defaultNamespace)) - { - XmlSerializationEventSource.Log.XmlSerializerExpired(serializerName, type.FullName!); - return null; - } - } - else - { - System.Xml.Serialization.XmlSerializerAssemblyAttribute assemblyAttribute = (System.Xml.Serialization.XmlSerializerAssemblyAttribute)attrs[0]; - if (assemblyAttribute.AssemblyName != null && assemblyAttribute.CodeBase != null) - throw new InvalidOperationException(SR.Format(SR.XmlPregenInvalidXmlSerializerAssemblyAttribute, "AssemblyName", "CodeBase")); + if (serializer == null) + { + if (XmlSerializer.Mode == SerializationMode.PreGenOnly) + { + throw new Exception(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName)); + } - // found XmlSerializerAssemblyAttribute attribute, it should have all needed information to load the pre-generated serializer - if (assemblyAttribute.AssemblyName != null) - { - serializerName = assemblyAttribute.AssemblyName; - serializer = Assembly.Load(serializerName); // LoadWithPartialName just does this in .Net Core; changing the obsolete call. - } - else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0) - { - serializerName = assemblyAttribute.CodeBase; - serializer = Assembly.LoadFrom(serializerName); + return null; + } + + if (!IsSerializerVersionMatch(serializer, type, defaultNamespace)) + { + XmlSerializationEventSource.Log.XmlSerializerExpired(serializerName, type.FullName!); + return null; + } } else { - serializerName = type.Assembly.FullName; - serializer = type.Assembly; - } - if (serializer == null) - { - throw new FileNotFoundException(null, serializerName); + System.Xml.Serialization.XmlSerializerAssemblyAttribute assemblyAttribute = (System.Xml.Serialization.XmlSerializerAssemblyAttribute)attrs[0]; + if (assemblyAttribute.AssemblyName != null && assemblyAttribute.CodeBase != null) + throw new InvalidOperationException(SR.Format(SR.XmlPregenInvalidXmlSerializerAssemblyAttribute, "AssemblyName", "CodeBase")); + + // found XmlSerializerAssemblyAttribute attribute, it should have all needed information to load the pre-generated serializer + if (assemblyAttribute.AssemblyName != null) + { + serializerName = assemblyAttribute.AssemblyName; + serializer = Assembly.Load(serializerName); // LoadWithPartialName just does this in .Net Core; changing the obsolete call. + } + else if (assemblyAttribute.CodeBase != null && assemblyAttribute.CodeBase.Length > 0) + { + serializerName = assemblyAttribute.CodeBase; + serializer = Assembly.LoadFrom(serializerName); + } + else + { + serializerName = type.Assembly.FullName; + serializer = type.Assembly; + } + if (serializer == null) + { + throw new FileNotFoundException(null, serializerName); + } } + Type contractType = GetTypeFromAssembly(serializer, "XmlSerializerContract"); + contract = (XmlSerializerImplementation)Activator.CreateInstance(contractType)!; + if (contract.CanSerialize(type)) + return serializer; } - Type contractType = GetTypeFromAssembly(serializer, "XmlSerializerContract"); - contract = (XmlSerializerImplementation)Activator.CreateInstance(contractType)!; - if (contract.CanSerialize(type)) - return serializer; return null; } @@ -449,81 +454,93 @@ internal static bool GenerateSerializerToStream(XmlMapping[] xmlMappings, Type?[ } [RequiresUnreferencedCode("calls GenerateElement")] - internal static Assembly GenerateRefEmitAssembly(XmlMapping[] xmlMappings, Type?[]? types, string? defaultNamespace) + internal static Assembly GenerateRefEmitAssembly(XmlMapping[] xmlMappings, Type?[] types, string? defaultNamespace) { + var mainType = (types.Length > 0) ? types[0] : null; + Assembly? mainAssembly = mainType?.Assembly; var scopeTable = new Dictionary(); foreach (XmlMapping mapping in xmlMappings) scopeTable[mapping.Scope!] = mapping; TypeScope[] scopes = new TypeScope[scopeTable.Keys.Count]; scopeTable.Keys.CopyTo(scopes, 0); - string assemblyName = "Microsoft.GeneratedCode"; - AssemblyBuilder assemblyBuilder = CodeGenerator.CreateAssemblyBuilder(assemblyName); - // Add AssemblyVersion attribute to match parent assembly version - if (types != null && types.Length > 0 && types[0] != null) + using (AssemblyLoadContext.EnterContextualReflection(mainAssembly)) { - ConstructorInfo AssemblyVersionAttribute_ctor = typeof(AssemblyVersionAttribute).GetConstructor( - new Type[] { typeof(string) } - )!; - string assemblyVersion = types[0]!.Assembly.GetName().Version!.ToString(); - assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(AssemblyVersionAttribute_ctor, new object[] { assemblyVersion })); - } - CodeIdentifiers classes = new CodeIdentifiers(); - classes.AddUnique("XmlSerializationWriter", "XmlSerializationWriter"); - classes.AddUnique("XmlSerializationReader", "XmlSerializationReader"); - string? suffix = null; - if (types != null && types.Length == 1 && types[0] != null) - { - suffix = CodeIdentifier.MakeValid(types[0]!.Name); - if (types[0]!.IsArray) + // Before generating any IL, check each mapping and supported type to make sure + // they are compatible with the current ALC + for (int i = 0; i < types.Length; i++) + VerifyLoadContext(types[i], mainAssembly); + foreach (var mapping in xmlMappings) + VerifyLoadContext(mapping.Accessor.Mapping?.TypeDesc?.Type, mainAssembly); + + string assemblyName = "Microsoft.GeneratedCode"; + AssemblyBuilder assemblyBuilder = CodeGenerator.CreateAssemblyBuilder(assemblyName); + // Add AssemblyVersion attribute to match parent assembly version + if (mainType != null) + { + ConstructorInfo AssemblyVersionAttribute_ctor = typeof(AssemblyVersionAttribute).GetConstructor( + new Type[] { typeof(string) } + )!; + string assemblyVersion = mainType.Assembly.GetName().Version!.ToString(); + assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(AssemblyVersionAttribute_ctor, new object[] { assemblyVersion })); + } + CodeIdentifiers classes = new CodeIdentifiers(); + classes.AddUnique("XmlSerializationWriter", "XmlSerializationWriter"); + classes.AddUnique("XmlSerializationReader", "XmlSerializationReader"); + string? suffix = null; + if (mainType != null) { - suffix += "Array"; + suffix = CodeIdentifier.MakeValid(mainType.Name); + if (mainType.IsArray) + { + suffix += "Array"; + } } - } - ModuleBuilder moduleBuilder = CodeGenerator.CreateModuleBuilder(assemblyBuilder, assemblyName); + ModuleBuilder moduleBuilder = CodeGenerator.CreateModuleBuilder(assemblyBuilder, assemblyName); - string writerClass = "XmlSerializationWriter" + suffix; - writerClass = classes.AddUnique(writerClass, writerClass); - XmlSerializationWriterILGen writerCodeGen = new XmlSerializationWriterILGen(scopes, "public", writerClass); - writerCodeGen.ModuleBuilder = moduleBuilder; + string writerClass = "XmlSerializationWriter" + suffix; + writerClass = classes.AddUnique(writerClass, writerClass); + XmlSerializationWriterILGen writerCodeGen = new XmlSerializationWriterILGen(scopes, "public", writerClass); + writerCodeGen.ModuleBuilder = moduleBuilder; - writerCodeGen.GenerateBegin(); - string[] writeMethodNames = new string[xmlMappings.Length]; + writerCodeGen.GenerateBegin(); + string[] writeMethodNames = new string[xmlMappings.Length]; - for (int i = 0; i < xmlMappings.Length; i++) - { - writeMethodNames[i] = writerCodeGen.GenerateElement(xmlMappings[i])!; - } - Type writerType = writerCodeGen.GenerateEnd(); + for (int i = 0; i < xmlMappings.Length; i++) + { + writeMethodNames[i] = writerCodeGen.GenerateElement(xmlMappings[i])!; + } + Type writerType = writerCodeGen.GenerateEnd(); - string readerClass = "XmlSerializationReader" + suffix; - readerClass = classes.AddUnique(readerClass, readerClass); - XmlSerializationReaderILGen readerCodeGen = new XmlSerializationReaderILGen(scopes, "public", readerClass); + string readerClass = "XmlSerializationReader" + suffix; + readerClass = classes.AddUnique(readerClass, readerClass); + XmlSerializationReaderILGen readerCodeGen = new XmlSerializationReaderILGen(scopes, "public", readerClass); - readerCodeGen.ModuleBuilder = moduleBuilder; - readerCodeGen.CreatedTypes.Add(writerType.Name, writerType); + readerCodeGen.ModuleBuilder = moduleBuilder; + readerCodeGen.CreatedTypes.Add(writerType.Name, writerType); - readerCodeGen.GenerateBegin(); - string[] readMethodNames = new string[xmlMappings.Length]; - for (int i = 0; i < xmlMappings.Length; i++) - { - readMethodNames[i] = readerCodeGen.GenerateElement(xmlMappings[i])!; - } - readerCodeGen.GenerateEnd(readMethodNames, xmlMappings, types!); + readerCodeGen.GenerateBegin(); + string[] readMethodNames = new string[xmlMappings.Length]; + for (int i = 0; i < xmlMappings.Length; i++) + { + readMethodNames[i] = readerCodeGen.GenerateElement(xmlMappings[i])!; + } + readerCodeGen.GenerateEnd(readMethodNames, xmlMappings, types!); - string baseSerializer = readerCodeGen.GenerateBaseSerializer("XmlSerializer1", readerClass, writerClass, classes); - var serializers = new Dictionary(); - for (int i = 0; i < xmlMappings.Length; i++) - { - if (!serializers.ContainsKey(xmlMappings[i].Key!)) + string baseSerializer = readerCodeGen.GenerateBaseSerializer("XmlSerializer1", readerClass, writerClass, classes); + var serializers = new Dictionary(); + for (int i = 0; i < xmlMappings.Length; i++) { - serializers[xmlMappings[i].Key!] = readerCodeGen.GenerateTypedSerializer(readMethodNames[i], writeMethodNames[i], xmlMappings[i], classes, baseSerializer, readerClass, writerClass); + if (!serializers.ContainsKey(xmlMappings[i].Key!)) + { + serializers[xmlMappings[i].Key!] = readerCodeGen.GenerateTypedSerializer(readMethodNames[i], writeMethodNames[i], xmlMappings[i], classes, baseSerializer, readerClass, writerClass); + } } - } - readerCodeGen.GenerateSerializerContract("XmlSerializerContract", xmlMappings, types!, readerClass, readMethodNames, writerClass, writeMethodNames, serializers); + readerCodeGen.GenerateSerializerContract("XmlSerializerContract", xmlMappings, types!, readerClass, readMethodNames, writerClass, writeMethodNames, serializers); - return writerType.Assembly; + return writerType.Assembly; + } } private static MethodInfo GetMethodFromType( @@ -588,6 +605,23 @@ internal bool CanRead(XmlMapping mapping, XmlReader xmlReader) return encodingStyle; } + internal static void VerifyLoadContext(Type? t, Assembly? assembly) + { + // The quick case, t is null or in the same assembly + if (t == null || assembly == null || t.Assembly == assembly) + return; + + // No worries if the type is not collectible + var typeALC = AssemblyLoadContext.GetLoadContext(t.Assembly); + if (typeALC == null || !typeALC.IsCollectible) + return; + + // Collectible types should be in the same collectible context + var baseALC = AssemblyLoadContext.GetLoadContext(assembly) ?? AssemblyLoadContext.CurrentContextualReflectionContext; + if (typeALC != baseALC) + throw new InvalidOperationException(SR.Format(SR.XmlTypeInBadLoadContext, t.FullName)); + } + [RequiresUnreferencedCode("calls Contract")] internal object? InvokeReader(XmlMapping mapping, XmlReader xmlReader, XmlDeserializationEvents events, string? encodingStyle) { @@ -666,9 +700,9 @@ internal sealed class TempMethodDictionary : Dictionary internal sealed class TempAssemblyCacheKey { private readonly string? _ns; - private readonly object _type; + private readonly Type _type; - internal TempAssemblyCacheKey(string? ns, object type) + internal TempAssemblyCacheKey(string? ns, Type type) { _type = type; _ns = ns; @@ -690,29 +724,52 @@ public override int GetHashCode() internal sealed class TempAssemblyCache { - private Dictionary _cache = new Dictionary(); + private Dictionary _fastCache = new Dictionary(); + private ConditionalWeakTable> _collectibleCaches = new ConditionalWeakTable>(); - internal TempAssembly? this[string? ns, object o] + internal TempAssembly? this[string? ns, Type t] { get { TempAssembly? tempAssembly; - _cache.TryGetValue(new TempAssemblyCacheKey(ns, o), out tempAssembly); + TempAssemblyCacheKey key = new TempAssemblyCacheKey(ns, t); + + if (_fastCache.TryGetValue(key, out tempAssembly)) + return tempAssembly; + + if (_collectibleCaches.TryGetValue(t.Assembly, out var cCache)) + cCache.TryGetValue(key, out tempAssembly); + return tempAssembly; } } - internal void Add(string? ns, object o, TempAssembly assembly) + internal void Add(string? ns, Type t, TempAssembly assembly) { - TempAssemblyCacheKey key = new TempAssemblyCacheKey(ns, o); lock (this) { - TempAssembly? tempAssembly; - if (_cache.TryGetValue(key, out tempAssembly) && tempAssembly == assembly) + TempAssembly? tempAssembly = this[ns, t]; + if (tempAssembly == assembly) return; - Dictionary _copy = new Dictionary(_cache); // clone - _copy[key] = assembly; - _cache = _copy; + + AssemblyLoadContext? alc = AssemblyLoadContext.GetLoadContext(t.Assembly); + TempAssemblyCacheKey key = new TempAssemblyCacheKey(ns, t); + Dictionary? cache; + + if (alc != null && alc.IsCollectible) + { + cache = _collectibleCaches.TryGetValue(t.Assembly, out var c) // Clone or create + ? new Dictionary(c) + : new Dictionary(); + cache[key] = assembly; + _collectibleCaches.AddOrUpdate(t.Assembly, cache); + } + else + { + cache = new Dictionary(_fastCache); // Clone + cache[key] = assembly; + _fastCache = cache; + } } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ContextAwareTables.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ContextAwareTables.cs new file mode 100644 index 00000000000000..64e09bbc063b2c --- /dev/null +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ContextAwareTables.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Xml.Serialization +{ + using System; + using System.Collections; + using System.Diagnostics.CodeAnalysis; + using System.Runtime.CompilerServices; + using System.Runtime.Loader; + + internal class ContextAwareTables<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T> where T : class? + { + private Hashtable _defaultTable; + private ConditionalWeakTable _collectibleTable; + + public ContextAwareTables() + { + _defaultTable = new Hashtable(); + _collectibleTable = new ConditionalWeakTable(); + } + + internal T GetOrCreateValue(Type t, Func f) + { + // The fast and most common default case + T? ret = (T?)_defaultTable[t]; + if (ret != null) + return ret; + + // Common case for collectible contexts + if (_collectibleTable.TryGetValue(t, out ret)) + return ret; + + // Not found. Do the slower work of creating the value in the correct collection. + AssemblyLoadContext? alc = AssemblyLoadContext.GetLoadContext(t.Assembly); + + // Null and non-collectible load contexts use the default table + if (alc == null || !alc.IsCollectible) + { + lock (_defaultTable) + { + if ((ret = (T?)_defaultTable[t]) == null) + { + ret = f(); + _defaultTable[t] = ret; + } + } + } + + // Collectible load contexts should use the ConditionalWeakTable so they can be unloaded + else + { + lock (_collectibleTable) + { + if (!_collectibleTable.TryGetValue(t, out ret)) + { + ret = f(); + _collectibleTable.AddOrUpdate(t, ret); + } + } + } + + return ret; + } + } +} diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs index 0c55638a27a66a..2477f283b01f16 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/ReflectionXmlSerializationReader.cs @@ -627,40 +627,48 @@ private static void AddObjectsIntoTargetCollection(object targetCollection, List } } - private static readonly ConcurrentDictionary<(Type, string), ReflectionXmlSerializationReaderHelper.SetMemberValueDelegate> s_setMemberValueDelegateCache = new ConcurrentDictionary<(Type, string), ReflectionXmlSerializationReaderHelper.SetMemberValueDelegate>(); + private static readonly ContextAwareTables s_setMemberValueDelegateCache = new ContextAwareTables(); [RequiresUnreferencedCode(XmlSerializer.TrimSerializationWarning)] private static ReflectionXmlSerializationReaderHelper.SetMemberValueDelegate GetSetMemberValueDelegate(object o, string memberName) { Debug.Assert(o != null, "Object o should not be null"); Debug.Assert(!string.IsNullOrEmpty(memberName), "memberName must have a value"); - (Type, string) typeMemberNameTuple = (o.GetType(), memberName); - if (!s_setMemberValueDelegateCache.TryGetValue(typeMemberNameTuple, out ReflectionXmlSerializationReaderHelper.SetMemberValueDelegate? result)) + Type type = o.GetType(); + var delegateCacheForType = s_setMemberValueDelegateCache.GetOrCreateValue(type, () => new Hashtable()); + var result = delegateCacheForType[memberName]; + if (result == null) { - MemberInfo memberInfo = ReflectionXmlSerializationHelper.GetEffectiveSetInfo(o.GetType(), memberName); - Debug.Assert(memberInfo != null, "memberInfo could not be retrieved"); - Type memberType; - if (memberInfo is PropertyInfo propInfo) - { - memberType = propInfo.PropertyType; - } - else if (memberInfo is FieldInfo fieldInfo) - { - memberType = fieldInfo.FieldType; - } - else + lock (delegateCacheForType) { - throw new InvalidOperationException(SR.XmlInternalError); - } + if ((result = delegateCacheForType[memberName]) == null) + { + MemberInfo memberInfo = ReflectionXmlSerializationHelper.GetEffectiveSetInfo(o.GetType(), memberName); + Debug.Assert(memberInfo != null, "memberInfo could not be retrieved"); + Type memberType; + if (memberInfo is PropertyInfo propInfo) + { + memberType = propInfo.PropertyType; + } + else if (memberInfo is FieldInfo fieldInfo) + { + memberType = fieldInfo.FieldType; + } + else + { + throw new InvalidOperationException(SR.XmlInternalError); + } - MethodInfo getSetMemberValueDelegateWithTypeGenericMi = typeof(ReflectionXmlSerializationReaderHelper).GetMethod("GetSetMemberValueDelegateWithType", BindingFlags.Static | BindingFlags.Public)!; - MethodInfo getSetMemberValueDelegateWithTypeMi = getSetMemberValueDelegateWithTypeGenericMi.MakeGenericMethod(o.GetType(), memberType); - var getSetMemberValueDelegateWithType = (Func)getSetMemberValueDelegateWithTypeMi.CreateDelegate(typeof(Func)); - result = getSetMemberValueDelegateWithType(memberInfo); - s_setMemberValueDelegateCache.TryAdd(typeMemberNameTuple, result); + MethodInfo getSetMemberValueDelegateWithTypeGenericMi = typeof(ReflectionXmlSerializationReaderHelper).GetMethod("GetSetMemberValueDelegateWithType", BindingFlags.Static | BindingFlags.Public)!; + MethodInfo getSetMemberValueDelegateWithTypeMi = getSetMemberValueDelegateWithTypeGenericMi.MakeGenericMethod(o.GetType(), memberType); + var getSetMemberValueDelegateWithType = (Func)getSetMemberValueDelegateWithTypeMi.CreateDelegate(typeof(Func)); + result = getSetMemberValueDelegateWithType(memberInfo); + delegateCacheForType[memberName] = result; + } + } } - return result; + return (ReflectionXmlSerializationReaderHelper.SetMemberValueDelegate)result; } private object? GetMemberValue(object o, MemberInfo memberInfo) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs index 46877f900e9028..7ebc4462dfb7a6 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriter.cs @@ -19,6 +19,7 @@ namespace System.Xml.Serialization using System.Xml.Serialization; using System.Xml; using System.Diagnostics.CodeAnalysis; + using System.Runtime.CompilerServices; /// public abstract class XmlSerializationWriter : XmlSerializationGeneratedCode @@ -1465,14 +1466,13 @@ internal static class DynamicAssemblies { private static readonly Hashtable s_nameToAssemblyMap = new Hashtable(); private static readonly Hashtable s_assemblyToNameMap = new Hashtable(); - private static readonly Hashtable s_tableIsTypeDynamic = Hashtable.Synchronized(new Hashtable()); + private static readonly ContextAwareTables s_tableIsTypeDynamic = new ContextAwareTables(); // SxS: This method does not take any resource name and does not expose any resources to the caller. // It's OK to suppress the SxS warning. internal static bool IsTypeDynamic(Type type) { - object? oIsTypeDynamic = s_tableIsTypeDynamic[type]; - if (oIsTypeDynamic == null) + object oIsTypeDynamic = s_tableIsTypeDynamic.GetOrCreateValue(type, () => { Assembly assembly = type.Assembly; bool isTypeDynamic = assembly.IsDynamic /*|| string.IsNullOrEmpty(assembly.Location)*/; @@ -1500,8 +1500,8 @@ internal static bool IsTypeDynamic(Type type) } } } - s_tableIsTypeDynamic[type] = oIsTypeDynamic = isTypeDynamic; - } + return isTypeDynamic; + }); return (bool)oIsTypeDynamic; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs index 15d78f2896ae62..b920b8f64a1cf6 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs @@ -10,6 +10,7 @@ using System.IO; using System.Reflection; using System.Runtime.CompilerServices; +using System.Runtime.Loader; using System.Runtime.Versioning; using System.Security; using System.Text; @@ -161,8 +162,7 @@ private static XmlSerializerNamespaces DefaultNamespaces internal const string TrimSerializationWarning = "Members from serialized types may be trimmed if not referenced directly"; private const string TrimDeserializationWarning = "Members from deserialized types may be trimmed if not referenced directly"; - private static readonly Dictionary> s_xmlSerializerTable = new Dictionary>(); - + private static readonly ContextAwareTables> s_xmlSerializerTable = new ContextAwareTables>(); protected XmlSerializer() { } @@ -194,7 +194,10 @@ public XmlSerializer(XmlTypeMapping xmlTypeMapping) if (xmlTypeMapping == null) throw new ArgumentNullException(nameof(xmlTypeMapping)); - _tempAssembly = GenerateTempAssembly(xmlTypeMapping); + if (Mode != SerializationMode.ReflectionOnly) + { + _tempAssembly = GenerateTempAssembly(xmlTypeMapping); + } _mapping = xmlTypeMapping; } @@ -218,6 +221,12 @@ public XmlSerializer(Type type, string? defaultNamespace) _primitiveType = type; return; } + + if (Mode == SerializationMode.ReflectionOnly) + { + return; + } + _tempAssembly = s_cache[defaultNamespace, type]; if (_tempAssembly == null) { @@ -226,30 +235,28 @@ public XmlSerializer(Type type, string? defaultNamespace) _tempAssembly = s_cache[defaultNamespace, type]; if (_tempAssembly == null) { + XmlSerializerImplementation? contract = null; + Assembly? assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out contract); + if (assembly == null) { - XmlSerializerImplementation? contract = null; - Assembly? assembly = TempAssembly.LoadGeneratedAssembly(type, defaultNamespace, out contract); - if (assembly == null) - { - if (Mode == SerializationMode.PreGenOnly) - { - AssemblyName name = type.Assembly.GetName(); - var serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace); - throw new FileLoadException(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName)); - } - - // need to reflect and generate new serialization assembly - XmlReflectionImporter importer = new XmlReflectionImporter(defaultNamespace); - _mapping = importer.ImportTypeMapping(type, null, defaultNamespace); - _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace)!; - } - else + if (Mode == SerializationMode.PreGenOnly) { - // we found the pre-generated assembly, now make sure that the assembly has the right serializer - // try to avoid the reflection step, need to get ElementName, namespace and the Key form the type - _mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace); - _tempAssembly = new TempAssembly(new XmlMapping[] { _mapping }, assembly, contract); + AssemblyName name = type.Assembly.GetName(); + var serializerName = Compiler.GetTempAssemblyName(name, defaultNamespace); + throw new FileLoadException(SR.Format(SR.FailLoadAssemblyUnderPregenMode, serializerName)); } + + // need to reflect and generate new serialization assembly + XmlReflectionImporter importer = new XmlReflectionImporter(defaultNamespace); + _mapping = importer.ImportTypeMapping(type, null, defaultNamespace); + _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace)!; + } + else + { + // we found the pre-generated assembly, now make sure that the assembly has the right serializer + // try to avoid the reflection step, need to get ElementName, namespace and the Key form the type + _mapping = XmlReflectionImporter.GetTopLevelMapping(type, defaultNamespace); + _tempAssembly = new TempAssembly(new XmlMapping[] { _mapping }, assembly, contract); } } s_cache.Add(defaultNamespace, type, _tempAssembly); @@ -270,7 +277,10 @@ public XmlSerializer(Type type, XmlAttributeOverrides? overrides, Type[]? extraT DefaultNamespace = defaultNamespace; _rootType = type; _mapping = GenerateXmlTypeMapping(type, overrides, extraTypes, root, defaultNamespace); - _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace, location); + if (Mode != SerializationMode.ReflectionOnly) + { + _tempAssembly = GenerateTempAssembly(_mapping, type, defaultNamespace, location); + } } [RequiresUnreferencedCode("calls ImportTypeMapping")] @@ -391,7 +401,9 @@ public void Serialize(XmlWriter xmlWriter, object? o, XmlSerializerNamespaces? n } } else + { _tempAssembly.InvokeWriter(_mapping, xmlWriter, o, namespaces == null || namespaces.Count == 0 ? DefaultNamespaces : namespaces, encodingStyle, id); + } } catch (Exception? e) { @@ -530,6 +542,14 @@ public virtual bool CanDeserialize(XmlReader xmlReader) TypeDesc typeDesc = (TypeDesc)TypeScope.PrimtiveTypes[_primitiveType]!; return xmlReader.IsStartElement(typeDesc.DataType!.Name!, string.Empty); } + else if (ShouldUseReflectionBasedSerialization(_mapping) || _isReflectionBasedSerializer) + { + // If we should use reflection, we will try to do reflection-based deserialization, without fallback. + // Don't check xmlReader.IsStartElement to avoid having to duplicate SOAP deserialization logic here. + // It is better to return an incorrect 'true', which will throw during Deserialize than to return an + // incorrect 'false', and the caller won't even try to Deserialize when it would succeed. + return true; + } else if (_tempAssembly != null) { return _tempAssembly.CanRead(_mapping, xmlReader); @@ -609,7 +629,10 @@ public static XmlSerializer[] FromMappings(XmlMapping[]? mappings, Type? type) { XmlSerializer[] serializers = new XmlSerializer[mappings.Length]; for (int i = 0; i < serializers.Length; i++) + { serializers[i] = (XmlSerializer)contract!.TypedSerializers[mappings[i].Key!]!; + TempAssembly.VerifyLoadContext(serializers[i]._rootType, type!.Assembly); + } return serializers; } } @@ -676,16 +699,9 @@ internal static bool GenerateSerializer(Type[]? types, XmlMapping[] mappings, St private static XmlSerializer[] GetSerializersFromCache(XmlMapping[] mappings, Type type) { XmlSerializer?[] serializers = new XmlSerializer?[mappings.Length]; - Dictionary? typedMappingTable = null; - lock (s_xmlSerializerTable) - { - if (!s_xmlSerializerTable.TryGetValue(type, out typedMappingTable)) - { - typedMappingTable = new Dictionary(); - s_xmlSerializerTable[type] = typedMappingTable; - } - } + + typedMappingTable = s_xmlSerializerTable.GetOrCreateValue(type, () => new Dictionary()); lock (typedMappingTable) { diff --git a/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj b/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj index d7a0e73f68f5b8..181be44826a6a6 100644 --- a/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj +++ b/src/libraries/System.Private.Xml/tests/TrimmingTests/System.Private.Xml.TrimmingTests.proj @@ -4,6 +4,8 @@ + diff --git a/src/libraries/System.Private.Xml/tests/TrimmingTests/XmlSerializer.Deserialize.SealerOpt.cs b/src/libraries/System.Private.Xml/tests/TrimmingTests/XmlSerializer.Deserialize.SealerOpt.cs new file mode 100644 index 00000000000000..11a5b5e91827f4 --- /dev/null +++ b/src/libraries/System.Private.Xml/tests/TrimmingTests/XmlSerializer.Deserialize.SealerOpt.cs @@ -0,0 +1,48 @@ +// 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.IO; +using System.Reflection; + +namespace System.Xml.Serialization.TrimmingTests +{ + /// + /// Tests that using XmlSerializer with linker option '--enable-opt sealer' works + /// when IsDynamicCodeSupported==false. + /// + internal class Program + { + // Preserve these types until XmlSerializer is fully trim-safe. + // see https://github.com/dotnet/runtime/issues/44768 + [DynamicDependency(DynamicallyAccessedMemberTypes.All, typeof(Response))] + public static int Main() + { + // simulate IsDynamicCodeSupported==false by setting the SerializationMode to ReflectionOnly + const int ReflectionOnly = 1; + typeof(XmlSerializer).GetField("s_mode", BindingFlags.NonPublic | BindingFlags.Static) + .SetValue(null, ReflectionOnly); + + using StringReader stringReader = new StringReader(@" + + "); + + Response obj = (Response)new XmlSerializer(typeof(Response)).Deserialize(stringReader); + if (obj.DataType == "Data") + { + return 100; + } + + return -1; + } + } + + [Serializable] + [XmlType(AnonymousType = true)] + [XmlRoot(Namespace = "", IsNullable = false)] + public class Response + { + [XmlAttribute] + public string DataType { get; set; } + } +} diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj b/src/libraries/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj index 53abcbd3957022..d7d1f3af3bb87f 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/ReflectionOnly/System.Xml.XmlSerializer.ReflectionOnly.Tests.csproj @@ -3,9 +3,13 @@ $(DefineConstants);ReflectionOnly $(NetCoreAppCurrent) + + + + - + diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj b/src/libraries/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj index dbc8447b87c1cb..7818cd132825c4 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj +++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/System.Xml.XmlSerializer.Tests.csproj @@ -2,10 +2,14 @@ $(NetCoreAppCurrent) + + + + - + diff --git a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs index c918520a19c8ff..9fefff2137faa5 100644 --- a/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs +++ b/src/libraries/System.Private.Xml/tests/XmlSerializer/XmlSerializerTests.cs @@ -8,6 +8,8 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Loader; using System.Text; using System.Threading; using System.Xml; @@ -1960,6 +1962,52 @@ public static void Xml_TypeWithSpecialCharacterInStringMember() Assert.Equal(x.Name, y.Name); } + [Fact] +#if XMLSERIALIZERGENERATORTESTS + // Lack of AssemblyDependencyResolver results in assemblies that are not loaded by path to get + // loaded in the default ALC, which causes problems for this test. + [SkipOnPlatform(TestPlatforms.Browser, "AssemblyDependencyResolver not supported in wasm")] +#endif + [ActiveIssue("34072", TestRuntimes.Mono)] + public static void Xml_TypeInCollectibleALC() + { + ExecuteAndUnload("SerializableAssembly.dll", "SerializationTypes.SimpleType", out var weakRef); + + for (int i = 0; weakRef.IsAlive && i < 10; i++) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + Assert.True(!weakRef.IsAlive); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void ExecuteAndUnload(string assemblyfile, string typename, out WeakReference wref) + { + var fullPath = Path.GetFullPath(assemblyfile); + var alc = new TestAssemblyLoadContext("XmlSerializerTests", true, fullPath); + wref = new WeakReference(alc); + + // Load assembly by path. By name, and it gets loaded in the default ALC. + var asm = alc.LoadFromAssemblyPath(fullPath); + + // Ensure the type loaded in the intended non-Default ALC + var type = asm.GetType(typename); + Assert.Equal(AssemblyLoadContext.GetLoadContext(type.Assembly), alc); + Assert.NotEqual(alc, AssemblyLoadContext.Default); + + // Round-Trip the instance + XmlSerializer serializer = new XmlSerializer(type); + var obj = Activator.CreateInstance(type); + var rtobj = SerializeAndDeserialize(obj, null, () => serializer, true); + Assert.NotNull(rtobj); + Assert.True(rtobj.Equals(obj)); + Assert.Equal(AssemblyLoadContext.GetLoadContext(rtobj.GetType().Assembly), alc); + + alc.Unload(); + } + + private static readonly string s_defaultNs = "http://tempuri.org/"; private static T RoundTripWithXmlMembersMapping(object requestBodyValue, string memberName, string baseline, bool skipStringCompare = false, string wrapperName = null) { @@ -2080,11 +2128,7 @@ private static Stream GenerateStreamFromString(string s) private static T SerializeAndDeserialize(T value, string baseline, Func serializerFactory = null, bool skipStringCompare = false, XmlSerializerNamespaces xns = null) { - XmlSerializer serializer = new XmlSerializer(typeof(T)); - if (serializerFactory != null) - { - serializer = serializerFactory(); - } + XmlSerializer serializer = (serializerFactory != null) ? serializerFactory() : new XmlSerializer(typeof(T)); using (MemoryStream ms = new MemoryStream()) { diff --git a/src/libraries/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs b/src/libraries/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs index 9c2df4249b3836..0b536e51a9447b 100644 --- a/src/libraries/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit.ILGeneration/tests/CustomAttributeBuilderTests.cs @@ -255,7 +255,6 @@ private static void VerifyCustomAttributeBuilder(CustomAttributeBuilder builder, } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/2383", TestRuntimes.Mono)] public static void Ctor_AllPrimitives() { ConstructorInfo con = typeof(Primitives).GetConstructors()[0]; diff --git a/src/libraries/System.Reflection.Emit/tests/AssemblyBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/AssemblyBuilderTests.cs index fb86151fdfcbc1..d968a6c8491ce7 100644 --- a/src/libraries/System.Reflection.Emit/tests/AssemblyBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/AssemblyBuilderTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using Xunit; @@ -24,6 +25,21 @@ public class IntClassAttribute : Attribute public class AssemblyTests { + // The ECMA replacement key for the Microsoft implementation of the CLR. + private static readonly byte[] TheKey = + { + 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, + 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, + 0x07,0xd1,0xfa,0x57,0xc4,0xae,0xd9,0xf0,0xa3,0x2e,0x84,0xaa,0x0f,0xae,0xfd,0x0d, + 0xe9,0xe8,0xfd,0x6a,0xec,0x8f,0x87,0xfb,0x03,0x76,0x6c,0x83,0x4c,0x99,0x92,0x1e, + 0xb2,0x3b,0xe7,0x9a,0xd9,0xd5,0xdc,0xc1,0xdd,0x9a,0xd2,0x36,0x13,0x21,0x02,0x90, + 0x0b,0x72,0x3c,0xf9,0x80,0x95,0x7f,0xc4,0xe1,0x77,0x10,0x8f,0xc6,0x07,0x77,0x4f, + 0x29,0xe8,0x32,0x0e,0x92,0xea,0x05,0xec,0xe4,0xe8,0x21,0xc0,0xa5,0xef,0xe8,0xf1, + 0x64,0x5c,0x4c,0x0c,0x93,0xc1,0xab,0x99,0x28,0x5d,0x62,0x2c,0xaa,0x65,0x2c,0x1d, + 0xfa,0xd6,0x3d,0x74,0x5d,0x6f,0x2d,0xe5,0xf1,0x7e,0x5e,0xaf,0x0f,0xc4,0x96,0x3d, + 0x26,0x1c,0x8a,0x12,0x43,0x65,0x18,0x20,0x6d,0xc0,0x93,0x34,0x4d,0x5a,0xd2,0x93 + }; + public static IEnumerable DefineDynamicAssembly_TestData() { foreach (AssemblyBuilderAccess access in new AssemblyBuilderAccess[] { AssemblyBuilderAccess.Run, AssemblyBuilderAccess.RunAndCollect }) @@ -32,11 +48,15 @@ public static IEnumerable DefineDynamicAssembly_TestData() yield return new object[] { new AssemblyName("testname") { Version = new Version(1, 2, 3, 4) }, access }; yield return new object[] { new AssemblyName("class") { Version = new Version(0, 0, 0, 0) }, access }; yield return new object[] { new AssemblyName("\uD800\uDC00") { Version = new Version(0, 0, 0, 0) }, access }; + + AssemblyName testPublicKey = new AssemblyName("TestPublicKey") { Version = new Version(0, 0, 0, 0) }; + testPublicKey.CultureInfo = CultureInfo.InvariantCulture; + testPublicKey.SetPublicKey(TheKey); + yield return new object[] { testPublicKey, access }; } } [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)] [MemberData(nameof(DefineDynamicAssembly_TestData))] public void DefineDynamicAssembly_AssemblyName_AssemblyBuilderAccess(AssemblyName name, AssemblyBuilderAccess access) { @@ -57,7 +77,6 @@ public static IEnumerable DefineDynamicAssembly_CustomAttributes_TestD } [Theory] - [ActiveIssue("https://github.com/dotnet/runtime/issues/2389", TestRuntimes.Mono)] [MemberData(nameof(DefineDynamicAssembly_CustomAttributes_TestData))] public void DefineDynamicAssembly_AssemblyName_AssemblyBuilderAccess_CustomAttributeBuilder(AssemblyName name, AssemblyBuilderAccess access, IEnumerable attributes) { diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj index 4b183a58768914..75258d65b0e081 100644 --- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj +++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj @@ -6,6 +6,8 @@ $(NetCoreAppCurrent);netstandard2.0;net461 enable true + true + 1 This packages provides a low-level .NET (ECMA-335) metadata reader and writer. It's geared for performance and is the ideal choice for building higher-level libraries that intend to provide their own object model, such as compilers. Commonly Used Types: diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs index 33bd80dec21f75..1762b12d928ba0 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs @@ -121,7 +121,7 @@ public ManagedTextSection( public const int MappedFieldDataAlignment = 8; - public int CalculateOffsetToMappedFieldDataStream() + internal int CalculateOffsetToMappedFieldDataStreamUnaligned() { int result = ComputeOffsetToImportTable(); @@ -135,6 +135,16 @@ public int CalculateOffsetToMappedFieldDataStream() return result; } + public int CalculateOffsetToMappedFieldDataStream() + { + int result = CalculateOffsetToMappedFieldDataStreamUnaligned(); + if (MappedFieldDataSize != 0) + { + result = BitArithmetic.Align(result, MappedFieldDataAlignment); + } + return result; + } + internal int ComputeOffsetToDebugDirectory() { Debug.Assert(MetadataSize % 4 == 0); @@ -185,7 +195,7 @@ public int GetEntryPointAddress(int rva) { // TODO: constants return RequiresStartupStub ? - rva + CalculateOffsetToMappedFieldDataStream() - (Is32Bit ? 6 : 10) : + rva + CalculateOffsetToMappedFieldDataStreamUnaligned() - (Is32Bit ? 6 : 10) : 0; } @@ -293,6 +303,8 @@ public void Serialize( // mapped field data: if (mappedFieldDataBuilderOpt != null) { + if (mappedFieldDataBuilderOpt.Count != 0) + builder.Align(MappedFieldDataAlignment); builder.LinkSuffix(mappedFieldDataBuilderOpt); } diff --git a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs index 763e26dbc1811c..c3dab37bbd3590 100644 --- a/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs +++ b/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs @@ -64,7 +64,8 @@ private static void WritePEImage( Blob mvidFixup = default(Blob), byte[] privateKeyOpt = null, bool publicSigned = false, - Machine machine = 0) + Machine machine = 0, + BlobBuilder? mappedFieldData = null) { var peHeaderBuilder = new PEHeaderBuilder(imageCharacteristics: entryPointHandle.IsNil ? Characteristics.Dll : Characteristics.ExecutableImage, machine: machine); @@ -75,7 +76,8 @@ private static void WritePEImage( ilBuilder, entryPoint: entryPointHandle, flags: CorFlags.ILOnly | (privateKeyOpt != null || publicSigned ? CorFlags.StrongNameSigned : 0), - deterministicIdProvider: content => s_contentId); + deterministicIdProvider: content => s_contentId, + mappedFieldData: mappedFieldData); var peBlob = new BlobBuilder(); @@ -487,6 +489,98 @@ private static MethodDefinitionHandle ComplexEmit(MetadataBuilder metadata, Blob return default(MethodDefinitionHandle); } + [Theory] // Validate FieldRVA alignment on common machine types + [MemberData(nameof(AllMachineTypes))] + public void FieldRVAAlignmentVerify(Machine machine) + { + using (var peStream = new MemoryStream()) + { + var ilBuilder = new BlobBuilder(); + var mappedRVADataBuilder = new BlobBuilder(); + var metadataBuilder = new MetadataBuilder(); + double validationNumber = 0.100001; + var fieldDef = FieldRVAValidationEmit(metadataBuilder, mappedRVADataBuilder, validationNumber); + + WritePEImage(peStream, metadataBuilder, ilBuilder, default(MethodDefinitionHandle), + mappedFieldData: mappedRVADataBuilder, + machine: machine); + + // Validate FieldRVA is aligned as ManagedPEBuilder.MappedFieldDataAlignemnt + peStream.Position = 0; + using (var peReader = new PEReader(peStream, PEStreamOptions.LeaveOpen)) + { + var mdReader = peReader.GetMetadataReader(); + + // Validate that there is only 1 field rva entry + Assert.Equal(1, mdReader.FieldRvaTable.NumberOfRows); + + // Validate that the RVA is aligned properly (which should be at least an 8 byte alignment + Assert.Equal(0, mdReader.FieldRvaTable.GetRva(1) % ManagedPEBuilder.MappedFieldDataAlignment); + + // Validate that the correct data is at the RVA + var fieldRVAData = peReader.GetSectionData(mdReader.FieldRvaTable.GetRva(1)); + Assert.Equal(validationNumber, fieldRVAData.GetReader().ReadDouble()); + } + + VerifyPE(peStream, machine); + } + } + + private static FieldDefinitionHandle FieldRVAValidationEmit(MetadataBuilder metadata, BlobBuilder mappedRVAData, double doubleToWriteAsData) + { + metadata.AddModule( + 0, + metadata.GetOrAddString("ConsoleApplication.exe"), + metadata.GetOrAddGuid(s_guid), + default(GuidHandle), + default(GuidHandle)); + + metadata.AddAssembly( + metadata.GetOrAddString("ConsoleApplication"), + version: new Version(1, 0, 0, 0), + culture: default(StringHandle), + publicKey: metadata.GetOrAddBlob(ImmutableArray.Create(Misc.KeyPair_PublicKey)), + flags: AssemblyFlags.PublicKey, + hashAlgorithm: AssemblyHashAlgorithm.Sha1); + + var mscorlibAssemblyRef = metadata.AddAssemblyReference( + name: metadata.GetOrAddString("mscorlib"), + version: new Version(4, 0, 0, 0), + culture: default(StringHandle), + publicKeyOrToken: metadata.GetOrAddBlob(ImmutableArray.Create(0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89)), + flags: default(AssemblyFlags), + hashValue: default(BlobHandle)); + + var systemObjectTypeRef = metadata.AddTypeReference( + mscorlibAssemblyRef, + metadata.GetOrAddString("System"), + metadata.GetOrAddString("Object")); + + mappedRVAData.WriteDouble(doubleToWriteAsData); + + var rvaFieldSignature = new BlobBuilder(); + + new BlobEncoder(rvaFieldSignature). + FieldSignature().Double(); + + var fieldRVADef = metadata.AddFieldDefinition( + FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasFieldRVA, + metadata.GetOrAddString("RvaField"), + metadata.GetOrAddBlob(rvaFieldSignature)); + + metadata.AddFieldRelativeVirtualAddress(fieldRVADef, 0); + + metadata.AddTypeDefinition( + TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit, + metadata.GetOrAddString("ConsoleApplication"), + metadata.GetOrAddString("Program"), + systemObjectTypeRef, + fieldList: fieldRVADef, + methodList: MetadataTokens.MethodDefinitionHandle(1)); + + return fieldRVADef; + } + private class TestResourceSectionBuilder : ResourceSectionBuilder { public TestResourceSectionBuilder() diff --git a/src/libraries/System.Reflection/tests/CustomAttributeTests.cs b/src/libraries/System.Reflection/tests/CustomAttributeTests.cs index bb9c928b542203..6b102884c0d2ca 100644 --- a/src/libraries/System.Reflection/tests/CustomAttributeTests.cs +++ b/src/libraries/System.Reflection/tests/CustomAttributeTests.cs @@ -76,5 +76,58 @@ public void AttributeWithDifferentPropertyTypes() Assert.Equal(1, attr.ObjectArray.Length); Assert.Null(attr.StringArray); } + + public class StringValuedAttribute : Attribute + { + public StringValuedAttribute (string s) + { + NamedField = s; + } + public StringValuedAttribute () {} + public string NamedProperty + { + get => NamedField; + set { NamedField = value; } + } + public string NamedField; + } + + internal class ClassWithAttrs + { + [StringValuedAttribute("")] + public void M1() {} + + [StringValuedAttribute(NamedProperty = "")] + public void M2() {} + + [StringValuedAttribute(NamedField = "")] + public void M3() {} + } + + [Fact] + public void StringAttributeValueRefEqualsStringEmpty () { + StringValuedAttribute attr; + attr = typeof (ClassWithAttrs).GetMethod("M1") + .GetCustomAttributes(typeof(StringValuedAttribute), true) + .Cast() + .Single(); + + Assert.Same(string.Empty, attr.NamedField); + + attr = typeof (ClassWithAttrs).GetMethod("M2") + .GetCustomAttributes(typeof(StringValuedAttribute), true) + .Cast() + .Single(); + + Assert.Same(string.Empty, attr.NamedField); + + + attr = typeof (ClassWithAttrs).GetMethod("M3") + .GetCustomAttributes(typeof(StringValuedAttribute), true) + .Cast() + .Single(); + + Assert.Same(string.Empty, attr.NamedField); + } } } diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs index 497017c14e7352..750a0e037493b7 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/FileChangeNotificationSystem.cs @@ -13,6 +13,9 @@ namespace System.Runtime.Caching { #if NET5_0_OR_GREATER [UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("ios")] + [UnsupportedOSPlatform("tvos")] + [SupportedOSPlatform("maccatalyst")] #endif internal sealed class FileChangeNotificationSystem : IFileChangeNotificationSystem { diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs index 9d3cb73564bf40..ecd228c35d5ba4 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/HostFileChangeMonitor.cs @@ -98,7 +98,7 @@ private static void InitFCN() if (fcn == null) { #if NET5_0_OR_GREATER - if (OperatingSystem.IsBrowser()) + if (OperatingSystem.IsBrowser() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()) || OperatingSystem.IsTvOS()) { throw new PlatformNotSupportedException(); } diff --git a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/HostFileChangeMonitorTest.cs b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/HostFileChangeMonitorTest.cs index 6d629139436289..c9d83355d6c1a6 100644 --- a/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/HostFileChangeMonitorTest.cs +++ b/src/libraries/System.Runtime.Caching/tests/System.Runtime.Caching/HostFileChangeMonitorTest.cs @@ -41,7 +41,7 @@ namespace MonoTests.System.Runtime.Caching { - [SkipOnPlatform(TestPlatforms.Browser, "HostFileChangeMonitor is not supported on Browser")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "HostFileChangeMonitor is not supported on Browser/iOS/tvOS")] public class HostFileChangeMonitorTest { [Fact] diff --git a/src/libraries/System.Runtime.Experimental/ref/System.Runtime.Experimental.csproj b/src/libraries/System.Runtime.Experimental/ref/System.Runtime.Experimental.csproj index 0ec6e1e5a1e891..c82e61a3544749 100644 --- a/src/libraries/System.Runtime.Experimental/ref/System.Runtime.Experimental.csproj +++ b/src/libraries/System.Runtime.Experimental/ref/System.Runtime.Experimental.csproj @@ -17,6 +17,7 @@ ref $(DefineConstants);FEATURE_GENERIC_MATH true + 1 Exposes new experimental APIs from System.Runtime $(MSBuildProjectName) @@ -32,7 +33,7 @@ <_FileVersionMin>$(FileVersion.Split('.')[1]) <_FileVersionBld>$(FileVersion.Split('.')[2]) <_FileVersionRev>$(FileVersion.Split('.')[3]) - $(_FileVersionMaj).$(_FileVersionMin).$([MSBuild]::Add($(_FileVersionBld), 100)).$(_FileVersionRev) + $(_FileVersionMaj).$([MSBuild]::Add($(_FileVersionMin), 100)).$(_FileVersionBld).$(_FileVersionRev) diff --git a/src/libraries/System.Runtime.Experimental/tests/System.Runtime.Experimental.Tests.csproj b/src/libraries/System.Runtime.Experimental/tests/System.Runtime.Experimental.Tests.csproj index 0001351ba031ab..d8ed841331b0f3 100644 --- a/src/libraries/System.Runtime.Experimental/tests/System.Runtime.Experimental.Tests.csproj +++ b/src/libraries/System.Runtime.Experimental/tests/System.Runtime.Experimental.Tests.csproj @@ -16,11 +16,14 @@ + + + @@ -29,18 +32,22 @@ + + + + diff --git a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs index e9fe758b834f7b..8c9e00887b1ad3 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/AppDomainTests.cs @@ -379,7 +379,7 @@ public void ReflectionOnlyGetAssemblies() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "Throws PNSE")] + [SkipOnPlatform(TestPlatforms.Browser | TestPlatforms.iOS | TestPlatforms.tvOS, "Throws PNSE")] public void MonitoringIsEnabled() { Assert.True(AppDomain.MonitoringIsEnabled); diff --git a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs index f019b1eb11a02f..8c6fc1a78d47bf 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs @@ -96,6 +96,7 @@ public void ProcessPath_Idempotent() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "Throws PNSE")] public void ProcessPath_MatchesExpectedValue() { string expectedProcessPath = PlatformDetection.IsBrowser ? null : Process.GetCurrentProcess().MainModule.FileName; @@ -235,7 +236,7 @@ public void Version_Valid() [Fact] public void WorkingSet_Valid() { - if (PlatformDetection.IsBrowser) + if (PlatformDetection.IsBrowser || (PlatformDetection.IsiOS && !PlatformDetection.IsMacCatalyst) || PlatformDetection.IstvOS) Assert.Equal(0, Environment.WorkingSet); else Assert.True(Environment.WorkingSet > 0, "Expected positive WorkingSet value"); @@ -330,6 +331,13 @@ public void FailFast_ExceptionStackTrace_InnerException() } } + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix | TestPlatforms.Browser)] + public void GetFolderPath_Unix_PersonalExists() + { + Assert.True(Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Personal))); + } + [Fact] [PlatformSpecific(TestPlatforms.AnyUnix | TestPlatforms.Browser)] // Tests OS-specific environment public void GetFolderPath_Unix_PersonalIsHomeAndUserProfile() @@ -339,6 +347,7 @@ public void GetFolderPath_Unix_PersonalIsHomeAndUserProfile() Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.Personal)); Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); } + Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)); } diff --git a/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs b/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs index 40fea32233194e..3a7e5aaa60f25e 100644 --- a/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs +++ b/src/libraries/System.Runtime.Extensions/tests/System/OperatingSystemTests.cs @@ -102,11 +102,9 @@ public static void IsOSPlatformVersionAtLeast_InvalidArgs_Throws() public static void TestIsOSVersionAtLeast_Android_21() => Assert.True(OperatingSystem.IsAndroidVersionAtLeast(21)); // 21 is our min supported version [Fact, PlatformSpecific(TestPlatforms.iOS)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56084", TestPlatforms.MacCatalyst)] public static void TestIsOSPlatform_IOS() => TestIsOSPlatform("iOS", OperatingSystem.IsIOS); [Fact, PlatformSpecific(TestPlatforms.iOS)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56084", TestPlatforms.MacCatalyst)] public static void TestIsOSVersionAtLeast_IOS() => TestIsOSVersionAtLeast("iOS"); [Fact, PlatformSpecific(TestPlatforms.OSX)] @@ -129,11 +127,9 @@ public static void OSX_Is_Treated_as_macOS() } [Fact, PlatformSpecific(TestPlatforms.MacCatalyst)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56084", TestPlatforms.MacCatalyst)] public static void TestIsOSPlatform_MacCatalyst() => TestIsOSPlatform("MacCatalyst", OperatingSystem.IsMacCatalyst); [Fact, PlatformSpecific(TestPlatforms.MacCatalyst)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56084", TestPlatforms.MacCatalyst)] public static void TestIsOSVersionAtLeast_MacCatalyst() => TestIsOSVersionAtLeast("MacCatalyst"); [Fact, PlatformSpecific(TestPlatforms.MacCatalyst)] @@ -147,7 +143,6 @@ public static void MacCatalyst_Is_Also_iOS() } [Fact, PlatformSpecific(TestPlatforms.iOS)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/56084", TestPlatforms.MacCatalyst)] public static void IOS_Is_Not_Also_MacCatalyst() { Assert.False(OperatingSystem.IsOSPlatform("MacCatalyst")); @@ -172,6 +167,12 @@ private static void TestIsOSPlatform(string currentOSName, Func currentOSC { bool expected = currentOSName.Equals(platformName, StringComparison.OrdinalIgnoreCase); + // MacCatalyst is a special case since it also returns true for iOS + if (currentOSName == "MacCatalyst" && platformName == "iOS") + { + expected = true; + } + Assert.Equal(expected, OperatingSystem.IsOSPlatform(platformName)); Assert.Equal(expected, OperatingSystem.IsOSPlatform(platformName.ToUpper())); Assert.Equal(expected, OperatingSystem.IsOSPlatform(platformName.ToLower())); @@ -186,14 +187,32 @@ private static void TestIsOSPlatform(string currentOSName, Func currentOSC OperatingSystem.IsFreeBSD(), OperatingSystem.IsAndroid(), OperatingSystem.IsIOS(), - OperatingSystem.IsMacOS(), OperatingSystem.IsMacCatalyst(), + OperatingSystem.IsMacOS(), OperatingSystem.IsTvOS(), OperatingSystem.IsWatchOS(), OperatingSystem.IsWindows() }; - Assert.Single(allResults, true); + // MacCatalyst is a special case since it also returns true for iOS + if (currentOSName == "MacCatalyst") + { + Assert.Equal(10, allResults.Length); + Assert.False(allResults[0]); // IsBrowser() + Assert.False(allResults[1]); // IsLinux() + Assert.False(allResults[2]); // IsFreeBSD() + Assert.False(allResults[3]); // IsAndroid() + Assert.True(allResults[4]); // IsIOS() + Assert.True(allResults[5]); // IsMacCatalyst() + Assert.False(allResults[6]); // IsMacOS() + Assert.False(allResults[7]); // IsTvOS() + Assert.False(allResults[8]); // IsWatchOS() + Assert.False(allResults[9]); // IsWindows() + } + else + { + Assert.Single(allResults, true); + } } private static void TestIsOSVersionAtLeast(string currentOSName) @@ -202,13 +221,19 @@ private static void TestIsOSVersionAtLeast(string currentOSName) { bool isCurrentOS = currentOSName.Equals(platformName, StringComparison.OrdinalIgnoreCase); + // MacCatalyst is a special case since it also returns true for iOS + if (currentOSName == "MacCatalyst" && platformName == "iOS") + { + isCurrentOS = true; + } + AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName, major, minor, build, revision)); AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName.ToLower(), major, minor, build, revision)); AssertVersionChecks(isCurrentOS, (major, minor, build, revision) => OperatingSystem.IsOSPlatformVersionAtLeast(platformName.ToUpper(), major, minor, build, revision)); } AssertVersionChecks(currentOSName.Equals("Android", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsAndroidVersionAtLeast); - AssertVersionChecks(currentOSName.Equals("iOS", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsIOSVersionAtLeast); + AssertVersionChecks(currentOSName == "MacCatalyst" || currentOSName.Equals("iOS", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsIOSVersionAtLeast); AssertVersionChecks(currentOSName.Equals("macOS", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsMacOSVersionAtLeast); AssertVersionChecks(currentOSName.Equals("MacCatalyst", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsMacCatalystVersionAtLeast); AssertVersionChecks(currentOSName.Equals("tvOS", StringComparison.OrdinalIgnoreCase), OperatingSystem.IsTvOSVersionAtLeast); diff --git a/src/libraries/System.Runtime.InteropServices.NFloat.Internal/Directory.Build.props b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/Directory.Build.props new file mode 100644 index 00000000000000..a2b7f43d8786fd --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/Directory.Build.props @@ -0,0 +1,9 @@ + + + + + false + Microsoft + true + + diff --git a/src/libraries/System.Runtime.InteropServices.NFloat.Internal/System.Runtime.InteropServices.NFloat.Internal.sln b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/System.Runtime.InteropServices.NFloat.Internal.sln new file mode 100644 index 00000000000000..a74a031810bfd2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/System.Runtime.InteropServices.NFloat.Internal.sln @@ -0,0 +1,198 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{94B59BA0-491F-4B59-ADFF-A057EC3EC835}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\ref\System.Runtime.CompilerServices.Unsafe.csproj", "{5BB5F99F-1052-4EB4-B12E-7863805661F3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\src\System.Runtime.CompilerServices.Unsafe.ilproj", "{04BA3E3C-6979-4792-B19E-C797AD607F42}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.NFloat.Internal", "ref\System.Runtime.InteropServices.NFloat.Internal.csproj", "{8671F164-F78C-44FA-93B7-A310F67890FE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.NFloat.Internal", "src\System.Runtime.InteropServices.NFloat.Internal.csproj", "{4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.ComDisabled.Tests", "tests\ComDisabled\System.Runtime.InteropServices.ComDisabled.Tests.csproj", "{6D2197E6-D3DF-43AE-9BEE-3573018639F9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.NFloat.Internal.Tests", "tests\System.Runtime.InteropServices.NFloat.Internal.Tests.csproj", "{E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{FB99AC59-1744-4F12-A4B0-0D54FCA048BF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B1678CCD-95C8-4419-B9F9-14A03061BE4B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{D893B9AA-57C5-49E3-97B1-12CC62D84307}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x64.ActiveCfg = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x64.Build.0 = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x86.ActiveCfg = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x86.Build.0 = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|Any CPU.Build.0 = Release|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x64.ActiveCfg = Release|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x64.Build.0 = Release|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x86.ActiveCfg = Release|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x86.Build.0 = Release|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|Any CPU.Build.0 = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x64.ActiveCfg = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x64.Build.0 = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x86.ActiveCfg = Debug|Any CPU + {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x86.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x64.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x64.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Debug|x86.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|Any CPU.Build.0 = Release|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x64.ActiveCfg = Release|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x64.Build.0 = Release|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.ActiveCfg = Release|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Release|x86.Build.0 = Release|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x86.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x86.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|Any CPU.Build.0 = Release|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x64.ActiveCfg = Release|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x64.Build.0 = Release|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.ActiveCfg = Release|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Release|x86.Build.0 = Release|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|Any CPU.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x64.Build.0 = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.ActiveCfg = Debug|Any CPU + {8671F164-F78C-44FA-93B7-A310F67890FE}.Checked|x86.Build.0 = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x64.ActiveCfg = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x64.Build.0 = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x86.ActiveCfg = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x86.Build.0 = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|Any CPU.Build.0 = Release|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x64.ActiveCfg = Release|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x64.Build.0 = Release|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x86.ActiveCfg = Release|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x86.Build.0 = Release|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|Any CPU.Build.0 = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x64.ActiveCfg = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x64.Build.0 = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x86.ActiveCfg = Debug|Any CPU + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x86.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x64.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x64.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x86.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Debug|x86.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|Any CPU.Build.0 = Release|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x64.ActiveCfg = Release|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x64.Build.0 = Release|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.ActiveCfg = Release|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Release|x86.Build.0 = Release|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|Any CPU.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x64.Build.0 = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.ActiveCfg = Debug|Any CPU + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA}.Checked|x86.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x64.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Debug|x86.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|Any CPU.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x64.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.ActiveCfg = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Release|x86.Build.0 = Release|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|Any CPU.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.Build.0 = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.ActiveCfg = Debug|Any CPU + {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.Build.0 = Debug|Any CPU + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.ActiveCfg = Debug|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|Any CPU.Build.0 = Debug|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x64.ActiveCfg = Debug|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x64.Build.0 = Debug|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x86.ActiveCfg = Debug|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Debug|x86.Build.0 = Debug|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|Any CPU.ActiveCfg = Release|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|Any CPU.Build.0 = Release|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x64.ActiveCfg = Release|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x64.Build.0 = Release|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.ActiveCfg = Release|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Release|x86.Build.0 = Release|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|Any CPU.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.ActiveCfg = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x64.Build.0 = Checked|x64 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.ActiveCfg = Checked|x86 + {94B59BA0-491F-4B59-ADFF-A057EC3EC835}.Checked|x86.Build.0 = Checked|x86 + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Debug|x64.ActiveCfg = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Debug|x64.Build.0 = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Debug|x86.ActiveCfg = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Debug|x86.Build.0 = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Release|Any CPU.Build.0 = Release|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Release|x64.ActiveCfg = Release|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Release|x64.Build.0 = Release|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Release|x86.ActiveCfg = Release|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Release|x86.Build.0 = Release|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Checked|Any CPU.Build.0 = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Checked|x64.ActiveCfg = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Checked|x64.Build.0 = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Checked|x86.ActiveCfg = Debug|Any CPU + {5BB5F99F-1052-4EB4-B12E-7863805661F3}.Checked|x86.Build.0 = Debug|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {6D2197E6-D3DF-43AE-9BEE-3573018639F9} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} + {04BA3E3C-6979-4792-B19E-C797AD607F42} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} + {94B59BA0-491F-4B59-ADFF-A057EC3EC835} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} + {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + {5BB5F99F-1052-4EB4-B12E-7863805661F3} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D4031401-FEB5-4CCF-91C1-38F5646B2BFD} + EndGlobalSection +EndGlobal diff --git a/src/libraries/System.Runtime.InteropServices.NFloat.Internal/ref/System.Runtime.InteropServices.NFloat.Internal.csproj b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/ref/System.Runtime.InteropServices.NFloat.Internal.csproj new file mode 100644 index 00000000000000..144688b2bf26d4 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/ref/System.Runtime.InteropServices.NFloat.Internal.csproj @@ -0,0 +1,44 @@ + + + System.Runtime.InteropServices + true + + + $(NoWarn);0809;0618;CS8614;CS8765;CS3015;NU5131 + true + $(NetCoreAppCurrent) + enable + + + + ref + $(DefineConstants);FEATURE_NFLOAT + true + 1 + true + Exposes additional NFloat APIs for Xamarin/Maui APIs from System.Runtime.InteropServices + $(MSBuildProjectName) + + true + + + + + + + + + + + + <_FileVersionMaj>$(FileVersion.Split('.')[0]) + <_FileVersionMin>$(FileVersion.Split('.')[1]) + <_FileVersionBld>$(FileVersion.Split('.')[2]) + <_FileVersionRev>$(FileVersion.Split('.')[3]) + $(_FileVersionMaj).$([MSBuild]::Add($(_FileVersionMin), 100)).$(_FileVersionBld).$(_FileVersionRev) + + + diff --git a/src/libraries/System.Runtime.InteropServices.NFloat.Internal/src/System.Runtime.InteropServices.NFloat.Internal.proj b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/src/System.Runtime.InteropServices.NFloat.Internal.proj new file mode 100644 index 00000000000000..304633a1911a7f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/src/System.Runtime.InteropServices.NFloat.Internal.proj @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices.NFloat.Internal/tests/System.Runtime.InteropServices.NFloat.Internal.Tests.csproj b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/tests/System.Runtime.InteropServices.NFloat.Internal.Tests.csproj new file mode 100644 index 00000000000000..a8499d3dde85dd --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices.NFloat.Internal/tests/System.Runtime.InteropServices.NFloat.Internal.Tests.csproj @@ -0,0 +1,19 @@ + + + true + true + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser + true + true + + + $(DefineConstants);FEATURE_NFLOAT + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index 6fa5eb10ea0d4f..e7eb8164ddbdc6 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -157,13 +157,14 @@ public enum ClassInterfaceType AutoDual = 2, } [System.CLSCompliantAttribute(false)] - public readonly struct CLong : IEquatable + public readonly partial struct CLong : System.IEquatable { - public CLong(int value) { } - public CLong(nint value) { } + private readonly int _dummyPrimitive; + public CLong(int value) { throw null; } + public CLong(nint value) { throw null; } public nint Value { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } - public bool Equals(CLong other) { throw null; } + public bool Equals(System.Runtime.InteropServices.CLong other) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } @@ -294,13 +295,14 @@ public sealed partial class ComUnregisterFunctionAttribute : System.Attribute public ComUnregisterFunctionAttribute() { } } [System.CLSCompliantAttribute(false)] - public readonly struct CULong : IEquatable + public readonly partial struct CULong : System.IEquatable { - public CULong(uint value) { } - public CULong(nuint value) { } + private readonly int _dummyPrimitive; + public CULong(uint value) { throw null; } + public CULong(nuint value) { throw null; } public nuint Value { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } - public bool Equals(CULong other) { throw null; } + public bool Equals(System.Runtime.InteropServices.CULong other) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } @@ -782,15 +784,109 @@ public static void Free(void* ptr) { } [System.CLSCompliantAttribute(false)] public static void* Realloc(void* ptr, nuint byteCount) { throw null; } } - public readonly struct NFloat : IEquatable + public readonly partial struct NFloat : System.IEquatable +#if FEATURE_NFLOAT +#pragma warning disable SA1001 + , System.IComparable, + System.IComparable, + System.IFormattable, + System.ISpanFormattable +#pragma warning restore SA1001 +#endif // FEATURE_NFLOAT { - public NFloat(float value) { } - public NFloat(double value) { } + private readonly int _dummyPrimitive; + public NFloat(double value) { throw null; } + public NFloat(float value) { throw null; } public double Value { get { throw null; } } - public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } - public bool Equals(NFloat other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Runtime.InteropServices.NFloat other) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } +#if FEATURE_NFLOAT + public static System.Runtime.InteropServices.NFloat Epsilon { get { throw null; } } + public static System.Runtime.InteropServices.NFloat MaxValue { get { throw null; } } + public static System.Runtime.InteropServices.NFloat MinValue { get { throw null; } } + public static System.Runtime.InteropServices.NFloat NaN { get { throw null; } } + public static System.Runtime.InteropServices.NFloat NegativeInfinity { get { throw null; } } + public static System.Runtime.InteropServices.NFloat PositiveInfinity { get { throw null; } } + public static int Size { get { throw null; } } + public int CompareTo(object? obj) { throw null; } + public int CompareTo(System.Runtime.InteropServices.NFloat other) { throw null; } + public static bool IsFinite(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsInfinity(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNaN(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNegative(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNegativeInfinity(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsNormal(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsPositiveInfinity(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool IsSubnormal(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator +(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator --(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator /(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator ==(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static explicit operator System.Runtime.InteropServices.NFloat (decimal value) { throw null; } + public static explicit operator System.Runtime.InteropServices.NFloat (double value) { throw null; } + public static explicit operator byte (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator char (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator decimal (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator short (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator int (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator long (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator nint (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator sbyte (System.Runtime.InteropServices.NFloat value) { throw null; } + public static explicit operator float (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator ushort (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator uint (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator ulong (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static explicit operator nuint (System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool operator >(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator >=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (byte value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (char value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (short value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (int value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (long value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (nint value) { throw null; } + public static implicit operator double (System.Runtime.InteropServices.NFloat value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (sbyte value) { throw null; } + public static implicit operator System.Runtime.InteropServices.NFloat (float value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (ushort value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (uint value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (ulong value) { throw null; } + [System.CLSCompliantAttribute(false)] + public static implicit operator System.Runtime.InteropServices.NFloat (nuint value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator ++(System.Runtime.InteropServices.NFloat value) { throw null; } + public static bool operator !=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator <(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static bool operator <=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator %(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator *(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator -(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) { throw null; } + public static System.Runtime.InteropServices.NFloat operator -(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat operator +(System.Runtime.InteropServices.NFloat value) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowExponent | System.Globalization.NumberStyles.AllowLeadingSign | System.Globalization.NumberStyles.AllowLeadingWhite | System.Globalization.NumberStyles.AllowThousands | System.Globalization.NumberStyles.AllowTrailingWhite, System.IFormatProvider? provider = null) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s, System.Globalization.NumberStyles style) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } + public static System.Runtime.InteropServices.NFloat Parse(string s, System.IFormatProvider? provider) { throw null; } + public string ToString(System.IFormatProvider? provider) { throw null; } + public string ToString(string? format) { throw null; } + public string ToString(string? format, System.IFormatProvider? provider) { throw null; } + public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Runtime.InteropServices.NFloat result) { throw null; } + public static bool TryParse(System.ReadOnlySpan s, out System.Runtime.InteropServices.NFloat result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Runtime.InteropServices.NFloat result) { throw null; } + public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Runtime.InteropServices.NFloat result) { throw null; } +#endif // FEATURE_NFLOAT } [System.AttributeUsageAttribute(System.AttributeTargets.Parameter, Inherited=false)] public sealed partial class OptionalAttribute : System.Attribute diff --git a/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt b/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt index dd2e06b69c3c29..7f9c02ebeff296 100644 --- a/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt +++ b/src/libraries/System.Runtime.InteropServices/src/MatchingRefApiCompatBaseline.txt @@ -8,4 +8,80 @@ TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationClassContext' TypesMustExist : Type 'System.Runtime.InteropServices.RegistrationConnectionType' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute' does not exist in the reference but it does exist in the implementation. MembersMustExist : Member 'public void System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute..ctor()' does not exist in the reference but it does exist in the implementation. -Total Issues: 9 +CannotRemoveBaseTypeOrInterface : Type 'System.Runtime.InteropServices.NFloat' does not implement interface 'System.IComparable' in the reference but it does in the implementation. +MembersMustExist : Member 'public System.Int32 System.Runtime.InteropServices.NFloat.CompareTo(System.Object)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Int32 System.Runtime.InteropServices.NFloat.CompareTo(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.Epsilon.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsFinite(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsInfinity(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsNaN(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsNegative(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsNegativeInfinity(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsNormal(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsPositiveInfinity(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.IsSubnormal(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.MaxValue.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.MinValue.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.NaN.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.NegativeInfinity.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Addition(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Decrement(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Division(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_Equality(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation.C:\Users\tagoo\.nuget\packages\microsoft.dotnet.apicompat\6.0.0-beta.21614.2\build\Microsoft.DotNet.ApiCompat.targets(145,5): error : MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Explicit(System.Decimal)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Explicit(System.Double)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Byte System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Char System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Decimal System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Int16 System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Int32 System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Int64 System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.IntPtr System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.SByte System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Single System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.UInt16 System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.UInt32 System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.UInt64 System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.UIntPtr System.Runtime.InteropServices.NFloat.op_Explicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_GreaterThan(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_GreaterThanOrEqual(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.Byte)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.Char)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.Int16)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.Int32)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.Int64)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.IntPtr)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Double System.Runtime.InteropServices.NFloat.op_Implicit(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.SByte)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.Single)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.UInt16)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.UInt32)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.UInt64)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Implicit(System.UIntPtr)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Increment(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_Inequality(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_LessThan(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation.C:\Users\tagoo\.nuget\packages\microsoft.dotnet.apicompat\6.0.0-beta.21614.2\build\Microsoft.DotNet.ApiCompat.targets(145,5): error : MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_LessThanOrEqual(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Modulus(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Multiply(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Subtraction(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_UnaryNegation(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_UnaryPlus(System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.Parse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.Parse(System.String)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.Parse(System.String, System.Globalization.NumberStyles)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.Parse(System.String, System.Globalization.NumberStyles, System.IFormatProvider)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.Parse(System.String, System.IFormatProvider)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.PositiveInfinity.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Int32 System.Runtime.InteropServices.NFloat.Size.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.String System.Runtime.InteropServices.NFloat.ToString(System.IFormatProvider)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.String System.Runtime.InteropServices.NFloat.ToString(System.String)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.String System.Runtime.InteropServices.NFloat.ToString(System.String, System.IFormatProvider)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.TryFormat(System.Span, System.Int32, System.ReadOnlySpan, System.IFormatProvider)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.TryParse(System.ReadOnlySpan, System.Globalization.NumberStyles, System.IFormatProvider, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.TryParse(System.ReadOnlySpan, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.TryParse(System.String, System.Globalization.NumberStyles, System.IFormatProvider, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.TryParse(System.String, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_Equality(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Runtime.InteropServices.NFloat System.Runtime.InteropServices.NFloat.op_Explicit(System.Decimal)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_LessThan(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Runtime.InteropServices.NFloat.op_LessThanOrEqual(System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat)' does not exist in the reference but it does exist in the implementation. +Total Issues: 85 diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs index 3781d521678c86..4d1353ffd6546b 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs @@ -34,11 +34,10 @@ public void OffsetOf_ClassWithSequentialLayout_ReturnsExpected() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49872", typeof(PlatformDetection), nameof(PlatformDetection.IsAndroid), nameof(PlatformDetection.Is32BitProcess))] public void OffsetOf_ExplicitLayout_ReturnsExpected() { Type t = typeof(ExplicitLayoutTest); - Assert.Equal(56, Marshal.SizeOf(t)); + Assert.Equal(OperatingSystem.IsAndroid() && RuntimeInformation.ProcessArchitecture == Architecture.X86 ? 52 : 56, Marshal.SizeOf(t)); Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_short1))); Assert.Equal(new IntPtr(2), Marshal.OffsetOf(t, nameof(ExplicitLayoutTest.m_short2))); @@ -107,27 +106,34 @@ public void OffsetOf_ValidField_ReturnsExpected() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/49872", typeof(PlatformDetection), nameof(PlatformDetection.IsAndroid), nameof(PlatformDetection.Is32BitProcess))] public void OffsetOf_Decimal_ReturnsExpected() { Type t = typeof(FieldAlignmentTest_Decimal); - if (OperatingSystem.IsWindows() || (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.Wasm)) + if (OperatingSystem.IsWindows() || (RuntimeInformation.ProcessArchitecture != Architecture.X86)) { Assert.Equal(96, Marshal.SizeOf(t)); } + else if (OperatingSystem.IsAndroid()) + { + Assert.Equal(72, Marshal.SizeOf(t)); + } else { Assert.Equal(88, Marshal.SizeOf(t)); } Assert.Equal(new IntPtr(0), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.b))); - Assert.Equal(new IntPtr(8), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.p))); + Assert.Equal(OperatingSystem.IsAndroid() && RuntimeInformation.ProcessArchitecture == Architecture.X86 ? new IntPtr(4) : new IntPtr(8), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.p))); - if (OperatingSystem.IsWindows() || (RuntimeInformation.ProcessArchitecture != Architecture.X86 && RuntimeInformation.ProcessArchitecture != Architecture.Wasm)) + if (OperatingSystem.IsWindows() || (RuntimeInformation.ProcessArchitecture != Architecture.X86)) { Assert.Equal(new IntPtr(88), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.s))); } + else if (OperatingSystem.IsAndroid()) + { + Assert.Equal(new IntPtr(68), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.s))); + } else { Assert.Equal(new IntPtr(80), Marshal.OffsetOf(t, nameof(FieldAlignmentTest_Decimal.s))); @@ -478,26 +484,26 @@ internal struct FieldAlignmentTest public double m_double2; // 8 bytes public byte m_byte3; // 1 byte public byte m_byte4; // 1 byte - // 6 bytes of padding + // 6 bytes of padding (2 bytes on Linux x86) public decimal m_decimal1; // 16 bytes public char m_char4; // 1 byte - // 7 bytes of padding + // 7 bytes of padding (3 bytes on Linux x86) } struct FieldAlignmentTest_Decimal { public byte b; // 1 byte - // 7 bytes of padding + // 7 bytes of padding (3 bytes on Linux x86) // The largest field in below struct is decimal (16 bytes wide). // However, alignment requirement for the below struct should be only 8 bytes (not 16). // This is because unlike fields of other types well known to mcg (like long, char etc.) // which need to be aligned according to their byte size, decimal is really a struct // with 8 byte alignment requirement. - public FieldAlignmentTest p; // 80 bytes (72 bytes on x86/Unix) + public FieldAlignmentTest p; // 80 bytes (72 bytes on Win x86/Unix) (64 bytes on Linux x86) public short s; // 2 bytes - // 6 bytes of padding + // 6 bytes of padding (2 bytes on Linux x86) } struct FieldAlignmentTest_Guid diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs index f174ab1cb03f62..ea55d5c177c54e 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs @@ -256,6 +256,30 @@ public unsafe void StructureToPtr_OpaqueStruct_In_NonBlittableStructure_Success( Assert.Equal(*opaqueData, *marshaledOpaqueData); } + [Fact] + public void StructureToPtr_Flat_And_Nested_NonBlittableStructure_Success() + { + MarshalAndDestroy(new NonBlittableStruct_Flat + { + del = null, + b = 0x55, + }); + + MarshalAndDestroy(new NonBlittableStruct_Nested + { + s = { del = null }, + b = 0x55, + }); + + static unsafe void MarshalAndDestroy(T value) where T : struct + { + int sizeof_T = Marshal.SizeOf(); + void* ptr = stackalloc byte[sizeof_T]; + Marshal.StructureToPtr(value, (IntPtr)ptr, false); + Marshal.DestroyStructure((IntPtr)ptr); + } + } + public struct StructWithIntField { public int value; @@ -318,5 +342,22 @@ public struct NonBlittableWithOpaque public OpaqueStruct opaque; public string str; } + + public struct NonBlittableStruct_Flat + { + public Delegate del; + public byte b; + } + + public struct NonBlittableStruct_Nested + { + public struct InnerStruct + { + public Delegate del; + } + + public InnerStruct s; + public byte b; + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NFloatTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NFloatTests.cs index c2311afae708d1..b56ee77c890039 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NFloatTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NFloatTests.cs @@ -15,36 +15,36 @@ public class NFloatTests [Fact] public void Ctor_Empty() { - NFloat value = new NFloat(); - Assert.Equal(0, value.Value); + NFloat result = new NFloat(); + Assert.Equal(0, result.Value); } [Fact] public void Ctor_Float() { - NFloat value = new NFloat(42.0f); - Assert.Equal(42.0, value.Value); + NFloat result = new NFloat(42.0f); + Assert.Equal(42.0, result.Value); } [Fact] public void Ctor_Double() { - NFloat value = new NFloat(42.0); - Assert.Equal(42.0, value.Value); + NFloat result = new NFloat(42.0); + Assert.Equal(42.0, result.Value); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is32BitProcess))] public void Ctor_Double_OutOfRange() { - NFloat value = new NFloat(double.MaxValue); - Assert.Equal((double)(float)double.MaxValue, value.Value); + NFloat result = new NFloat(double.MaxValue); + Assert.Equal(float.PositiveInfinity, result.Value); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))] public void Ctor_Double_LargeValue() { - NFloat value = new NFloat(double.MaxValue); - Assert.Equal(double.MaxValue, value.Value); + NFloat result = new NFloat(double.MaxValue); + Assert.Equal(double.MaxValue, result.Value); } public static IEnumerable EqualsData() @@ -83,7 +83,6 @@ public void NaNEqualsTest() [InlineData(0.0f)] [InlineData(4567.0f)] [InlineData(4567.89101f)] - [InlineData(float.NaN)] public static void ToStringTest64(float value) { @@ -116,5 +115,805 @@ public unsafe void Size() #pragma warning restore xUnit2000 Assert.Equal(size, Marshal.SizeOf()); } + +#if FEATURE_NFLOAT + [Fact] + public void Epsilon() + { + NFloat result = NFloat.Epsilon; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.Epsilon, result.Value); + } + else + { + Assert.Equal(float.Epsilon, result.Value); + } + } + + [Fact] + public void MaxValue() + { + NFloat result = NFloat.MaxValue; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.MaxValue, result.Value); + } + else + { + Assert.Equal(float.MaxValue, result.Value); + } + } + + [Fact] + public void MinValue() + { + NFloat result = NFloat.MinValue; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.MinValue, result.Value); + } + else + { + Assert.Equal(float.MinValue, result.Value); + } + } + + [Fact] + public void NaN() + { + NFloat result = NFloat.NaN; + Assert.True(double.IsNaN(result.Value)); + } + + [Fact] + public void NegativeInfinity() + { + NFloat result = NFloat.NegativeInfinity; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.NegativeInfinity, result.Value); + } + else + { + Assert.Equal(float.NegativeInfinity, result.Value); + } + } + + [Fact] + public void PositiveInfinity() + { + NFloat result = NFloat.PositiveInfinity; + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.PositiveInfinity, result.Value); + } + else + { + Assert.Equal(float.PositiveInfinity, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_UnaryPlus(float value) + { + NFloat result = +(new NFloat(value)); + Assert.Equal(+value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_UnaryNegation(float value) + { + NFloat result = -(new NFloat(value)); + Assert.Equal(-value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_Decrement(float value) + { + NFloat result = new NFloat(value); + --result; + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)value - 1, result.Value); + } + else + { + Assert.Equal(value - 1, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public static void op_Increment(float value) + { + NFloat result = new NFloat(value); + ++result; + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)value + 1, result.Value); + } + else + { + Assert.Equal(value + 1, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Addition(float left, float right) + { + NFloat result = new NFloat(left) + new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left + right, result.Value); + } + else + { + Assert.Equal(left + right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Subtraction(float left, float right) + { + NFloat result = new NFloat(left) - new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left - right, result.Value); + } + else + { + Assert.Equal(left - right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Multiply(float left, float right) + { + NFloat result = new NFloat(left) * new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left * right, result.Value); + } + else + { + Assert.Equal(left * right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Division(float left, float right) + { + NFloat result = new NFloat(left) / new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left / right, result.Value); + } + else + { + Assert.Equal(left / right, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f, 3.14f)] + [InlineData(-4567.89101f, 3.14569f)] + [InlineData(0.0f, 3.14f)] + [InlineData(4567.0f, -3.14f)] + [InlineData(4567.89101f, -3.14569f)] + public static void op_Modulus(float left, float right) + { + NFloat result = new NFloat(left) % new NFloat(right); + + if (Environment.Is64BitProcess) + { + Assert.Equal((double)left % right, result.Value); + } + else + { + Assert.Equal(left % right, result.Value); + } + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_Equality(float left, float right) + { + bool result = new NFloat(left) == new NFloat(right); + Assert.Equal(left == right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_Inequality(float left, float right) + { + bool result = new NFloat(left) != new NFloat(right); + Assert.Equal(left != right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_GreaterThan(float left, float right) + { + bool result = new NFloat(left) > new NFloat(right); + Assert.Equal(left > right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_GreaterThanOrEqual(float left, float right) + { + bool result = new NFloat(left) >= new NFloat(right); + Assert.Equal(left >= right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_LessThan(float left, float right) + { + bool result = new NFloat(left) < new NFloat(right); + Assert.Equal(left < right, result); + } + + [Theory] + [InlineData(789.0f, 789.0f)] + [InlineData(789.0f, -789.0f)] + [InlineData(789.0f, 0.0f)] + [InlineData(789.0f, 1000.0f)] + public void op_LessThanOrEqual(float left, float right) + { + bool result = new NFloat(left) <= new NFloat(right); + Assert.Equal(left <= right, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void DoubleToNFloat(float value) + { + NFloat result = (NFloat)(double)value; + + if (Environment.Is64BitProcess) + { + Assert.Equal(value, result.Value); + } + else + { + Assert.Equal((float)value, result.Value); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToByte(float value) + { + byte result = (byte)new NFloat(value); + Assert.Equal((byte)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToChar(float value) + { + char result = (char)new NFloat(value); + Assert.Equal((char)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToDecimal(float value) + { + decimal result = (decimal)new NFloat(value); + + if (Environment.Is64BitProcess) + { + Assert.Equal((decimal)(double)value, result); + } + else + { + Assert.Equal((decimal)value, result); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToInt16(float value) + { + short result = (short)new NFloat(value); + Assert.Equal((short)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToInt32(float value) + { + int result = (int)new NFloat(value); + Assert.Equal((int)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToInt64(float value) + { + long result = (long)new NFloat(value); + Assert.Equal((long)value, result); + } + + [Theory] + [InlineData(-4567.0f, Skip = "https://github.com/dotnet/runtime/issues/64386")] + [InlineData(-4567.89101f, Skip = "https://github.com/dotnet/runtime/issues/64386")] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToIntPtr(float value) + { + nint result = (nint)new NFloat(value); + Assert.Equal((nint)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToSByte(float value) + { + sbyte result = (sbyte)new NFloat(value); + Assert.Equal((sbyte)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToSingle(float value) + { + float result = (float)new NFloat(value); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUInt16(float value) + { + ushort result = (ushort)new NFloat(value); + Assert.Equal((ushort)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUInt32(float value) + { + uint result = (uint)new NFloat(value); + Assert.Equal((uint)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUInt64(float value) + { + ulong result = (ulong)new NFloat(value); + Assert.Equal((ulong)value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToUIntPtr(float value) + { + nuint result = (nuint)new NFloat(value); + Assert.Equal((nuint)value, result); + } + + [Theory] + [InlineData((byte)0)] + [InlineData((byte)5)] + [InlineData((byte)42)] + [InlineData((byte)127)] + [InlineData((byte)255)] + public void ByteToNFloat(byte value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData('A')] + [InlineData('B')] + [InlineData('C')] + [InlineData('D')] + [InlineData('E')] + public void CharToNFloat(char value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((short)-255)] + [InlineData((short)-127)] + [InlineData((short)0)] + [InlineData((short)127)] + [InlineData((short)255)] + public void Int16ToNFloat(short value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData(-255)] + [InlineData(-127)] + [InlineData(0)] + [InlineData(127)] + [InlineData(255)] + public void Int32ToNFloat(int value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((long)-255)] + [InlineData((long)-127)] + [InlineData((long)0)] + [InlineData((long)127)] + [InlineData((long)255)] + public void Int64ToNFloat(long value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((int)-255)] + [InlineData((int)-127)] + [InlineData((int)0)] + [InlineData((int)127)] + [InlineData((int)255)] + public void IntPtrToNFloat(int value) + { + NFloat result = (nint)value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((sbyte)-127)] + [InlineData((sbyte)-63)] + [InlineData((sbyte)0)] + [InlineData((sbyte)63)] + [InlineData((sbyte)127)] + public void SByteToNFloat(sbyte value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void SingleToNFloat(float value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((ushort)0)] + [InlineData((ushort)5)] + [InlineData((ushort)42)] + [InlineData((ushort)127)] + [InlineData((ushort)255)] + public void UInt16ToNFloat(ushort value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((uint)0)] + [InlineData((uint)5)] + [InlineData((uint)42)] + [InlineData((uint)127)] + [InlineData((uint)255)] + public void UInt32ToNFloat(uint value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((ulong)0)] + [InlineData((ulong)5)] + [InlineData((ulong)42)] + [InlineData((ulong)127)] + [InlineData((ulong)255)] + public void UInt64ToNFloat(ulong value) + { + NFloat result = value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData((uint)0)] + [InlineData((uint)5)] + [InlineData((uint)42)] + [InlineData((uint)127)] + [InlineData((uint)255)] + public void UIntPtrToNFloat(uint value) + { + NFloat result = (nuint)value; + Assert.Equal(value, result.Value); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + public void NFloatToDouble(float value) + { + double result = new NFloat(value); + Assert.Equal(value, result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsFinite(float value) + { + bool result = NFloat.IsFinite(value); + Assert.Equal(float.IsFinite(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsInfinity(float value) + { + bool result = NFloat.IsInfinity(value); + Assert.Equal(float.IsInfinity(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNaN(float value) + { + bool result = NFloat.IsNaN(value); + Assert.Equal(float.IsNaN(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNegative(float value) + { + bool result = NFloat.IsNegative(value); + Assert.Equal(float.IsNegative(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNegativeInfinity(float value) + { + bool result = NFloat.IsNegativeInfinity(value); + Assert.Equal(float.IsNegativeInfinity(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsNormal(float value) + { + bool result = NFloat.IsNormal(value); + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.IsNormal(value), result); + } + else + { + Assert.Equal(float.IsNormal(value), result); + } + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsPositiveInfinity(float value) + { + bool result = NFloat.IsPositiveInfinity(value); + Assert.Equal(float.IsPositiveInfinity(value), result); + } + + [Theory] + [InlineData(-4567.0f)] + [InlineData(-4567.89101f)] + [InlineData(0.0f)] + [InlineData(4567.0f)] + [InlineData(4567.89101f)] + [InlineData(float.Epsilon)] + [InlineData(float.NegativeInfinity)] + [InlineData(float.PositiveInfinity)] + [InlineData(float.NaN)] + public void IsSubnormal(float value) + { + bool result = NFloat.IsSubnormal(value); + + if (Environment.Is64BitProcess) + { + Assert.Equal(double.IsSubnormal(value), result); + } + else + { + Assert.Equal(float.IsSubnormal(value), result); + } + } +#endif // FEATURE_NFLOAT } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs index 4b0c9fc01dea3a..f844b4d160a884 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using Xunit; +using System.Diagnostics; +using System.Globalization; using System.Threading; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -57,7 +59,16 @@ public void SignalHandlerCalledForKnownSignals(PosixSignal s) semaphore.Release(); }); - kill(signal); + // Use 'kill' command with signal name to validate the signal pal mapping. + string sigArg = signalStr.StartsWith("SIG") ? signalStr.Substring(3) : signalStr; + using var process = Process.Start(new ProcessStartInfo + { + FileName = "/bin/sh", // Use a shell because not all platforms include a 'kill' executable. + ArgumentList = { "-c", $"kill -s {sigArg} {Environment.ProcessId.ToString()}" } + }); + process.WaitForExit(); + Assert.Equal(0, process.ExitCode); + bool entered = semaphore.Wait(SuccessTimeout); Assert.True(entered); }, s.ToString()).Dispose(); diff --git a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs index 6ad7fc3eb9842b..4391b94b5ccb25 100644 --- a/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs +++ b/src/libraries/System.Runtime.Intrinsics/ref/System.Runtime.Intrinsics.cs @@ -3,7 +3,6 @@ // ------------------------------------------------------------------------------ // Changes to this file must follow the https://aka.ms/api-review process. // ------------------------------------------------------------------------------ -using System.Runtime.Versioning; namespace System.Runtime.Intrinsics { @@ -3371,7 +3370,7 @@ internal X64() { } } [System.CLSCompliantAttribute(false)] - [RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("AvxVnni is in preview.")] public abstract class AvxVnni : System.Runtime.Intrinsics.X86.Avx2 { internal AvxVnni() { } diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate.cs new file mode 100644 index 00000000000000..47bbcd171ad3b4 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate.cs @@ -0,0 +1,12 @@ +// 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.Metadata.ApplyUpdate.Test +{ + public class FirstCallAfterUpdate { + public FirstCallAfterUpdate() {} + public string Method1 (string s) { + return s + " STRING"; + } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate_v1.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate_v1.cs new file mode 100644 index 00000000000000..66d1d336e6baa3 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate_v1.cs @@ -0,0 +1,12 @@ +// 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.Metadata.ApplyUpdate.Test +{ + public class FirstCallAfterUpdate { + public FirstCallAfterUpdate() {} + public string Method1(string s) { + return "NEW " + s; + } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate_v2.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate_v2.cs new file mode 100644 index 00000000000000..9ea687752b8026 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/FirstCallAfterUpdate_v2.cs @@ -0,0 +1,12 @@ +// 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.Metadata.ApplyUpdate.Test +{ + public class FirstCallAfterUpdate { + public FirstCallAfterUpdate() {} + public string Method1(string s) { + return s + "EST STRING"; + } + } +} diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate.csproj new file mode 100644 index 00000000000000..1cd197f92264de --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate.csproj @@ -0,0 +1,12 @@ + + + System.Runtime.Loader.Tests + $(NetCoreAppCurrent) + true + deltascript.json + true + + + + + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/deltascript.json b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/deltascript.json new file mode 100644 index 00000000000000..64d533be6b7560 --- /dev/null +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.FirstCallAfterUpdate/deltascript.json @@ -0,0 +1,7 @@ +{ + "changes": [ + {"document": "FirstCallAfterUpdate.cs", "update": "FirstCallAfterUpdate_v1.cs"}, + {"document": "FirstCallAfterUpdate.cs", "update": "FirstCallAfterUpdate_v2.cs"}, + ] +} + diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index 794ace67148c94..3e240e65caabf8 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -94,6 +94,26 @@ void LambdaCapturesThis() }); } + [ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/54617", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] + void FirstCallAfterUpdate() + { + /* Tests that updating a method that has not been called before works correctly and that + * the JIT/interpreter doesn't have to rely on cached baseline data. */ + ApplyUpdateUtil.TestCase(static () => + { + var assm = typeof (ApplyUpdate.Test.FirstCallAfterUpdate).Assembly; + + var o = new ApplyUpdate.Test.FirstCallAfterUpdate (); + + ApplyUpdateUtil.ApplyUpdate(assm); + ApplyUpdateUtil.ApplyUpdate(assm); + + string r = o.Method1("NEW"); + + Assert.Equal("NEWEST STRING", r); + }); + } [ConditionalFact(typeof(ApplyUpdateUtil), nameof (ApplyUpdateUtil.IsSupported))] [ActiveIssue("https://github.com/dotnet/runtime/issues/52993", TestRuntimes.Mono)] diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj index f893446f21d0e2..8b946a20828d2e 100644 --- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj +++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj @@ -38,6 +38,7 @@ + @@ -54,6 +55,7 @@ + diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index 18374c12c775f2..d27244837a0899 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -2021,10 +2021,14 @@ public static explicit operator decimal(BigInteger value) } NumericsHelpers.DangerousMakeTwosComplement(xd); // Mutates xd - if (xd[^1] == 0) - { - trackSignBit = true; - } + + // For a shift of N x 32 bit, + // We check for a special case where its sign bit could be outside the uint array after 2's complement conversion. + // For example given [0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF], its 2's complement is [0x01, 0x00, 0x00] + // After a 32 bit right shift, it becomes [0x00, 0x00] which is [0x00, 0x00] when converted back. + // The expected result is [0x00, 0x00, 0xFFFFFFFF] (2's complement) or [0x00, 0x00, 0x01] when converted back + // If the 2's component's last element is a 0, we will track the sign externally + trackSignBit = smallShift == 0 && xd[^1] == 0; } int zl = xd.Length - digitShift + (trackSignBit ? 1: 0); @@ -2061,12 +2065,12 @@ stackalloc uint[StackallocUInt32Limit].Slice(0, zl) : } if (negx) { - NumericsHelpers.DangerousMakeTwosComplement(zd); // Mutates zd - + // Set the tracked sign to the last element if (trackSignBit) { - zd[^1] = 1; + zd[^1] = 0xFFFFFFFF; } + NumericsHelpers.DangerousMakeTwosComplement(zd); // Mutates zd } return new BigInteger(zd, zdArray, negx); diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs index 0e7fbf1e30ebab..2f65e779c0430f 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs @@ -63,6 +63,14 @@ public static void RunRightShiftTests() VerifyRightShiftString(Print(tempByteArray2) + Print(tempByteArray1) + "b>>"); } + // RightShift Method - Uint 0xffffffff 0x8000000 ... Large BigIntegers - 32 bit Shift + for (int i = 0; i < s_samples; i++) + { + tempByteArray1 = GetRandomLengthFirstUIntMaxSecondUIntMSBMaxArray(s_random); + tempByteArray2 = new byte[] { (byte)32 }; + VerifyRightShiftString(Print(tempByteArray2) + Print(tempByteArray1) + "b>>"); + } + // RightShift Method - Large BigIntegers - large - Shift for (int i = 0; i < s_samples; i++) { @@ -229,6 +237,15 @@ private static byte[] GetRandomLengthAllOnesUIntByteArray(Random random) array[^1] = 0xFF; return array; } + private static byte[] GetRandomLengthFirstUIntMaxSecondUIntMSBMaxArray(Random random) + { + int gap = random.Next(0, 128); + int byteLength = 4 + gap * 4 + 1; + byte[] array = new byte[byteLength]; + array[^6] = 0x80; + array[^1] = 0xFF; + return array; + } private static string Print(byte[] bytes) { diff --git a/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs b/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs index 87cd3085c99e3f..b8d386a5b71e4d 100644 --- a/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs +++ b/src/libraries/System.Runtime.Serialization.Json/tests/DataContractJsonSerializer.cs @@ -2384,6 +2384,38 @@ public static void DCJS_ExtensionDataObjectTest() } } + [Fact] + public static void DCJS_ExtensionDataObjectTest2() + { + SerializeThenDeserialize(new ContractExtended { Item = new Item { Id = 1, Code = 2 } }); + SerializeThenDeserialize(new ContractExtended { Item = new Item { Id = 1 } }); + } + + private static void SerializeThenDeserialize(ContractExtended extendedData) + { + string extendedContractJson; + using (var memoryStream = new MemoryStream()) + { + new DataContractJsonSerializer(typeof(ContractExtended)).WriteObject(memoryStream, extendedData); + extendedContractJson = Encoding.UTF8.GetString(memoryStream.ToArray()); + } + + ContractGeneric reducedData; + using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(extendedContractJson))) + { + reducedData = (ContractGeneric)new DataContractJsonSerializer(typeof(ContractGeneric)).ReadObject(memoryStream); + } + + string reducedContractJson; + using (var memoryStream = new MemoryStream()) + { + new DataContractJsonSerializer(typeof(ContractGeneric)).WriteObject(memoryStream, reducedData); + reducedContractJson = Encoding.UTF8.GetString(memoryStream.ToArray()); + } + + Assert.Equal(extendedContractJson, reducedContractJson); + } + private static string ConstructorWithRootNameTestHelper(TypeForRootNameTest value, DataContractJsonSerializer serializer) { using (var ms = new MemoryStream()) diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.RuntimeOnly.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.RuntimeOnly.cs index 95d51d43c89197..abe72c65388aab 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.RuntimeOnly.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.RuntimeOnly.cs @@ -4347,6 +4347,29 @@ public NativeJsonTestData(Type type, Func instantiate) public Func Instantiate { get; set; } } +[DataContract] +public class ContractGeneric : IExtensibleDataObject +{ + public ExtensionDataObject ExtensionData { get; set; } +} + +[DataContract(Name = "ContractGeneric")] +public class ContractExtended +{ + [DataMember(Name = "item", Order = 1)] + public Item Item; +} + +[DataContract] +public class Item +{ + [DataMember(Name = "id", Order = 1, EmitDefaultValue = false)] + public long? Id; + + [DataMember(Name = "code", Order = 2, EmitDefaultValue = false)] + public long? Code; +} + public class TypeWithCollectionAndDateTimeOffset { public TypeWithCollectionAndDateTimeOffset() diff --git a/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs b/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs index bc10a370b033cd..747f661129a94a 100644 --- a/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs +++ b/src/libraries/System.Runtime.Serialization.Xml/tests/SerializationTypes.cs @@ -47,6 +47,16 @@ public static bool AreEqual(SimpleType x, SimpleType y) return (x.P1 == y.P1) && (x.P2 == y.P2); } } + + public override bool Equals(object? obj) + { + if (obj is SimpleType st) + return AreEqual(this, st); + + return base.Equals(obj); + } + + public override int GetHashCode() => base.GetHashCode(); } public class TypeWithGetSetArrayMembers diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 5de2f8d1c1605d..17d5d0e7e131a2 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -754,130 +754,130 @@ public static void SetByte(System.Array array, int index, byte value) { } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Byte result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IAdditionOperators.operator +(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.LeadingZeroCount(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.PopCount(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.RotateLeft(byte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.RotateRight(byte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryInteger.TrailingZeroCount(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBinaryNumber.Log2(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator &(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator |(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator ^(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IBitwiseOperators.operator ~(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IDecrementOperators.operator --(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IDivisionOperators.operator /(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IIncrementOperators.operator ++(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IModulusOperators.operator %(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IMultiplyOperators.operator *(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Abs(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Clamp(byte value, byte min, byte max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (byte Quotient, byte Remainder) INumber.DivRem(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Max(byte x, byte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Min(byte x, byte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte INumber.Sign(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IShiftOperators.operator <<(byte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IShiftOperators.operator >>(byte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out byte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte ISubtractionOperators.operator -(byte left, byte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IUnaryNegationOperators.operator -(byte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static byte IUnaryPlusOperators.operator +(byte value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -974,130 +974,130 @@ public CannotUnloadAppDomainException(string? message, System.Exception? innerEx string System.IFormattable.ToString(string? format, IFormatProvider? formatProvider) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IAdditionOperators.operator +(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.LeadingZeroCount(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.PopCount(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.RotateLeft(char value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.RotateRight(char value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryInteger.TrailingZeroCount(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBinaryNumber.Log2(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator &(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator |(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator ^(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IBitwiseOperators.operator ~(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IDecrementOperators.operator --(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IDivisionOperators.operator /(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IIncrementOperators.operator ++(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IModulusOperators.operator %(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IMultiplyOperators.operator *(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Abs(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Clamp(char value, char min, char max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (char Quotient, char Remainder) INumber.DivRem(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Max(char x, char y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Min(char x, char y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char INumber.Sign(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IShiftOperators.operator <<(char value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures, System.Runtime.CompilerServices.SpecialNameAttribute] + [System.Runtime.Versioning.RequiresPreviewFeatures("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview"), System.Runtime.CompilerServices.SpecialNameAttribute] static char IShiftOperators.operator >>(char value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out char result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char ISubtractionOperators.operator -(char left, char right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IUnaryNegationOperators.operator -(char value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static char IUnaryPlusOperators.operator +(char value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -1656,33 +1656,33 @@ public static partial class Convert public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.DateOnly left, System.DateOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.DateOnly result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateOnly ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.DateOnly result) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -1820,44 +1820,44 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IAdditionOperators.operator +(System.DateTime left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.DateTime left, System.DateTime right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.DateTime result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.DateTime result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTime ISubtractionOperators.operator -(System.DateTime left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.DateTime left, System.DateTime right) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -1972,44 +1972,44 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IAdditionOperators.operator +(System.DateTimeOffset left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.DateTimeOffset result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.DateTimeOffset result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.DateTimeOffset ISubtractionOperators.operator -(System.DateTimeOffset left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -2195,103 +2195,103 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Decimal result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IAdditionOperators.operator +(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IDecrementOperators.operator --(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IDivisionOperators.operator /(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IIncrementOperators.operator ++(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IModulusOperators.operator %(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IMultiplyOperators.operator *(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Abs(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Clamp(decimal value, decimal min, decimal max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (decimal Quotient, decimal Remainder) INumber.DivRem(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Max(decimal x, decimal y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Min(decimal x, decimal y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal INumber.Sign(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out decimal result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal ISubtractionOperators.operator -(decimal left, decimal right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IUnaryNegationOperators.operator -(decimal value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static decimal IUnaryPlusOperators.operator +(decimal value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -2407,209 +2407,226 @@ public DivideByZeroException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Double result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.E { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Epsilon { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.NaN { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.NegativeInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.NegativeZero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Pi { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.PositiveInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Tau { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IAdditionOperators.operator +(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBinaryNumber.Log2(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator &(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator |(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator ^(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IBitwiseOperators.operator ~(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IDecrementOperators.operator --(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IDivisionOperators.operator /(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Acos(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Acosh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Asin(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Asinh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Atan(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Atan2(double y, double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Atanh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.BitIncrement(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.BitDecrement(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Cbrt(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Ceiling(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.CopySign(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Cos(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Cosh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Exp(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Floor(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.FusedMultiplyAdd(double left, double right, double addend) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.IEEERemainder(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static TInteger IFloatingPoint.ILogB(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log(double x, double newBase) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log2(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Log10(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.MaxMagnitude(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.MinMagnitude(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Pow(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x, TInteger digits) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Round(double x, TInteger digits, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.ScaleB(double x, TInteger n) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Sin(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Sinh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Sqrt(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Tan(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Tanh(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IFloatingPoint.Truncate(double x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsFinite(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsInfinity(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNaN(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNegative(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNegativeInfinity(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNormal(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsPositiveInfinity(double d) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsSubnormal(double d) { throw null; } + + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IIncrementOperators.operator ++(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IModulusOperators.operator %(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMultiplyOperators.operator *(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Abs(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Clamp(double value, double min, double max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (double Quotient, double Remainder) INumber.DivRem(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Max(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Min(double x, double y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double INumber.Sign(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out double result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double ISubtractionOperators.operator -(double left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IUnaryNegationOperators.operator -(double value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IUnaryPlusOperators.operator +(double value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3045,28 +3062,28 @@ public GopherStyleUriParser() { } bool System.ISpanFormattable.TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider? provider) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.Guid left, System.Guid right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Guid IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.Guid result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Guid ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.Guid result) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3124,209 +3141,226 @@ public GopherStyleUriParser() { } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Half result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.E { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Epsilon { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.NaN { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.NegativeInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.NegativeZero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Pi { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.PositiveInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Tau { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IAdditionOperators.operator +(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBinaryNumber.Log2(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator &(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator |(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator ^(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IBitwiseOperators.operator ~(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IDecrementOperators.operator --(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IDivisionOperators.operator /(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Acos(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Acosh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Asin(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Asinh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Atan(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Atan2(System.Half y, System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Atanh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.BitIncrement(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.BitDecrement(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Cbrt(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Ceiling(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.CopySign(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Cos(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Cosh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Exp(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Floor(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.FusedMultiplyAdd(System.Half left, System.Half right, System.Half addend) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.IEEERemainder(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static TInteger IFloatingPoint.ILogB(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log(System.Half x, System.Half newBase) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log2(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Log10(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.MaxMagnitude(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.MinMagnitude(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Pow(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x, TInteger digits) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Round(System.Half x, TInteger digits, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.ScaleB(System.Half x, TInteger n) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Sin(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Sinh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Sqrt(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Tan(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Tanh(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IFloatingPoint.Truncate(System.Half x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsFinite(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsInfinity(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNaN(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNegative(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNegativeInfinity(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNormal(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsPositiveInfinity(System.Half x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsSubnormal(System.Half x) { throw null; } + + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IIncrementOperators.operator ++(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IModulusOperators.operator %(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IMultiplyOperators.operator *(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Abs(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Clamp(System.Half value, System.Half min, System.Half max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (System.Half Quotient, System.Half Remainder) INumber.DivRem(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Max(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Min(System.Half x, System.Half y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half INumber.Sign(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.Half result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half ISubtractionOperators.operator -(System.Half left, System.Half right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IUnaryNegationOperators.operator -(System.Half value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.Half IUnaryPlusOperators.operator +(System.Half value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3357,24 +3391,24 @@ public partial class HttpStyleUriParser : System.UriParser public HttpStyleUriParser() { } } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IAdditionOperators where TSelf : System.IAdditionOperators { static abstract TResult operator +(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IAdditiveIdentity where TSelf : System.IAdditiveIdentity { static abstract TResult AdditiveIdentity { get; } } -[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] +[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBinaryFloatingPoint : System.IBinaryNumber, System.IFloatingPoint where TSelf : IBinaryFloatingPoint { } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBinaryInteger : System.IBinaryNumber, System.IShiftOperators where TSelf : IBinaryInteger { @@ -3384,14 +3418,14 @@ public partial interface IBinaryInteger : System.IBinaryNumber, Sy static abstract TSelf RotateRight(TSelf value, int rotateAmount); static abstract TSelf TrailingZeroCount(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBinaryNumber : System.IBitwiseOperators, System.INumber where TSelf : IBinaryNumber { static abstract bool IsPow2(TSelf value); static abstract TSelf Log2(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IBitwiseOperators where TSelf : System.IBitwiseOperators { @@ -3400,7 +3434,7 @@ public partial interface IBitwiseOperators static abstract TResult operator ^(TSelf left, TOther right); static abstract TResult operator ~(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IComparisonOperators : System.IComparable, System.IComparable, System.IEqualityOperators where TSelf : IComparisonOperators { @@ -3409,26 +3443,26 @@ public partial interface IComparisonOperators : System.IComparabl static abstract bool operator >(TSelf left, TOther right); static abstract bool operator >=(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IDecrementOperators where TSelf : System.IDecrementOperators { static abstract TSelf operator --(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IDivisionOperators where TSelf : System.IDivisionOperators { static abstract TResult operator /(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IEqualityOperators : IEquatable where TSelf : System.IEqualityOperators { static abstract bool operator ==(TSelf left, TOther right); static abstract bool operator !=(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IFloatingPoint : System.ISignedNumber where TSelf : System.IFloatingPoint { @@ -3486,38 +3520,38 @@ public partial interface IFloatingPoint : System.ISignedNumber static abstract TSelf Tanh(TSelf x); static abstract TSelf Truncate(TSelf x); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IIncrementOperators where TSelf : System.IIncrementOperators { static abstract TSelf operator ++(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IMinMaxValue where TSelf : System.IMinMaxValue { static abstract TSelf MinValue { get; } static abstract TSelf MaxValue { get; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IModulusOperators where TSelf : System.IModulusOperators { static abstract TResult operator %(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IMultiplicativeIdentity where TSelf : System.IMultiplicativeIdentity { static abstract TResult MultiplicativeIdentity { get; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IMultiplyOperators where TSelf : System.IMultiplyOperators { static abstract TResult operator *(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface INumber : System.IAdditionOperators, System.IAdditiveIdentity, System.IComparable, System.IComparable, System.IComparisonOperators, System.IDecrementOperators, System.IDivisionOperators, System.IEquatable, System.IEqualityOperators, System.IFormattable, System.IIncrementOperators, System.IModulusOperators, System.IMultiplicativeIdentity, System.IMultiplyOperators, System.IParseable, System.ISpanFormattable, System.ISpanParseable, System.ISubtractionOperators, System.IUnaryNegationOperators, System.IUnaryPlusOperators where TSelf : System.INumber { @@ -3538,52 +3572,52 @@ public partial interface INumber : System.IAdditionOperators s, System.Globalization.NumberStyles style, IFormatProvider? provider, out TSelf result); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IParseable where TSelf : System.IParseable { static abstract TSelf Parse(string s, System.IFormatProvider? provider); static abstract bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out TSelf result); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IShiftOperators where TSelf : System.IShiftOperators { static abstract TResult operator <<(TSelf value, int shiftAmount); static abstract TResult operator >>(TSelf value, int shiftAmount); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface ISignedNumber : System.INumber, System.IUnaryNegationOperators where TSelf : System.ISignedNumber { static abstract TSelf NegativeOne { get; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface ISpanParseable : System.IParseable where TSelf : System.ISpanParseable { static abstract TSelf Parse(System.ReadOnlySpan s, System.IFormatProvider? provider); static abstract bool TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out TSelf result); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface ISubtractionOperators where TSelf : System.ISubtractionOperators { static abstract TResult operator -(TSelf left, TOther right); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IUnaryNegationOperators where TSelf : System.IUnaryNegationOperators { static abstract TResult operator -(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IUnaryPlusOperators where TSelf : System.IUnaryPlusOperators { static abstract TResult operator +(TSelf value); } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public partial interface IUnsignedNumber : System.INumber where TSelf : IUnsignedNumber { @@ -3737,133 +3771,133 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Int16 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IAdditionOperators.operator +(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.LeadingZeroCount(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.PopCount(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.RotateLeft(short value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.RotateRight(short value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryInteger.TrailingZeroCount(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBinaryNumber.Log2(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator &(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator |(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator ^(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IBitwiseOperators.operator ~(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IDecrementOperators.operator --(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IDivisionOperators.operator /(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IIncrementOperators.operator ++(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IModulusOperators.operator %(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IMultiplyOperators.operator *(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Abs(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Clamp(short value, short min, short max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (short Quotient, short Remainder) INumber.DivRem(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Max(short x, short y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Min(short x, short y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short INumber.Sign(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IShiftOperators.operator <<(short value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IShiftOperators.operator >>(short value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out short result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short ISubtractionOperators.operator -(short left, short right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IUnaryNegationOperators.operator -(short value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static short IUnaryPlusOperators.operator +(short value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -3916,133 +3950,133 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Int32 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IAdditionOperators.operator +(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.LeadingZeroCount(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.PopCount(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.RotateLeft(int value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.RotateRight(int value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryInteger.TrailingZeroCount(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBinaryNumber.Log2(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator &(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator |(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator ^(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IBitwiseOperators.operator ~(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IDecrementOperators.operator --(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IDivisionOperators.operator /(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IIncrementOperators.operator ++(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IModulusOperators.operator %(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IMultiplyOperators.operator *(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Abs(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Clamp(int value, int min, int max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (int Quotient, int Remainder) INumber.DivRem(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Max(int x, int y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Min(int x, int y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int INumber.Sign(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IShiftOperators.operator <<(int value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IShiftOperators.operator >>(int value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out int result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int ISubtractionOperators.operator -(int left, int right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IUnaryNegationOperators.operator -(int value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static int IUnaryPlusOperators.operator +(int value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -4095,133 +4129,133 @@ public InsufficientMemoryException(string? message, System.Exception? innerExcep public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Int64 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IAdditionOperators.operator +(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.LeadingZeroCount(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.PopCount(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.RotateLeft(long value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.RotateRight(long value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryInteger.TrailingZeroCount(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBinaryNumber.Log2(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator &(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator |(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator ^(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IBitwiseOperators.operator ~(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IDecrementOperators.operator --(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IDivisionOperators.operator /(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IIncrementOperators.operator ++(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IModulusOperators.operator %(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IMultiplyOperators.operator *(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Abs(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Clamp(long value, long min, long max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (long Quotient, long Remainder) INumber.DivRem(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Max(long x, long y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Min(long x, long y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long INumber.Sign(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IShiftOperators.operator <<(long value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IShiftOperators.operator >>(long value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out long result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long ISubtractionOperators.operator -(long left, long right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IUnaryNegationOperators.operator -(long value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static long IUnaryPlusOperators.operator +(long value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -4283,133 +4317,133 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.IntPtr result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IAdditionOperators.operator +(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.LeadingZeroCount(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.PopCount(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.RotateLeft(nint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.RotateRight(nint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryInteger.TrailingZeroCount(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBinaryNumber.Log2(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator &(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator |(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator ^(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IBitwiseOperators.operator ~(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IDecrementOperators.operator --(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IDivisionOperators.operator /(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IIncrementOperators.operator ++(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IModulusOperators.operator %(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IMultiplyOperators.operator *(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Abs(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Clamp(nint value, nint min, nint max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (nint Quotient, nint Remainder) INumber.DivRem(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Max(nint x, nint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Min(nint x, nint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint INumber.Sign(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IShiftOperators.operator <<(nint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IShiftOperators.operator >>(nint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out nint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint ISubtractionOperators.operator -(nint left, nint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IUnaryNegationOperators.operator -(nint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nint IUnaryPlusOperators.operator +(nint value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -5248,133 +5282,133 @@ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, S public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.SByte result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IAdditionOperators.operator +(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.LeadingZeroCount(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.PopCount(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.RotateLeft(sbyte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.RotateRight(sbyte value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryInteger.TrailingZeroCount(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBinaryNumber.Log2(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator &(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator |(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator ^(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IBitwiseOperators.operator ~(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IDecrementOperators.operator --(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IDivisionOperators.operator /(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IIncrementOperators.operator ++(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IModulusOperators.operator %(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IMultiplyOperators.operator *(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Abs(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Clamp(sbyte value, sbyte min, sbyte max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (sbyte Quotient, sbyte Remainder) INumber.DivRem(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Max(sbyte x, sbyte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Min(sbyte x, sbyte y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte INumber.Sign(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IShiftOperators.operator <<(sbyte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IShiftOperators.operator >>(sbyte value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out sbyte result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte ISubtractionOperators.operator -(sbyte left, sbyte right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IUnaryNegationOperators.operator -(sbyte value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static sbyte IUnaryPlusOperators.operator +(sbyte value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -5449,209 +5483,226 @@ public SerializableAttribute() { } public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.Single result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.E { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Epsilon { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.NaN { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.NegativeInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.NegativeZero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Pi { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.PositiveInfinity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Tau { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IAdditionOperators.operator +(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBinaryNumber.Log2(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator &(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator |(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator ^(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IBitwiseOperators.operator ~(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IDecrementOperators.operator --(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IDivisionOperators.operator /(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Acos(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Acosh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Asin(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Asinh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Atan(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Atan2(float y, float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Atanh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.BitIncrement(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.BitDecrement(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Cbrt(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Ceiling(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.CopySign(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Cos(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Cosh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Exp(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Floor(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.FusedMultiplyAdd(float left, float right, float addend) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.IEEERemainder(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static TInteger IFloatingPoint.ILogB(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log(float x, float newBase) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log2(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Log10(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.MaxMagnitude(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.MinMagnitude(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Pow(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x, TInteger digits) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Round(float x, TInteger digits, System.MidpointRounding mode) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.ScaleB(float x, TInteger n) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Sin(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Sinh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Sqrt(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Tan(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Tanh(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IFloatingPoint.Truncate(float x) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsFinite(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsInfinity(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNaN(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNegative(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNegativeInfinity(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsNormal(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsPositiveInfinity(float x) { throw null; } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static bool IFloatingPoint.IsSubnormal(float x) { throw null; } + + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IIncrementOperators.operator ++(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IModulusOperators.operator %(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IMultiplyOperators.operator *(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Abs(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Clamp(float value, float min, float max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (float Quotient, float Remainder) INumber.DivRem(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Max(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Min(float x, float y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float INumber.Sign(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float ISignedNumber.NegativeOne { get; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out float result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float ISubtractionOperators.operator -(float left, float right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IUnaryNegationOperators.operator -(float value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static float IUnaryPlusOperators.operator +(float value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -6036,32 +6087,37 @@ public ThreadStaticAttribute() { } public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider? provider = null) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.TimeOnly left, System.TimeOnly right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeOnly IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.TimeOnly result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeOnly ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.TimeOnly result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.TimeOnly left, System.TimeOnly right) { throw null; } + + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static System.TimeOnly IMinMaxValue.MinValue { get { throw null; } } + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static System.TimeOnly IMinMaxValue.MaxValue { get { throw null; } } #endif // FEATURE_GENERIC_MATH } public partial class TimeoutException : System.SystemException @@ -6174,59 +6230,59 @@ public TimeoutException(string? message, System.Exception? innerException) { } public static bool TryParseExact([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? input, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string?[]? formats, System.IFormatProvider? formatProvider, out System.TimeSpan result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IAdditionOperators.operator +(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IDivisionOperators.operator /(System.TimeSpan left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static double IDivisionOperators.operator /(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IMultiplyOperators.operator *(System.TimeSpan left, double right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out System.TimeSpan result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISpanParseable.Parse(System.ReadOnlySpan s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out System.TimeSpan result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan ISubtractionOperators.operator -(System.TimeSpan left, System.TimeSpan right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IUnaryNegationOperators.operator -(System.TimeSpan value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static System.TimeSpan IUnaryPlusOperators.operator +(System.TimeSpan value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -6961,130 +7017,130 @@ public TypeUnloadedException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.UInt16 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IAdditionOperators.operator +(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.LeadingZeroCount(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.PopCount(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.RotateLeft(ushort value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.RotateRight(ushort value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryInteger.TrailingZeroCount(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBinaryNumber.Log2(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator &(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator |(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator ^(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IBitwiseOperators.operator ~(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IDecrementOperators.operator --(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IDivisionOperators.operator /(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IIncrementOperators.operator ++(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IModulusOperators.operator %(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IMultiplyOperators.operator *(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Abs(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Clamp(ushort value, ushort min, ushort max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (ushort Quotient, ushort Remainder) INumber.DivRem(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Max(ushort x, ushort y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Min(ushort x, ushort y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort INumber.Sign(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IShiftOperators.operator <<(ushort value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IShiftOperators.operator >>(ushort value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out ushort result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort ISubtractionOperators.operator -(ushort left, ushort right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IUnaryNegationOperators.operator -(ushort value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ushort IUnaryPlusOperators.operator +(ushort value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7138,130 +7194,130 @@ public TypeUnloadedException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.UInt32 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IAdditionOperators.operator +(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.LeadingZeroCount(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.PopCount(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.RotateLeft(uint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.RotateRight(uint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryInteger.TrailingZeroCount(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBinaryNumber.Log2(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator &(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator |(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator ^(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IBitwiseOperators.operator ~(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IDecrementOperators.operator --(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IDivisionOperators.operator /(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IIncrementOperators.operator ++(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IModulusOperators.operator %(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IMultiplyOperators.operator *(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Abs(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Clamp(uint value, uint min, uint max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (uint Quotient, uint Remainder) INumber.DivRem(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Max(uint x, uint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Min(uint x, uint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint INumber.Sign(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IShiftOperators.operator <<(uint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IShiftOperators.operator >>(uint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out uint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint ISubtractionOperators.operator -(uint left, uint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IUnaryNegationOperators.operator -(uint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static uint IUnaryPlusOperators.operator +(uint value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7315,130 +7371,130 @@ public TypeUnloadedException(string? message, System.Exception? innerException) public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, out System.UInt64 result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IAdditionOperators.operator +(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.LeadingZeroCount(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.PopCount(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.RotateLeft(ulong value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.RotateRight(ulong value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryInteger.TrailingZeroCount(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBinaryNumber.Log2(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator &(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator |(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator ^(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IBitwiseOperators.operator ~(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IDecrementOperators.operator --(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IDivisionOperators.operator /(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IIncrementOperators.operator ++(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IModulusOperators.operator %(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IMultiplyOperators.operator *(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Abs(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Clamp(ulong value, ulong min, ulong max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (ulong Quotient, ulong Remainder) INumber.DivRem(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Max(ulong x, ulong y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Min(ulong x, ulong y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong INumber.Sign(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IShiftOperators.operator <<(ulong value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IShiftOperators.operator >>(ulong value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out ulong result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong ISubtractionOperators.operator -(ulong left, ulong right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IUnaryNegationOperators.operator -(ulong value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static ulong IUnaryPlusOperators.operator +(ulong value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7497,129 +7553,129 @@ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Ser public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out System.UIntPtr result) { throw null; } #if FEATURE_GENERIC_MATH - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IAdditiveIdentity.AdditiveIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMinMaxValue.MinValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMinMaxValue.MaxValue { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMultiplicativeIdentity.MultiplicativeIdentity { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.One { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Zero { get { throw null; } } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IAdditionOperators.operator +(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.LeadingZeroCount(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.PopCount(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.RotateLeft(nuint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.RotateRight(nuint value, int rotateAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryInteger.TrailingZeroCount(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IBinaryNumber.IsPow2(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBinaryNumber.Log2(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator &(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator |(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator ^(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IBitwiseOperators.operator ~(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator <=(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IComparisonOperators.operator >=(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IDecrementOperators.operator --(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IDivisionOperators.operator /(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator ==(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IEqualityOperators.operator !=(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IIncrementOperators.operator ++(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IModulusOperators.operator %(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IMultiplyOperators.operator *(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Abs(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Clamp(nuint value, nuint min, nuint max) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Create(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.CreateSaturating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.CreateTruncating(TOther value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static (nuint Quotient, nuint Remainder) INumber.DivRem(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Max(nuint x, nuint y) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] - static nuint INumber.Min(nuint x, nuint y) { throw null; }[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] + static nuint INumber.Min(nuint x, nuint y) { throw null; }[System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint INumber.Sign(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryCreate(TOther value, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool INumber.TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IParseable.Parse(string s, System.IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool IParseable.TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? s, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IShiftOperators.operator <<(nuint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeatures] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IShiftOperators.operator >>(nuint value, int shiftAmount) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint ISpanParseable.Parse(System.ReadOnlySpan s, IFormatProvider? provider) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static bool ISpanParseable.TryParse(System.ReadOnlySpan s, System.IFormatProvider? provider, out nuint result) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint ISubtractionOperators.operator -(nuint left, nuint right) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IUnaryNegationOperators.operator -(nuint value) { throw null; } - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] static nuint IUnaryPlusOperators.operator +(nuint value) { throw null; } #endif // FEATURE_GENERIC_MATH } @@ -7660,6 +7716,7 @@ protected Uri(System.Runtime.Serialization.SerializationInfo serializationInfo, public Uri(string uriString) { } [System.ObsoleteAttribute("This constructor has been deprecated; the dontEscape parameter is always false. Use Uri(string) instead.")] public Uri(string uriString, bool dontEscape) { } + public Uri(string uriString, in System.UriCreationOptions creationOptions) { } public Uri(string uriString, System.UriKind uriKind) { } public Uri(System.Uri baseUri, string? relativeUri) { } [System.ObsoleteAttribute("This constructor has been deprecated; the dontEscape parameter is always false. Use Uri(Uri, string) instead.")] @@ -7729,6 +7786,7 @@ protected void GetObjectData(System.Runtime.Serialization.SerializationInfo seri protected virtual void Parse() { } void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) { } public override string ToString() { throw null; } + public static bool TryCreate([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? uriString, in System.UriCreationOptions creationOptions, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Uri? result) { throw null; } public static bool TryCreate([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? uriString, System.UriKind uriKind, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Uri? result) { throw null; } public static bool TryCreate(System.Uri? baseUri, string? relativeUri, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Uri? result) { throw null; } public static bool TryCreate(System.Uri? baseUri, System.Uri? relativeUri, [System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] out System.Uri? result) { throw null; } @@ -7765,6 +7823,10 @@ public UriBuilder(System.Uri uri) { } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } } + public partial struct UriCreationOptions + { + public bool DangerousDisablePathAndQueryCanonicalization { readonly get { throw null; } set { } } + } [System.FlagsAttribute] public enum UriComponents { @@ -13016,7 +13078,7 @@ public static partial class RuntimeFeature public const string DefaultImplementationsOfInterfaces = "DefaultImplementationsOfInterfaces"; public const string UnmanagedSignatureCallingConvention = "UnmanagedSignatureCallingConvention"; public const string PortablePdb = "PortablePdb"; - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute] + [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("Generic Math is in preview.", Url = "https://aka.ms/dotnet-warnings/generic-math-preview")] public const string VirtualStaticsInInterfaces = "VirtualStaticsInInterfaces"; public static bool IsDynamicCodeCompiled { get { throw null; } } public static bool IsDynamicCodeSupported { get { throw null; } } diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj index 6d888e344bc80e..913da87c5b2845 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests.csproj @@ -14,32 +14,19 @@ $(DefineConstants);FEATURE_GENERIC_MATH - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -248,8 +235,7 @@ - + @@ -257,12 +243,15 @@ + + + @@ -283,31 +272,27 @@ - + - + - + System.Reflection.Tests.EmbeddedImage.png System.Reflection.Tests.EmbeddedTextFile.txt - + - + diff --git a/src/libraries/System.Runtime/tests/System/ArrayTests.cs b/src/libraries/System.Runtime/tests/System/ArrayTests.cs index b7bdc5fab35834..7917c4e8d2bda8 100644 --- a/src/libraries/System.Runtime/tests/System/ArrayTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArrayTests.cs @@ -1275,6 +1275,9 @@ public static IEnumerable Copy_SZArray_UnreliableConversion_CanPerform // Interface[] -> Class[] yield return new object[] { new NonGenericInterface1[10], 0, new NonGenericClass1[10], 0, 10, new NonGenericClass1[10] }; + + // object[] -> Int32Enum[] when values are all Int32Enum + yield return new object[] { new object[] { Int32Enum.Case3 }, 0, new Int32Enum[1], 0, 1, new Int32Enum[] { Int32Enum.Case3 } }; } public static IEnumerable Copy_Array_UnreliableConversion_CanPerform_TestData() diff --git a/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs b/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs index 935c75e01bb7c3..624b9b508a868e 100644 --- a/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs +++ b/src/libraries/System.Runtime/tests/System/DateOnlyTests.cs @@ -513,6 +513,16 @@ public static void TryFormatTest() Assert.False(dateOnly.TryFormat(buffer.Slice(0, 3), out charsWritten)); Assert.False(dateOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "r")); Assert.False(dateOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "O")); + Assert.Throws(() => { + Span buff = stackalloc char[100]; + dateOnly.TryFormat(buff, out charsWritten, "u"); + }); + Assert.Throws(() => { + Span buff = stackalloc char[100]; + dateOnly.TryFormat(buff, out charsWritten, "hh-ss"); + }); + Assert.Throws(() => $"{dateOnly:u}"); + Assert.Throws(() => $"{dateOnly:hh-ss}"); } } } diff --git a/src/libraries/System.Runtime/tests/System/DoubleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System/DoubleTests.GenericMath.cs new file mode 100644 index 00000000000000..60a20053823ec2 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/DoubleTests.GenericMath.cs @@ -0,0 +1,127 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Globalization; +using System.Runtime.Versioning; +using Xunit; + +namespace System.Tests +{ + [ActiveIssue("https://github.com/dotnet/runtime/issues/54910", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] + [RequiresPreviewFeaturesAttribute] + public class DoubleTests_GenericMath + { + [Theory] + [MemberData(nameof(DoubleTests.Parse_Valid_TestData), MemberType = typeof(DoubleTests))] + public static void ParseValidStringTest(string value, NumberStyles style, IFormatProvider provider, double expected) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + double result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.True(NumberHelper.TryParse(value, null, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, null)); + } + + Assert.Equal(expected, NumberHelper.Parse(value, provider)); + } + + // Use Parse(string, NumberStyles, IFormatProvider) + Assert.True(NumberHelper.TryParse(value, style, provider, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, style, provider)); + + if (isDefaultProvider) + { + // Use Parse(string, NumberStyles) or Parse(string, NumberStyles, IFormatProvider) + Assert.True(NumberHelper.TryParse(value, style, NumberFormatInfo.CurrentInfo, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, style, null)); + Assert.Equal(expected, NumberHelper.Parse(value, style, NumberFormatInfo.CurrentInfo)); + } + } + + [Theory] + [MemberData(nameof(DoubleTests.Parse_Invalid_TestData), MemberType = typeof(DoubleTests))] + public static void ParseInvalidStringTest(string value, NumberStyles style, IFormatProvider provider, Type exceptionType) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + double result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None && (style & NumberStyles.AllowLeadingWhite) == (style & NumberStyles.AllowTrailingWhite)) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.False(NumberHelper.TryParse(value, null, out result)); + Assert.Equal(default(double), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, null)); + } + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, provider)); + } + + // Use Parse(string, NumberStyles, IFormatProvider) + Assert.False(NumberHelper.TryParse(value, style, provider, out result)); + Assert.Equal(default(double), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, provider)); + + if (isDefaultProvider) + { + // Use Parse(string, NumberStyles) or Parse(string, NumberStyles, IFormatProvider) + Assert.False(NumberHelper.TryParse(value, style, NumberFormatInfo.CurrentInfo, out result)); + Assert.Equal(default(double), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, null)); + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, NumberFormatInfo.CurrentInfo)); + } + } + + [Theory] + [MemberData(nameof(DoubleTests.Parse_ValidWithOffsetCount_TestData), MemberType = typeof(DoubleTests))] + public static void ParseValidSpanTest(string value, int offset, int count, NumberStyles style, IFormatProvider provider, double expected) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + double result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.True(NumberHelper.TryParse(value.AsSpan(offset, count), null, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), null)); + } + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), provider: provider)); + } + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), style, provider)); + + Assert.True(NumberHelper.TryParse(value.AsSpan(offset, count), style, provider, out result)); + Assert.Equal(expected, result); + } + + [Theory] + [MemberData(nameof(DoubleTests.Parse_Invalid_TestData), MemberType = typeof(DoubleTests))] + public static void ParseInvalidSpanTest(string value, NumberStyles style, IFormatProvider provider, Type exceptionType) + { + if (value != null) + { + Assert.Throws(exceptionType, () => NumberHelper.Parse(value.AsSpan(), style, provider)); + + Assert.False(NumberHelper.TryParse(value.AsSpan(), style, provider, out double result)); + Assert.Equal(0, result); + } + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/EnumTests.cs b/src/libraries/System.Runtime/tests/System/EnumTests.cs index f718e6e4c24429..a764555bd93fd8 100644 --- a/src/libraries/System.Runtime/tests/System/EnumTests.cs +++ b/src/libraries/System.Runtime/tests/System/EnumTests.cs @@ -287,6 +287,15 @@ private static void Parse_Generic_Invalid(Type enumType, string value, bool i } } + [Theory] + [InlineData("Yellow")] + [InlineData("Yellow,Orange")] + public static void Parse_NonExistentValue_IncludedInErrorMessage(string value) + { + ArgumentException e = Assert.Throws(() => Enum.Parse(typeof(SimpleEnum), value)); + Assert.Contains(value, e.Message); + } + [Theory] [InlineData(SByteEnum.Min, "Min")] [InlineData(SByteEnum.One, "One")] diff --git a/src/libraries/System.Runtime/tests/System/GenericMathHelpers.cs b/src/libraries/System.Runtime/tests/System/GenericMathHelpers.cs index 2895dd8841962e..e1d4659db229be 100644 --- a/src/libraries/System.Runtime/tests/System/GenericMathHelpers.cs +++ b/src/libraries/System.Runtime/tests/System/GenericMathHelpers.cs @@ -157,8 +157,12 @@ public static TSelf CreateTruncating(TOther value) public static TSelf Min(TSelf x, TSelf y) => TSelf.Min(x, y); + public static TSelf Parse(string s, IFormatProvider provider) => TSelf.Parse(s, provider); + public static TSelf Parse(string s, NumberStyles style, IFormatProvider provider) => TSelf.Parse(s, style, provider); + public static TSelf Parse(ReadOnlySpan s, IFormatProvider provider) => TSelf.Parse(s, provider); + public static TSelf Parse(ReadOnlySpan s, NumberStyles style, IFormatProvider provider) => TSelf.Parse(s, style, provider); public static TSelf Sign(TSelf value) => TSelf.Sign(value); @@ -166,8 +170,12 @@ public static TSelf CreateTruncating(TOther value) public static bool TryCreate(TOther value, out TSelf result) where TOther : INumber => TSelf.TryCreate(value, out result); + public static bool TryParse(string s, IFormatProvider provider, out TSelf result) => TSelf.TryParse(s, provider, out result); + public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out TSelf result) => TSelf.TryParse(s, style, provider, out result); + public static bool TryParse(ReadOnlySpan s, IFormatProvider provider, out TSelf result) => TSelf.TryParse(s, provider, out result); + public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider provider, out TSelf result) => TSelf.TryParse(s, style, provider, out result); } diff --git a/src/libraries/System.Runtime/tests/System/HalfTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System/HalfTests.GenericMath.cs new file mode 100644 index 00000000000000..c9fe77c9154a98 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/HalfTests.GenericMath.cs @@ -0,0 +1,127 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Globalization; +using System.Runtime.Versioning; +using Xunit; + +namespace System.Tests +{ + [ActiveIssue("https://github.com/dotnet/runtime/issues/54910", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] + [RequiresPreviewFeaturesAttribute] + public class HalfTests_GenericMath + { + [Theory] + [MemberData(nameof(HalfTests.Parse_Valid_TestData), MemberType = typeof(HalfTests))] + public static void ParseValidStringTest(string value, NumberStyles style, IFormatProvider provider, Half expected) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + Half result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.True(NumberHelper.TryParse(value, null, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, null)); + } + + Assert.Equal(expected, NumberHelper.Parse(value, provider)); + } + + // Use Parse(string, NumberStyles, IFormatProvider) + Assert.True(NumberHelper.TryParse(value, style, provider, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, style, provider)); + + if (isDefaultProvider) + { + // Use Parse(string, NumberStyles) or Parse(string, NumberStyles, IFormatProvider) + Assert.True(NumberHelper.TryParse(value, style, NumberFormatInfo.CurrentInfo, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, style, null)); + Assert.Equal(expected, NumberHelper.Parse(value, style, NumberFormatInfo.CurrentInfo)); + } + } + + [Theory] + [MemberData(nameof(HalfTests.Parse_Invalid_TestData), MemberType = typeof(HalfTests))] + public static void ParseInvalidStringTest(string value, NumberStyles style, IFormatProvider provider, Type exceptionType) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + Half result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None && (style & NumberStyles.AllowLeadingWhite) == (style & NumberStyles.AllowTrailingWhite)) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.False(NumberHelper.TryParse(value, null, out result)); + Assert.Equal(default(Half), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, null)); + } + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, provider)); + } + + // Use Parse(string, NumberStyles, IFormatProvider) + Assert.False(NumberHelper.TryParse(value, style, provider, out result)); + Assert.Equal(default(Half), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, provider)); + + if (isDefaultProvider) + { + // Use Parse(string, NumberStyles) or Parse(string, NumberStyles, IFormatProvider) + Assert.False(NumberHelper.TryParse(value, style, NumberFormatInfo.CurrentInfo, out result)); + Assert.Equal(default(Half), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, null)); + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, NumberFormatInfo.CurrentInfo)); + } + } + + [Theory] + [MemberData(nameof(HalfTests.Parse_ValidWithOffsetCount_TestData), MemberType = typeof(HalfTests))] + public static void ParseValidSpanTest(string value, int offset, int count, NumberStyles style, IFormatProvider provider, Half expected) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + Half result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.True(NumberHelper.TryParse(value.AsSpan(offset, count), null, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), null)); + } + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), provider: provider)); + } + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), style, provider)); + + Assert.True(NumberHelper.TryParse(value.AsSpan(offset, count), style, provider, out result)); + Assert.Equal(expected, result); + } + + [Theory] + [MemberData(nameof(HalfTests.Parse_Invalid_TestData), MemberType = typeof(HalfTests))] + public static void ParseInvalidSpanTest(string value, NumberStyles style, IFormatProvider provider, Type exceptionType) + { + if (value != null) + { + Assert.Throws(exceptionType, () => NumberHelper.Parse(value.AsSpan(), style, provider)); + + Assert.False(NumberHelper.TryParse(value.AsSpan(), style, provider, out Half result)); + Assert.Equal((Half)0, result); + } + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs index d016e53c75e299..4460797182c873 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs @@ -52,6 +52,14 @@ public static void Test_CustomAttributeTypedArgument_Constructor() Assert.True(false, "Expected to find MyAttr Attribute"); } + [Fact] + public static void Test_CustomAttributeTypedArgument_ToString() + { + var argument = new CustomAttributeTypedArgument(new [] { new CustomAttributeTypedArgument(0) }); + + Assert.Equal("new CustomAttributeTypedArgument[1] { 0 }", argument.ToString()); + } + [MyAttr(MyKinds.First, Desc = "This is a description on a method")] private static void MyMethod() { } } diff --git a/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs index 1651b1817a4ab7..f444a5624c6bb6 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/NullabilityInfoContextTests.cs @@ -33,7 +33,7 @@ public static IEnumerable FieldTestData() yield return new object[] { "FieldAllowNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; - yield return new object[] { "FieldMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; + yield return new object[] { "FieldMaybeNull2", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; yield return new object[] { "FieldNotNull2", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; } @@ -121,7 +121,7 @@ public static IEnumerable ArrayPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(ArrayPropertyTestData))] public void ArrayPropertyTest(string propertyName, NullabilityState elementState, NullabilityState propertyState) { @@ -143,7 +143,7 @@ public static IEnumerable GenericArrayPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(GenericArrayPropertyTestData))] public void GenericArrayPropertyTest(string propertyName, NullabilityState elementState, NullabilityState propertyState) { @@ -167,7 +167,7 @@ public static IEnumerable JaggedArrayPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(JaggedArrayPropertyTestData))] public void JaggedArrayPropertyTest(string propertyName, NullabilityState innermodtElementState, NullabilityState elementState, NullabilityState propertyState) { @@ -192,7 +192,7 @@ public static IEnumerable TuplePropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(TuplePropertyTestData))] public void TuplePropertyTest(string propertyName, NullabilityState genericParam1, NullabilityState genericParam2, NullabilityState genericParam3, NullabilityState propertyState) { @@ -217,7 +217,7 @@ public static IEnumerable GenericTuplePropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(GenericTuplePropertyTestData))] public void GenericTuplePropertyTest(string propertyName, NullabilityState genericParam1, NullabilityState genericParam2, NullabilityState genericParam3, NullabilityState propertyState) { @@ -243,7 +243,7 @@ public static IEnumerable DictionaryPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(DictionaryPropertyTestData))] public void DictionaryPropertyTest(string propertyName, NullabilityState keyState, NullabilityState valueElement, NullabilityState valueState, NullabilityState propertyState) { @@ -269,7 +269,7 @@ public static IEnumerable GenericDictionaryPropertyTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(GenericDictionaryPropertyTestData))] public void GenericDictionaryPropertyTest(string propertyName, NullabilityState keyState, NullabilityState valueElement, NullabilityState valueState, NullabilityState propertyState) { @@ -433,16 +433,16 @@ public void GenericFieldNullableValueTypeTest(string fieldName, NullabilityState Assert.Equal(type, nullability.Type); } - public static IEnumerable GenericNotnullConstraintTestData() + public static IEnumerable GenericNotnullConstraintFieldsTestData() { - yield return new object[] { "FieldNullable", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; + yield return new object[] { "FieldNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "FieldUnknown", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; yield return new object[] { "FieldNullableEnabled", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; } [Theory] - [MemberData(nameof(GenericNotnullConstraintTestData))] - public void GenericNotNullConstraintTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) + [MemberData(nameof(GenericNotnullConstraintFieldsTestData))] + public void GenericNotNullConstraintFieldsTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) { FieldInfo field = typeof(GenericTestConstrainedNotNull).GetField(fieldName, flags)!; NullabilityInfo nullability = nullabilityContext.Create(field); @@ -451,7 +451,25 @@ public void GenericNotNullConstraintTest(string fieldName, NullabilityState read Assert.Equal(type, nullability.Type); } - public static IEnumerable GenericStructConstraintTestData() + public static IEnumerable GenericNotnullConstraintPropertiesTestData() + { + yield return new object[] { "PropertyNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(string) }; + yield return new object[] { "PropertyUnknown", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyNullableEnabled", NullabilityState.NotNull, NullabilityState.NotNull, typeof(string) }; + } + + [Theory] + [MemberData(nameof(GenericNotnullConstraintPropertiesTestData))] + public void GenericNotNullConstraintPropertiesTest(string propertyName, NullabilityState readState, NullabilityState writeState, Type type) + { + PropertyInfo property = typeof(GenericTestConstrainedNotNull).GetProperty(propertyName, flags)!; + NullabilityInfo nullability = nullabilityContext.Create(property); + Assert.Equal(readState, nullability.ReadState); + Assert.Equal(writeState, nullability.WriteState); + Assert.Equal(type, nullability.Type); + } + + public static IEnumerable GenericStructConstraintFieldsTestData() { yield return new object[] { "FieldNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(int?) }; yield return new object[] { "FieldUnknown", NullabilityState.NotNull, NullabilityState.NotNull, typeof(int) }; @@ -459,8 +477,8 @@ public static IEnumerable GenericStructConstraintTestData() } [Theory] - [MemberData(nameof(GenericStructConstraintTestData))] - public void GenericStructConstraintTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) + [MemberData(nameof(GenericStructConstraintFieldsTestData))] + public void GenericStructConstraintFieldsTest(string fieldName, NullabilityState readState, NullabilityState writeState, Type type) { FieldInfo field = typeof(GenericTestConstrainedStruct).GetField(fieldName, flags)!; NullabilityInfo nullability = nullabilityContext.Create(field); @@ -469,6 +487,24 @@ public void GenericStructConstraintTest(string fieldName, NullabilityState readS Assert.Equal(type, nullability.Type); } + public static IEnumerable GenericStructConstraintPropertiesTestData() + { + yield return new object[] { "PropertyNullable", NullabilityState.Nullable, NullabilityState.Nullable, typeof(int?) }; + yield return new object[] { "PropertyUnknown", NullabilityState.NotNull, NullabilityState.NotNull, typeof(int) }; + yield return new object[] { "PropertyNullableEnabled", NullabilityState.NotNull, NullabilityState.NotNull, typeof(int) }; + } + + [Theory] + [MemberData(nameof(GenericStructConstraintPropertiesTestData))] + public void GenericStructConstraintPropertiesTest(string propertyName, NullabilityState readState, NullabilityState writeState, Type type) + { + PropertyInfo property = typeof(GenericTestConstrainedStruct).GetProperty(propertyName, flags)!; + NullabilityInfo nullability = nullabilityContext.Create(property); + Assert.Equal(readState, nullability.ReadState); + Assert.Equal(writeState, nullability.WriteState); + Assert.Equal(type, nullability.Type); + } + [Fact] [SkipOnMono("Nullability attributes trimmed on Mono")] public void GenericListTest() @@ -480,8 +516,8 @@ public void GenericListTest() Assert.Equal(NullabilityState.Nullable, nullability.WriteState); Assert.Equal(typeof(string), nullability.Type); - Type lisNontNull = typeof(List); - MethodInfo addNotNull = lisNontNull.GetMethod("Add")!; + Type listNotNull = typeof(List); + MethodInfo addNotNull = listNotNull.GetMethod("Add")!; nullability = nullabilityContext.Create(addNotNull.GetParameters()[0]); Assert.Equal(NullabilityState.Nullable, nullability.ReadState); Assert.Equal(typeof(string), nullability.Type); @@ -544,7 +580,7 @@ public static IEnumerable MethodReturnParameterTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodReturnParameterTestData))] public void MethodReturnParameterTest(string methodName, NullabilityState elementState, NullabilityState readState) { @@ -557,6 +593,31 @@ public void MethodReturnParameterTest(string methodName, NullabilityState elemen Assert.Empty(nullability.GenericTypeArguments); } + public static IEnumerable MethodReturnsTupleTestData() + { + // public Tuple? MethodReturnsTupleNullNonNull() => null; + yield return new object[] { "MethodReturnsTupleNullNonNull", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + // public Tuple MethodReturnsTupleNullNonNot() => null! + yield return new object[] { "MethodReturnsTupleNullNonNot", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull }; + // public (int?, string)? MethodReturnsValueTupleNullNonNull() => null; + yield return new object[] { "MethodReturnsValueTupleNullNonNull", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + // public (string?, string) MethodReturnsValueTupleNullNonNon() => (null, string.Empty); + yield return new object[] { "MethodReturnsValueTupleNullNonNon", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull }; + } + + [Theory] + [SkipOnMono("Nullability attributes trimmed on Mono")] + [MemberData(nameof(MethodReturnsTupleTestData))] + public void MethodReturnsTupleTest(string methodName, NullabilityState param1, NullabilityState param2, NullabilityState readState) + { + MethodInfo method = testType.GetMethod(methodName, flags)!; + NullabilityInfo nullability = nullabilityContext.Create(method.ReturnParameter); + Assert.Equal(readState, nullability.ReadState); + Assert.Null(nullability.ElementType); + Assert.Equal(param1, nullability.GenericTypeArguments[0].ReadState); + Assert.Equal(param2, nullability.GenericTypeArguments[1].ReadState); + } + public static IEnumerable MethodGenericReturnParameterTestData() { yield return new object[] { "MethodReturnsUnknown", NullabilityState.Unknown, NullabilityState.Unknown }; @@ -569,7 +630,7 @@ public static IEnumerable MethodGenericReturnParameterTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodGenericReturnParameterTestData))] public void MethodGenericReturnParameterTest(string methodName, NullabilityState readState, NullabilityState elementState) { @@ -592,7 +653,7 @@ public static IEnumerable MethodParametersTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodParametersTestData))] public void MethodParametersTest(string methodName, NullabilityState stringState, NullabilityState dictKey, NullabilityState dictValueElement, NullabilityState dictValue, NullabilityState dictionaryState) { @@ -616,7 +677,7 @@ public static IEnumerable MethodGenericParametersTestData() } [Theory] - [SkipOnMono("Disabling NullablePublicOnly feature not work for Mono tests")] + [SkipOnMono("Nullability attributes trimmed on Mono")] [MemberData(nameof(MethodGenericParametersTestData))] public void MethodGenericParametersTest(string methodName, NullabilityState param1State, NullabilityState dictKey, NullabilityState dictValue, NullabilityState dictionaryState) { @@ -705,6 +766,8 @@ public void NullablePublicOnlyOtherTypesTest() public static IEnumerable DifferentContextTestData() { yield return new object[] { "PropertyDisabled", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyDisabledAllowNull", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; + yield return new object[] { "PropertyDisabledMaybeNull", NullabilityState.Unknown, NullabilityState.Unknown, typeof(string) }; yield return new object[] { "PropertyEnabledAllowNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyEnabledNotNull", NullabilityState.NotNull, NullabilityState.Nullable, typeof(string) }; yield return new object[] { "PropertyEnabledMaybeNull", NullabilityState.Nullable, NullabilityState.NotNull, typeof(string) }; @@ -766,15 +829,15 @@ public void AttributedParametersTest() Assert.Equal(NullabilityState.Nullable, notNullIfNotNull.WriteState); Assert.Equal(NullabilityState.Nullable, nullabilityContext.Create(allowNullParameter[1]).ReadState); - // [return: NotNullIfNotNull("nullable")] public string? NullablNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) - ParameterInfo[] nullablNotNullIfNotNullReturn = type.GetMethod("NullablNotNullIfNotNullReturn", flags)!.GetParameters(); - NullabilityInfo returnNotNullIfNotNull = nullabilityContext.Create(type.GetMethod("NullablNotNullIfNotNullReturn", flags)!.ReturnParameter); - NullabilityInfo readNotNull = nullabilityContext.Create(nullablNotNullIfNotNullReturn[1]); + // [return: NotNullIfNotNull("nullable")] public string? NullableNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) + ParameterInfo[] nullableNotNullIfNotNullReturn = type.GetMethod("NullableNotNullIfNotNullReturn", flags)!.GetParameters(); + NullabilityInfo returnNotNullIfNotNull = nullabilityContext.Create(type.GetMethod("NullableNotNullIfNotNullReturn", flags)!.ReturnParameter); + NullabilityInfo readNotNull = nullabilityContext.Create(nullableNotNullIfNotNullReturn[1]); Assert.Equal(NullabilityState.Nullable, returnNotNullIfNotNull.ReadState); Assert.Equal(NullabilityState.Nullable, returnNotNullIfNotNull.WriteState); Assert.Equal(NullabilityState.NotNull, readNotNull.ReadState); Assert.Equal(NullabilityState.Nullable, readNotNull.WriteState); - Assert.Equal(NullabilityState.Nullable, nullabilityContext.Create(nullablNotNullIfNotNullReturn[0]).ReadState); + Assert.Equal(NullabilityState.Nullable, nullabilityContext.Create(nullableNotNullIfNotNullReturn[0]).ReadState); // public bool TryGetOutParameters(string id, [NotNullWhen(true)] out string? value, [MaybeNullWhen(false)] out string value2) ParameterInfo[] tryGetOutParameters = type.GetMethod("TryGetOutParameters", flags)!.GetParameters(); @@ -787,6 +850,51 @@ public void AttributedParametersTest() Assert.Equal(NullabilityState.NotNull, nullabilityContext.Create(tryGetOutParameters[0]).ReadState); } + public static IEnumerable NestedGenericsReturnParameterData() + { + // public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; + yield return new object[] { "MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon", + NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable?>? MethodReturnsEnumerableNullTupleNullNonNullValueTupleNullNonNull() => null!; + yield return new object[] { "MethodReturnsEnumerableNullTupleNullNonNullValueTupleNullNonNull", + NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull }; + + // public IEnumerable, int>?> MethodReturnsEnumerableNonTupleNonNonNullTupleNonNullNon() => null!; + yield return new object[] { "MethodReturnsEnumerableNonTupleNonNonNullTupleNonNullNon", + NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable?, int>?>? MethodReturnsEnumerableNullStructNullNonNonTupleNonNullNull() => null; + yield return new object[] { "MethodReturnsEnumerableNullStructNullNonNullTupleNonNullNull", + NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable?, int>?>? MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull() => null; + yield return new object[] { "MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull", + NullabilityState.Nullable, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + + // public IEnumerable<(GenericStruct str, int? count)> MethodReturnsEnumerableNonValueTupleNonNullNonTupleNonNullNon() => null!; + yield return new object[] { "MethodReturnsEnumerableNonValueTupleNonNullNonStructNonNullNon", + NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.Nullable }; + } + + [Theory] + [MemberData(nameof(NestedGenericsReturnParameterData))] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void NestedGenericsReturnParameterTest(string methodName, NullabilityState enumState, NullabilityState innerTupleState, + NullabilityState intState, NullabilityState outerTupleState, NullabilityState stringState, NullabilityState objectState) + { + NullabilityInfo enumerabeNullability = nullabilityContext.Create(typeof(TypeWithNotNullContext).GetMethod(methodName, flags)!.ReturnParameter); + Assert.Equal(enumState, enumerabeNullability.ReadState); + NullabilityInfo tupleNullability = enumerabeNullability.GenericTypeArguments[0]; + Assert.Equal(outerTupleState, tupleNullability.ReadState); + Assert.Equal(innerTupleState, tupleNullability.GenericTypeArguments[0].ReadState); + Assert.Equal(intState, tupleNullability.GenericTypeArguments[1].ReadState); + NullabilityInfo valueTupleNullability = tupleNullability.GenericTypeArguments[0]; + Assert.Equal(innerTupleState, valueTupleNullability.ReadState); + Assert.Equal(stringState, valueTupleNullability.GenericTypeArguments[0].ReadState); + Assert.Equal(objectState, valueTupleNullability.GenericTypeArguments[1].ReadState); + } + public static IEnumerable RefReturnData() { yield return new object[] { "RefReturnUnknown", NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown, NullabilityState.Unknown }; @@ -812,12 +920,42 @@ public void RefReturnTestTest(string methodName, NullabilityState retReadState, Assert.Equal(paramReadState, paramNullability.ReadState); Assert.Equal(paramWriteState, paramNullability.WriteState); } + + public static IEnumerable ValueTupleTestData() + { + // public (int, string) UnknownValueTuple; [0] + yield return new object[] { "UnknownValueTuple", NullabilityState.NotNull, NullabilityState.Unknown, NullabilityState.NotNull }; + // public (string?, object) NullNonNonValueTuple; [0, 2, 1] + yield return new object[] { "Null_Non_Non_ValueTuple", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.NotNull }; + // public (string?, object)? Null_Non_Null_ValueTuple; [0, 2, 1] + yield return new object[] { "Null_Non_Null_ValueTuple", NullabilityState.Nullable, NullabilityState.NotNull, NullabilityState.Nullable }; + // public (int, int?)? Non_Null_Null_ValueTuple; [0] + yield return new object[] { "Non_Null_Null_ValueTuple", NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.Nullable }; + // public (int, string) Non_Non_Non_ValueTuple; [0, 1] + yield return new object[] { "Non_Non_Non_ValueTuple", NullabilityState.NotNull, NullabilityState.NotNull, NullabilityState.NotNull }; + // public (int, string?) Non_Null_Non_ValueTuple; [0, 2] + yield return new object[] { "Non_Null_Non_ValueTuple", NullabilityState.NotNull, NullabilityState.Nullable, NullabilityState.NotNull }; + } + + [Theory] + [MemberData(nameof(ValueTupleTestData))] + [SkipOnMono("Nullability attributes trimmed on Mono")] + public void TestValueTupleGenericTypeParameters(string fieldName, NullabilityState param1, NullabilityState param2, NullabilityState fieldState) + { + var tupleInfo = nullabilityContext.Create(testType.GetField(fieldName)!); + + Assert.Equal(fieldState, tupleInfo.ReadState); + Assert.Equal(param1, tupleInfo.GenericTypeArguments[0].ReadState); + Assert.Equal(param2, tupleInfo.GenericTypeArguments[1].ReadState); + } } #pragma warning disable CS0649, CS0067, CS0414 public class TypeWithNullableContext { #nullable disable + [AllowNull] public string PropertyDisabledAllowNull { get; set; } + [MaybeNull] public string PropertyDisabledMaybeNull { get; set; } public string PropertyDisabled { get; set; } public ref string RefReturnUnknown(ref string id) { return ref id; } #nullable enable @@ -830,12 +968,13 @@ public class TypeWithNullableContext bool NotNullWhenParameter([DisallowNull] string? disallowNull, [NotNullWhen(true)] ref string? notNullWhen, Type? nullableType) { return false; } public bool MaybeNullParameters([MaybeNull] string maybeNull, [MaybeNullWhen(false)] out string maybeNullWhen, Type? nullableType) { maybeNullWhen = null; return false; } public string? AllowNullParameter([AllowNull] string allowNull, [NotNullIfNotNull("allowNull")] string? notNullIfNotNull) { return null; } - [return: NotNullIfNotNull("nullable")] public string? NullablNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) { readNotNull = string.Empty; return null!; } + [return: NotNullIfNotNull("nullable")] public string? NullableNotNullIfNotNullReturn(string? nullable, [NotNull] ref string? readNotNull) { readNotNull = string.Empty; return null!; } public ref string? RefReturnNullable([AllowNull] ref string id) { return ref id!; } [return: MaybeNull] public ref string RefReturnMaybeNull([DisallowNull] ref string? id) { return ref id; } [return: NotNull] public ref string? RefReturnNotNull([NotNull] ref string? id) { id = string.Empty; return ref id!; } public ref string RefReturnNotNullable([MaybeNull] ref string id) { return ref id; } public bool TryGetOutParameters(string id, [NotNullWhen(true)] out string? value, [MaybeNullWhen(false)] out string value2) { value = null; value2 = null; return false; } + public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; } public class TypeWithNoContext @@ -852,8 +991,6 @@ public class TypeWithNoContext public string? PropertyEnabledNullable { get; set; } public string PropertyEnabledNonNullable { get; set; } = null!; #nullable disable - [return: NotNull, MaybeNull] - public string MethodNullableDisabled([AllowNull] string value, string ret) { return null; } } public class TypeWithNotNullContext @@ -865,6 +1002,7 @@ public class TypeWithNotNullContext protected Tuple PropertyTupleUnknown { get; set; } protected internal IDictionary PropertyDictionaryUnknown { get; set; } + public (int, string) UnknownValueTuple; internal TypeWithNotNullContext FieldUnknown; public int FieldValueTypeUnknown; @@ -915,6 +1053,11 @@ public void MethodParametersUnknown(string s, IDictionary dict) private IDictionary? PropertyDictionaryNonNonNonNull { get; set; } public IDictionary PropertyDictionaryNonNonNonNon { get; set; } = null!; + public (string?, object) Null_Non_Non_ValueTuple; + public (string?, object)? Null_Non_Null_ValueTuple; + public (int, int?)? Non_Null_Null_ValueTuple; + public (int, string) Non_Non_Non_ValueTuple; + public (int, string?) Non_Null_Non_ValueTuple; private const string? FieldNullable = null; protected static NullabilityInfoContextTests FieldNonNullable = null!; public static double FieldValueTypeNotNull; @@ -936,14 +1079,24 @@ public void MethodParametersUnknown(string s, IDictionary dict) [return: NotNull, MaybeNull] public string[]? MethodReturnsNonNotNull() => null!; // only NotNull is applicable [return: MaybeNull] public string[] MethodReturnsNonMaybeNull() => null; public string[] MethodReturnsNonNon() => null!; - public Tuple? MethodTupleNullNonNull() => null; - public IEnumerable?> MethodEnumerableNonNonNullUnknownNullNonNullNon() => null!; + public Tuple? MethodReturnsTupleNullNonNull() => null; + public Tuple MethodReturnsTupleNullNonNot() => null!; + public (int?, string)? MethodReturnsValueTupleNullNonNull() => null; + public (string?, string) MethodReturnsValueTupleNullNonNon() => (null, string.Empty); + public IEnumerable?> MethodReturnsEnumerableNonTupleNonNonNullValueTupleNonNullNon() => null!; + public IEnumerable?>? MethodReturnsEnumerableNullTupleNullNonNullValueTupleNullNonNull() => null!; + public IEnumerable, int>?> MethodReturnsEnumerableNonTupleNonNonNullTupleNonNullNon() => null!; + public IEnumerable?, int>?>? MethodReturnsEnumerableNullStructNullNonNullTupleNonNullNull() => null; + public IEnumerable?, int>?>? MethodReturnsEnumerableNullTupleNullNonNullStructNonNullNull() => null; + public IEnumerable<(GenericStruct str, int? count)> MethodReturnsEnumerableNonValueTupleNonNullNonStructNonNullNon() => null!; public void MethodNullNonNullNonNon(string? s, IDictionary dict) { } public void MethodNonNullNonNullNotNull(string s, [NotNull] IDictionary? dict) { dict = new Dictionary(); } public void MethodNullNonNullNullNon(string? s, IDictionary dict) { } public void MethodAllowNullNonNonNonNull([AllowNull] string s, IDictionary? dict) { } } + public struct GenericStruct { } + internal class GenericTest { #nullable disable @@ -969,14 +1122,14 @@ public void MethodParametersUnknown(T s, IDictionary dict) { } public Tuple? PropertyTupleNullNullNullNull { get; set; } public Tuple PropertyTupleNonNullNonNon { get; set; } = null!; Tuple? PropertyTupleNullNonNullNull { get; set; } - public Tuple? PropertyTupleNonNullNonNull { get; set; } - public Tuple PropertyTupleNonNonNonNon { get; set; } = null!; + public Tuple? PropertyTupleNonNullNonNull { get; set; } + public Tuple PropertyTupleNonNonNonNon { get; set; } = null!; private IDictionary PropertyDictionaryNullNullNullNon { get; set; } = null!; static IDictionary? PropertyDictionaryNonNullNonNull { get; set; } public static IDictionary? PropertyDictionaryNullNonNonNull { get; set; } public IDictionary PropertyDictionaryNonNullNonNon { get; set; } = null!; protected IDictionary? PropertyDictionaryNonNonNonNull { get; set; } - public IDictionary PropertyDictionaryNonNonNonNon { get; set; } = null!; + public IDictionary PropertyDictionaryNonNonNonNon { get; set; } = null!; static T? FieldNullable = default; public T FieldNonNullable = default!; @@ -1007,6 +1160,7 @@ internal class GenericTestConstrainedNotNull where T : notnull public T FieldNullableEnabled = default!; public T? FieldNullable; public T PropertyNullableEnabled { get; set; } = default!; + public T? PropertyNullable { get; set; } = default!; } internal class GenericTestConstrainedStruct where T : struct @@ -1019,5 +1173,6 @@ internal class GenericTestConstrainedStruct where T : struct public T FieldNullableEnabled; public T? FieldNullable; public T PropertyNullableEnabled { get; set; } + public T? PropertyNullable { get; set; } } } diff --git a/src/libraries/System.Runtime/tests/System/SingleTests.GenericMath.cs b/src/libraries/System.Runtime/tests/System/SingleTests.GenericMath.cs new file mode 100644 index 00000000000000..8e7c3e8a1c6908 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System/SingleTests.GenericMath.cs @@ -0,0 +1,127 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Globalization; +using System.Runtime.Versioning; +using Xunit; + +namespace System.Tests +{ + [ActiveIssue("https://github.com/dotnet/runtime/issues/54910", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] + [RequiresPreviewFeaturesAttribute] + public class SingleTests_GenericMath + { + [Theory] + [MemberData(nameof(SingleTests.Parse_Valid_TestData), MemberType = typeof(SingleTests))] + public static void ParseValidStringTest(string value, NumberStyles style, IFormatProvider provider, float expected) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + float result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.True(NumberHelper.TryParse(value, null, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, null)); + } + + Assert.Equal(expected, NumberHelper.Parse(value, provider)); + } + + // Use Parse(string, NumberStyles, IFormatProvider) + Assert.True(NumberHelper.TryParse(value, style, provider, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, style, provider)); + + if (isDefaultProvider) + { + // Use Parse(string, NumberStyles) or Parse(string, NumberStyles, IFormatProvider) + Assert.True(NumberHelper.TryParse(value, style, NumberFormatInfo.CurrentInfo, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value, style, null)); + Assert.Equal(expected, NumberHelper.Parse(value, style, NumberFormatInfo.CurrentInfo)); + } + } + + [Theory] + [MemberData(nameof(SingleTests.Parse_Invalid_TestData), MemberType = typeof(SingleTests))] + public static void ParseInvalidStringTest(string value, NumberStyles style, IFormatProvider provider, Type exceptionType) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + float result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None && (style & NumberStyles.AllowLeadingWhite) == (style & NumberStyles.AllowTrailingWhite)) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.False(NumberHelper.TryParse(value, null, out result)); + Assert.Equal(default(float), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, null)); + } + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, provider)); + } + + // Use Parse(string, NumberStyles, IFormatProvider) + Assert.False(NumberHelper.TryParse(value, style, provider, out result)); + Assert.Equal(default(float), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, provider)); + + if (isDefaultProvider) + { + // Use Parse(string, NumberStyles) or Parse(string, NumberStyles, IFormatProvider) + Assert.False(NumberHelper.TryParse(value, style, NumberFormatInfo.CurrentInfo, out result)); + Assert.Equal(default(float), result); + + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, null)); + Assert.Throws(exceptionType, () => NumberHelper.Parse(value, style, NumberFormatInfo.CurrentInfo)); + } + } + + [Theory] + [MemberData(nameof(SingleTests.Parse_ValidWithOffsetCount_TestData), MemberType = typeof(SingleTests))] + public static void ParseValidSpanTest(string value, int offset, int count, NumberStyles style, IFormatProvider provider, float expected) + { + bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; + float result; + if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) + { + // Use Parse(string) or Parse(string, IFormatProvider) + if (isDefaultProvider) + { + Assert.True(NumberHelper.TryParse(value.AsSpan(offset, count), null, out result)); + Assert.Equal(expected, result); + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), null)); + } + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), provider: provider)); + } + + Assert.Equal(expected, NumberHelper.Parse(value.AsSpan(offset, count), style, provider)); + + Assert.True(NumberHelper.TryParse(value.AsSpan(offset, count), style, provider, out result)); + Assert.Equal(expected, result); + } + + [Theory] + [MemberData(nameof(SingleTests.Parse_Invalid_TestData), MemberType = typeof(SingleTests))] + public static void ParseInvalidSpanTest(string value, NumberStyles style, IFormatProvider provider, Type exceptionType) + { + if (value != null) + { + Assert.Throws(exceptionType, () => NumberHelper.Parse(value.AsSpan(), style, provider)); + + Assert.False(NumberHelper.TryParse(value.AsSpan(), style, provider, out float result)); + Assert.Equal(0, result); + } + } + } +} diff --git a/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs b/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs index b39e94e00d1dc9..f74a4012747489 100644 --- a/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeOnlyTests.cs @@ -483,6 +483,17 @@ public static void TryFormatTest() Assert.False(timeOnly.TryFormat(buffer.Slice(0, 3), out charsWritten)); Assert.False(timeOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "r")); Assert.False(timeOnly.TryFormat(buffer.Slice(0, 3), out charsWritten, "O")); + + Assert.Throws(() => { + Span buff = stackalloc char[100]; + timeOnly.TryFormat(buff, out charsWritten, "u"); + }); + Assert.Throws(() => { + Span buff = stackalloc char[100]; + timeOnly.TryFormat(buff, out charsWritten, "dd-yyyy"); + }); + Assert.Throws(() => $"{timeOnly:u}"); + Assert.Throws(() => $"{timeOnly:dd-yyyy}"); } } } diff --git a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs index 38c8bd8c3393a0..236adb890ec175 100644 --- a/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs +++ b/src/libraries/System.Runtime/tests/System/TimeZoneInfoTests.cs @@ -87,7 +87,7 @@ public static void Names() // Name abbreviations, if available, are used instead public static IEnumerable Platform_TimeZoneNamesTestData() { - if (PlatformDetection.IsBrowser) + if (PlatformDetection.IsBrowser || PlatformDetection.IsiOS || PlatformDetection.IstvOS) return new TheoryData { { TimeZoneInfo.FindSystemTimeZoneById(s_strPacific), "(UTC-08:00) America/Los_Angeles", "PST", "PDT" }, @@ -125,7 +125,6 @@ public static IEnumerable Platform_TimeZoneNamesTestData() // We test the existence of a specific English time zone name to avoid failures on non-English platforms. [ConditionalTheory(nameof(IsEnglishUILanguage))] [MemberData(nameof(Platform_TimeZoneNamesTestData))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52072", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void Platform_TimeZoneNames(TimeZoneInfo tzi, string displayName, string standardName, string daylightName) { // Edge case - Optionally allow some characters to be absent in the display name. @@ -2542,6 +2541,30 @@ public static void NJulianRuleTest(string posixRule, int dayNumber, int monthNum } } + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public static void TimeZoneInfo_LocalZoneWithInvariantMode() + { + string hostTZId = TimeZoneInfo.Local.Id; + + ProcessStartInfo psi = new ProcessStartInfo() { UseShellExecute = false }; + psi.Environment.Add("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT", PlatformDetection.IsInvariantGlobalization ? "0" : "1"); + + RemoteExecutor.Invoke((tzId, hostIsRunningInInvariantMode) => + { + bool hostInvariantMode = bool.Parse(hostIsRunningInInvariantMode); + + if (!hostInvariantMode) + { + // If hostInvariantMode is false, means the child process should enable the globalization invariant mode. + // We validate here that by trying to create a culture which should throws in such mode. + Assert.Throws(() => CultureInfo.GetCultureInfo("en-US")); + } + + Assert.Equal(tzId, TimeZoneInfo.Local.Id); + + }, hostTZId, PlatformDetection.IsInvariantGlobalization.ToString(), new RemoteInvokeOptions { StartInfo = psi}).Dispose(); + } + [Fact] public static void TimeZoneInfo_DaylightDeltaIsNoMoreThan12Hours() { @@ -2623,10 +2646,9 @@ public static void EnsureUtcObjectSingleton() [InlineData("Argentina Standard Time", "America/Argentina/Catamarca")] [InlineData("Newfoundland Standard Time", "America/St_Johns")] [InlineData("Iran Standard Time", "Asia/Tehran")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52072", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void UsingAlternativeTimeZoneIdsTest(string windowsId, string ianaId) { - if (PlatformDetection.ICUVersion.Major >= 52) + if (PlatformDetection.ICUVersion.Major >= 52 && !PlatformDetection.IsiOS && !PlatformDetection.IstvOS) { TimeZoneInfo tzi1 = TimeZoneInfo.FindSystemTimeZoneById(ianaId); TimeZoneInfo tzi2 = TimeZoneInfo.FindSystemTimeZoneById(windowsId); @@ -2641,14 +2663,33 @@ public static void UsingAlternativeTimeZoneIdsTest(string windowsId, string iana } } - public static bool SupportIanaNamesConversion => PlatformDetection.IsNotBrowser && PlatformDetection.ICUVersion.Major >= 52; + public static bool SupportIanaNamesConversion => PlatformDetection.IsNotMobile && PlatformDetection.ICUVersion.Major >= 52; + public static bool SupportIanaNamesConversionAndRemoteExecution => SupportIanaNamesConversion && RemoteExecutor.IsSupported; + + // This test is executed using the remote execution because it needs to run before creating the time zone cache to ensure testing with that state. + // There are already other tests that test after creating the cache. + [ConditionalFact(nameof(SupportIanaNamesConversionAndRemoteExecution))] + public static void IsIanaIdWithNotCacheTest() + { + RemoteExecutor.Invoke(() => + { + Assert.Equal(!s_isWindows || TimeZoneInfo.Local.Id.Equals("Utc", StringComparison.OrdinalIgnoreCase), TimeZoneInfo.Local.HasIanaId); + + TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time"); + Assert.False(tzi.HasIanaId); + + tzi = TimeZoneInfo.FindSystemTimeZoneById("Europe/Berlin"); + Assert.True(tzi.HasIanaId); + }).Dispose(); + } [ConditionalFact(nameof(SupportIanaNamesConversion))] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52072", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void IsIanaIdTest() { bool expected = !s_isWindows; + Assert.Equal((expected || TimeZoneInfo.Local.Id.Equals("Utc", StringComparison.OrdinalIgnoreCase)), TimeZoneInfo.Local.HasIanaId); + foreach (TimeZoneInfo tzi in TimeZoneInfo.GetSystemTimeZones()) { Assert.True((expected || tzi.Id.Equals("Utc", StringComparison.OrdinalIgnoreCase)) == tzi.HasIanaId, $"`{tzi.Id}` has wrong IANA Id indicator"); @@ -2674,7 +2715,6 @@ public static void IsIanaIdTest() [InlineData("Argentina Standard Time", "America/Buenos_Aires")] [InlineData("Newfoundland Standard Time", "America/St_Johns")] [InlineData("Iran Standard Time", "Asia/Tehran")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52072", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void IdsConversionsTest(string windowsId, string ianaId) { Assert.True(TimeZoneInfo.TryConvertIanaIdToWindowsId(ianaId, out string winId)); @@ -2709,7 +2749,6 @@ public static void IdsConversionsTest(string windowsId, string ianaId) [InlineData("GMT Standard Time", "Europe/Dublin", "ie")] [InlineData("W. Europe Standard Time", "Europe/Rome", "it")] [InlineData("New Zealand Standard Time", "Pacific/Auckland", "nz")] - [ActiveIssue("https://github.com/dotnet/runtime/issues/52072", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] public static void IdsConversionsWithRegionTest(string windowsId, string ianaId, string region) { Assert.True(TimeZoneInfo.TryConvertWindowsIdToIanaId(windowsId, region, out string ianaConvertedId)); @@ -2834,6 +2873,20 @@ public static void AdjustmentRuleBaseUtcOffsetDeltaTest() Assert.Equal(new TimeSpan(2, 0, 0), customTimeZone.GetUtcOffset(new DateTime(2021, 3, 10, 2, 0, 0))); } + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/64111", TestPlatforms.Linux)] + public static void NoBackwardTimeZones() + { + ReadOnlyCollection tzCollection = TimeZoneInfo.GetSystemTimeZones(); + HashSet tzDisplayNames = new HashSet(); + + foreach (TimeZoneInfo timezone in tzCollection) + { + tzDisplayNames.Add(timezone.DisplayName); + } + Assert.Equal(tzCollection.Count, tzDisplayNames.Count); + } + private static bool IsEnglishUILanguage => CultureInfo.CurrentUICulture.Name.Length == 0 || CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "en"; private static bool IsEnglishUILanguageAndRemoteExecutorSupported => IsEnglishUILanguage && RemoteExecutor.IsSupported; @@ -3062,6 +3115,14 @@ private static unsafe int EnumUiLanguagesCallback(char* lpUiLanguageString, IntP // native string is null terminated var cultureName = new string(lpUiLanguageString); + string tzResourceFilePath = Path.Join(Environment.SystemDirectory, cultureName, "tzres.dll.mui"); + if (!File.Exists(tzResourceFilePath)) + { + // If Windows installed a UI language but did not include the time zone resources DLL for that language, + // then skip this language as .NET will not be able to get the localized resources for that language. + return 1; + } + try { var handle = GCHandle.FromIntPtr(lParam); diff --git a/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs b/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs index f8816f13a62ab7..a749e939d226e3 100644 --- a/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs +++ b/src/libraries/System.Runtime/tests/System/Type/TypeTests.cs @@ -923,6 +923,16 @@ public void IsContextful() Assert.True(!typeof(ContextBoundClass).IsContextful); } + [Fact] + public void MakeGenericType_NonRuntimeType() + { + foreach (Type nonRuntimeType in Helpers.NonRuntimeTypes) + { + Type t = typeof(List<>).MakeGenericType(nonRuntimeType); + Assert.NotNull(t); + } + } + #region GetInterfaceMap tests public static IEnumerable GetInterfaceMap_TestData() { diff --git a/src/libraries/System.Security.AccessControl/NuGet.config b/src/libraries/System.Security.AccessControl/NuGet.config new file mode 100644 index 00000000000000..a66b7f9b013241 --- /dev/null +++ b/src/libraries/System.Security.AccessControl/NuGet.config @@ -0,0 +1,12 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.Evidence.cs b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.Evidence.cs deleted file mode 100644 index 9c42db1a8f5189..00000000000000 --- a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.Evidence.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// ------------------------------------------------------------------------------ -// Changes to this file must follow the https://aka.ms/api-review process. -// ------------------------------------------------------------------------------ - -#nullable enable - -namespace System.Security.Policy -{ - public sealed partial class Evidence : System.Collections.ICollection, System.Collections.IEnumerable - { - public Evidence() { } - [System.ObsoleteAttribute("This constructor is obsolete. Use the constructor which accepts arrays of EvidenceBase instead.")] - public Evidence(object[] hostEvidence, object[] assemblyEvidence) { } - public Evidence(System.Security.Policy.Evidence evidence) { } - public Evidence(System.Security.Policy.EvidenceBase[] hostEvidence, System.Security.Policy.EvidenceBase[] assemblyEvidence) { } - [System.ObsoleteAttribute("Evidence should not be treated as an ICollection. Use GetHostEnumerator and GetAssemblyEnumerator to iterate over the evidence to collect a count.")] - public int Count { get { throw null; } } - public bool IsReadOnly { get { throw null; } } - public bool IsSynchronized { get { throw null; } } - public bool Locked { get { throw null; } set { } } - public object SyncRoot { get { throw null; } } - [System.ObsoleteAttribute("Evidence.AddAssembly has been deprecated. Use AddAssemblyEvidence instead.")] - public void AddAssembly(object id) { } - public void AddAssemblyEvidence(T evidence) where T : System.Security.Policy.EvidenceBase { } - [System.ObsoleteAttribute("Evidence.AddHost has been deprecated. Use AddHostEvidence instead.")] - public void AddHost(object id) { } - public void AddHostEvidence(T evidence) where T : System.Security.Policy.EvidenceBase { } - public void Clear() { } - public System.Security.Policy.Evidence? Clone() { throw null; } - [System.ObsoleteAttribute("Evidence should not be treated as an ICollection. Use the GetHostEnumerator and GetAssemblyEnumerator methods rather than using CopyTo.")] - public void CopyTo(System.Array array, int index) { } - public System.Collections.IEnumerator GetAssemblyEnumerator() { throw null; } - public T? GetAssemblyEvidence() where T : System.Security.Policy.EvidenceBase { throw null; } - [System.ObsoleteAttribute("GetEnumerator is obsolete. Use GetAssemblyEnumerator and GetHostEnumerator instead.")] - public System.Collections.IEnumerator GetEnumerator() { throw null; } - public System.Collections.IEnumerator GetHostEnumerator() { throw null; } - public T? GetHostEvidence() where T : System.Security.Policy.EvidenceBase { throw null; } - public void Merge(System.Security.Policy.Evidence evidence) { } - public void RemoveType(System.Type t) { } - } - public abstract partial class EvidenceBase - { - protected EvidenceBase() { } - public virtual System.Security.Policy.EvidenceBase? Clone() { throw null; } - } -} diff --git a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.cs b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.cs index b47ecfdc101652..e7007ca46d5046 100644 --- a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.cs +++ b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.cs @@ -530,3 +530,44 @@ public void SetAudit(System.Security.AccessControl.AuditFlags auditFlags, System public void SetAudit(System.Security.Principal.SecurityIdentifier sid, System.Security.AccessControl.ObjectAuditRule rule) { } } } + +namespace System.Security.Policy +{ + public sealed partial class Evidence : System.Collections.ICollection, System.Collections.IEnumerable + { + public Evidence() { } + [System.ObsoleteAttribute("This constructor is obsolete. Please use the constructor which takes arrays of EvidenceBase instead.")] + public Evidence(object[] hostEvidence, object[] assemblyEvidence) { } + public Evidence(System.Security.Policy.Evidence evidence) { } + public Evidence(System.Security.Policy.EvidenceBase[] hostEvidence, System.Security.Policy.EvidenceBase[] assemblyEvidence) { } + [System.ObsoleteAttribute("Evidence should not be treated as an ICollection. Please use GetHostEnumerator and GetAssemblyEnumerator to iterate over the evidence to collect a count.")] + public int Count { get { throw null; } } + public bool IsReadOnly { get { throw null; } } + public bool IsSynchronized { get { throw null; } } + public bool Locked { get { throw null; } set { } } + public object SyncRoot { get { throw null; } } + [System.ObsoleteAttribute("This method is obsolete. Please use AddAssemblyEvidence instead.")] + public void AddAssembly(object id) { } + public void AddAssemblyEvidence(T evidence) where T : System.Security.Policy.EvidenceBase { } + [System.ObsoleteAttribute("This method is obsolete. Please use AddHostEvidence instead.")] + public void AddHost(object id) { } + public void AddHostEvidence(T evidence) where T : System.Security.Policy.EvidenceBase { } + public void Clear() { } + public System.Security.Policy.Evidence? Clone() { throw null; } + [System.ObsoleteAttribute("Evidence should not be treated as an ICollection. Please use the GetHostEnumerator and GetAssemblyEnumerator methods rather than using CopyTo.")] + public void CopyTo(System.Array array, int index) { } + public System.Collections.IEnumerator GetAssemblyEnumerator() { throw null; } + public T? GetAssemblyEvidence() where T : System.Security.Policy.EvidenceBase { throw null; } + [System.ObsoleteAttribute("GetEnumerator is obsolete. Please use GetAssemblyEnumerator and GetHostEnumerator instead.")] + public System.Collections.IEnumerator GetEnumerator() { throw null; } + public System.Collections.IEnumerator GetHostEnumerator() { throw null; } + public T? GetHostEvidence() where T : System.Security.Policy.EvidenceBase { throw null; } + public void Merge(System.Security.Policy.Evidence evidence) { } + public void RemoveType(System.Type t) { } + } + public abstract partial class EvidenceBase + { + protected EvidenceBase() { } + public virtual System.Security.Policy.EvidenceBase? Clone() { throw null; } + } +} diff --git a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.csproj b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.csproj index 348ff2fe1971ed..d2f2a11fc11313 100644 --- a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.csproj +++ b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.csproj @@ -1,13 +1,16 @@ - $(NetCoreAppCurrent) + $(NetCoreAppCurrent);netstandard2.0;net461 enable - - + + - + + + + \ No newline at end of file diff --git a/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.net461.cs b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.net461.cs new file mode 100644 index 00000000000000..9fa292c50bbb76 --- /dev/null +++ b/src/libraries/System.Security.AccessControl/ref/System.Security.AccessControl.net461.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +using System.Runtime.CompilerServices; + +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AccessControlActions))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AccessControlModification))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AccessControlSections))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AccessControlType))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AccessRule))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AccessRule<>))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AceEnumerator))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AceFlags))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AceQualifier))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AceType))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AuditFlags))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AuditRule))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AuditRule<>))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AuthorizationRule))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.AuthorizationRuleCollection))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CommonAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CommonAcl))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CommonObjectSecurity))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CommonSecurityDescriptor))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CompoundAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CompoundAceType))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ControlFlags))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.CustomAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.DiscretionaryAcl))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.GenericAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.GenericAcl))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.GenericSecurityDescriptor))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.InheritanceFlags))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.KnownAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.NativeObjectSecurity))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ObjectAccessRule))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ObjectAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ObjectAceFlags))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ObjectAuditRule))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ObjectSecurity))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ObjectSecurity<>))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.PrivilegeNotHeldException))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.PropagationFlags))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.QualifiedAce))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.RawAcl))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.RawSecurityDescriptor))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.ResourceType))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.SecurityInfos))] +[assembly: TypeForwardedTo(typeof(System.Security.AccessControl.SystemAcl))] diff --git a/src/libraries/System.Security.AccessControl/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.AccessControl/src/CompatibilitySuppressions.xml new file mode 100644 index 00000000000000..6cb765819a0e14 --- /dev/null +++ b/src/libraries/System.Security.AccessControl/src/CompatibilitySuppressions.xml @@ -0,0 +1,37 @@ + + + + CP0001 + T:System.Security.Policy.Evidence + lib/netstandard2.0/System.Security.AccessControl.dll + lib/net461/System.Security.AccessControl.dll + + + CP0001 + T:System.Security.Policy.EvidenceBase + lib/netstandard2.0/System.Security.AccessControl.dll + lib/net461/System.Security.AccessControl.dll + + + CP0002 + M:System.Security.AccessControl.ObjectSecurity.get_SecurityDescriptor + lib/netstandard2.0/System.Security.AccessControl.dll + lib/net461/System.Security.AccessControl.dll + + + PKV006 + .NETFramework,Version=v4.6 + + + PKV006 + .NETStandard,Version=v1.3 + + + PKV007 + .NETFramework,Version=v4.6-win + + + PKV007 + .NETStandard,Version=v1.3-win + + \ No newline at end of file diff --git a/src/libraries/System.Security.AccessControl/src/ILLink/ILLink.Descriptors.LibraryBuild.xml b/src/libraries/System.Security.AccessControl/src/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 00000000000000..881d8ee5fd369b --- /dev/null +++ b/src/libraries/System.Security.AccessControl/src/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj b/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj index ae2bd9f64570a4..ee7ab7edc3ad73 100644 --- a/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj +++ b/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj @@ -1,14 +1,24 @@ true - $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent) + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);netstandard2.0-windows;netstandard2.0;net461-windows + true + Provides base classes that enable managing access and audit control lists on securable objects. + +Commonly Used Types: +System.Security.AccessControl.AccessRule +System.Security.AccessControl.AuditRule +System.Security.AccessControl.ObjectAccessRule +System.Security.AccessControl.ObjectAuditRule +System.Security.AccessControl.ObjectSecurity enable + true SR.PlatformNotSupported_AccessControl - + @@ -78,8 +88,7 @@ - - + @@ -87,8 +96,12 @@ + + + + diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Windows.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Windows.cs index c72dcb4c932499..e9275bc28ae3cc 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Windows.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/Pbkdf2Implementation.Windows.cs @@ -16,9 +16,9 @@ namespace Internal.Cryptography { internal static partial class Pbkdf2Implementation { - // For Windows 7 we will use BCryptDeriveKeyPBKDF2. For Windows 8+ we will use BCryptKeyDerivation - // since it has better performance. - private static readonly bool s_useKeyDerivation = OperatingSystem.IsWindowsVersionAtLeast(8, 0, 0); + // For Windows 7 we will use BCryptDeriveKeyPBKDF2. For Windows 8+ (seen as version 6.2.0) we will + // use BCryptKeyDerivation since it has better performance. + private static readonly bool s_useKeyDerivation = OperatingSystem.IsWindowsVersionAtLeast(6, 2); // A cached instance of PBKDF2 for Windows 8, where pseudo handles are not supported. private static SafeBCryptAlgorithmHandle? s_pbkdf2AlgorithmHandle; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs b/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs index dc5738441db564..38f57040589962 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/tests/HashAlgorithmTest.cs @@ -488,6 +488,30 @@ public void Initialize_TransformBlock_Unused() } } + [Fact] + public void Initialize_DoubleInitialize_Works() + { + byte[] hashInput = new byte[] { 1, 2, 3, 4, 5 }; + byte[] expectedDigest; + + using (HashAlgorithm hash = Create()) + { + expectedDigest = hash.ComputeHash(hashInput); + } + + using (HashAlgorithm hash = Create()) + { + byte[] buffer = new byte[1024]; + hash.TransformBlock(buffer, 0, buffer.Length, buffer, 0); + hash.Initialize(); + hash.TransformFinalBlock(Array.Empty(), 0, 0); + hash.Initialize(); + hash.TransformFinalBlock(hashInput, 0, hashInput.Length); + + Assert.Equal(expectedDigest, hash.Hash); + } + } + protected class DataRepeatingStream : Stream { private int _remaining; diff --git a/src/libraries/System.Security.Cryptography.Encoding/tests/AsnEncodedData.cs b/src/libraries/System.Security.Cryptography.Encoding/tests/AsnEncodedData.cs index 0f63a74998dd43..bb1b734a8e5311 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/tests/AsnEncodedData.cs +++ b/src/libraries/System.Security.Cryptography.Encoding/tests/AsnEncodedData.cs @@ -101,11 +101,12 @@ public static void TestSubjectAlternativeName_Unix() sanExtension); string s = asnData.Format(false); + bool isOpenSsl3 = PlatformDetection.IsOpenSsl3; string expected = string.Join( ", ", // Choice[0]: OtherName - "othername:", + isOpenSsl3 ? "othername: UPN::subjectupn1@example.org" : "othername:", // Choice[1]: Rfc822Name (EmailAddress) "email:sanemail1@example.org", // Choice[2]: DnsName @@ -123,7 +124,7 @@ public static void TestSubjectAlternativeName_Unix() // Choice[7]: IPAddress (IPv6) "IP Address:2001:DB8:AC10:FE01:0:0:0:0", // Choice[7]: IPAddress (unknown type) - "IP Address:", + isOpenSsl3 ? "IP Address:" : "IP Address:", // Choice[7]: IPAddress (IPv4, longer string) "IP Address:255.255.255.255", // Choice[7]: IPAddress (IPv4, medium string) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml index 59a3d702ec042e..b56749eac2c275 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Security.Cryptography.Pkcs/src/CompatibilitySuppressions.xml @@ -1,7 +1,86 @@ - + - CP0001 + CP0002 + M:System.Security.Cryptography.Pkcs.CmsSigner.get_PrivateKey + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.CmsSigner.set_PrivateKey(System.Security.Cryptography.AsymmetricAlgorithm) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.CmsSigner.#ctor(System.Security.Cryptography.Pkcs.SubjectIdentifierType,System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.AsymmetricAlgorithm) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.ContentInfo.GetContentType(System.ReadOnlySpan{System.Byte}) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.EnvelopedCms.Decode(System.ReadOnlySpan{System.Byte}) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.EnvelopedCms.Decrypt(System.Security.Cryptography.Pkcs.RecipientInfo,System.Security.Cryptography.AsymmetricAlgorithm) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignedCms.Decode(System.ReadOnlySpan{System.Byte}) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignedCms.AddCertificate(System.Security.Cryptography.X509Certificates.X509Certificate2) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignedCms.RemoveCertificate(System.Security.Cryptography.X509Certificates.X509Certificate2) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignerInfo.GetSignature + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignerInfo.get_SignatureAlgorithm + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignerInfo.AddUnsignedAttribute(System.Security.Cryptography.AsnEncodedData) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SignerInfo.RemoveUnsignedAttribute(System.Security.Cryptography.AsnEncodedData) + lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll + lib/net461/System.Security.Cryptography.Pkcs.dll + + + CP0002 + M:System.Security.Cryptography.Pkcs.SubjectIdentifier.MatchesCertificate(System.Security.Cryptography.X509Certificates.X509Certificate2) lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll lib/net461/System.Security.Cryptography.Pkcs.dll diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs index 9d90fe7905550f..cfa17458204e57 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs @@ -377,6 +377,7 @@ public static void AddAttributeToIndefiniteLengthContent() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public static void AddSigner_RSA_EphemeralKey() { using (RSA rsa = RSA.Create()) @@ -435,6 +436,7 @@ public static void AddSigner_DSA_EphemeralKey() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public static void AddSigner_ECDSA_EphemeralKey() { using (ECDsa ecdsa = ECDsa.Create()) diff --git a/src/libraries/System.Security.Cryptography.ProtectedData/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.Cryptography.ProtectedData/src/CompatibilitySuppressions.xml index 40864690636e2e..1fabb2d07af7b1 100644 --- a/src/libraries/System.Security.Cryptography.ProtectedData/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Security.Cryptography.ProtectedData/src/CompatibilitySuppressions.xml @@ -1,17 +1,5 @@ - + - - CP0001 - T:System.Security.Cryptography.DataProtectionScope - lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll - lib/net461/System.Security.Cryptography.ProtectedData.dll - - - CP0001 - T:System.Security.Cryptography.ProtectedData - lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll - lib/net461/System.Security.Cryptography.ProtectedData.dll - PKV006 .NETFramework,Version=v4.6 diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs index e31f2c3a84a0cf..0392b093e87d7c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/CollectionTests.cs @@ -833,6 +833,7 @@ public static void ExportMultiplePrivateKeys() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public static void CanAddMultipleCertsWithSinglePrivateKey() { using (var oneWithKey = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, X509KeyStorageFlags.Exportable | Cert.EphemeralIfPossible)) @@ -899,7 +900,13 @@ public static void X509ChainElementCollection_CopyTo_NonZeroLowerBound_ThrowsInd chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags; - chain.Build(microsoftDotCom); + // Halfway between microsoftDotCom's NotBefore and NotAfter + // This isn't a boundary condition test. + chain.ChainPolicy.VerificationTime = new DateTime(2021, 02, 26, 12, 01, 01, DateTimeKind.Local); + + bool valid = chain.Build(microsoftDotCom); + Assert.True(valid, "Precondition: Chain built validly"); + ICollection collection = chain.ChainElements; Array array = Array.CreateInstance(typeof(object), new int[] { 10 }, new int[] { 10 }); Assert.Throws(() => collection.CopyTo(array, 0)); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs index 0051bc4da70e67..951a1329b77244 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/ExportTests.cs @@ -104,6 +104,7 @@ public static void ExportAsPfxVerifyPassword() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public static void ExportAsPfxWithPrivateKeyVerifyPassword() { using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, X509KeyStorageFlags.Exportable)) @@ -124,6 +125,7 @@ public static void ExportAsPfxWithPrivateKeyVerifyPassword() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public static void ExportAsPfxWithPrivateKey() { using (X509Certificate2 cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, X509KeyStorageFlags.Exportable)) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.SingleCertGenerator.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.SingleCertGenerator.cs index de3a5f18004e4e..3fad2b9d3beb08 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.SingleCertGenerator.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.SingleCertGenerator.cs @@ -62,6 +62,7 @@ public static IEnumerable AllSingleCertVariations [Theory] [MemberData(nameof(AllSingleCertVariations))] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCertWithOneKey(SingleCertOptions options) { bool sameContainer = (options & SingleCertOptions.KeyAndCertInSameContents) != 0; diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.cs index 3b83ac201e5097..c73af1ac3173a7 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxFormatTests.cs @@ -158,6 +158,7 @@ public void EmptyPfx_BadPassword() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_NoKeys_EncryptedNullPassword_NoMac() { using (X509Certificate2 cert = new X509Certificate2(TestData.MsCertificate)) @@ -175,6 +176,7 @@ public void OneCert_NoKeys_EncryptedNullPassword_NoMac() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_NoKeys_EncryptedEmptyPassword_NoMac() { using (X509Certificate2 cert = new X509Certificate2(TestData.MsCertificate)) @@ -196,6 +198,7 @@ public void OneCert_NoKeys_EncryptedEmptyPassword_NoMac() [InlineData(false, true)] [InlineData(true, false)] [InlineData(true, true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_EncryptedEmptyPassword_OneKey_EncryptedNullPassword_NoMac(bool encryptKeySafe, bool associateKey) { // This test shows that while a null or empty password will result in both @@ -237,6 +240,7 @@ public void OneCert_EncryptedEmptyPassword_OneKey_EncryptedNullPassword_NoMac(bo } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_MismatchedKey() { string pw = nameof(OneCert_MismatchedKey); @@ -285,6 +289,7 @@ public void OneCert_MismatchedKey() [Theory] [InlineData(false)] [InlineData(true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_TwoKeys_FirstWins(bool correctKeyFirst) { string pw = nameof(OneCert_TwoKeys_FirstWins); @@ -356,6 +361,7 @@ public void OneCert_TwoKeys_FirstWins(bool correctKeyFirst) [Theory] [InlineData(false)] [InlineData(true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void TwoCerts_OneKey(bool certWithKeyFirst) { string pw = nameof(TwoCerts_OneKey); @@ -400,6 +406,7 @@ public void TwoCerts_OneKey(bool certWithKeyFirst) } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_ExtraKeyWithUnknownAlgorithm() { string pw = nameof(OneCert_ExtraKeyWithUnknownAlgorithm); @@ -445,6 +452,7 @@ public void OneCert_ExtraKeyWithUnknownAlgorithm() [Theory] [InlineData(true)] [InlineData(false)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_ExtraKeyBadEncoding(bool badTag) { string pw = nameof(OneCert_ExtraKeyBadEncoding); @@ -503,6 +511,7 @@ public void OneCert_ExtraKeyBadEncoding(bool badTag) } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_NoKey_WithLocalKeyId() { string pw = nameof(OneCert_NoKey_WithLocalKeyId); @@ -524,6 +533,7 @@ public void OneCert_NoKey_WithLocalKeyId() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void OneCert_TwentyKeys_NoMatches() { string pw = nameof(OneCert_NoKey_WithLocalKeyId); @@ -562,6 +572,7 @@ public void OneCert_TwentyKeys_NoMatches() [Theory] [InlineData(true)] [InlineData(false)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void TwoCerts_TwentyKeys_NoMatches(bool msCertFirst) { string pw = nameof(OneCert_NoKey_WithLocalKeyId); @@ -635,6 +646,7 @@ public void OneCorruptCert() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void CertAndKey_NoLocalKeyId() { string pw = nameof(CertAndKey_NoLocalKeyId); @@ -661,6 +673,7 @@ public void CertAndKey_NoLocalKeyId() [Theory] [InlineData(false)] [InlineData(true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void SameCertTwice_NoKeys(bool addLocalKeyId) { string pw = nameof(SameCertTwice_NoKeys); @@ -692,6 +705,7 @@ public void SameCertTwice_NoKeys(bool addLocalKeyId) } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void TwoCerts_CrossedKeys() { string pw = nameof(TwoCerts_CrossedKeys); @@ -766,6 +780,7 @@ public void TwoCerts_CrossedKeys() [InlineData(false, false)] [InlineData(true, false)] [InlineData(true, true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void CertAndKeyTwice(bool addLocalKeyId, bool crossIdentifiers) { string pw = nameof(CertAndKeyTwice); @@ -821,6 +836,7 @@ public void CertAndKeyTwice(bool addLocalKeyId, bool crossIdentifiers) } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void CertAndKeyTwice_KeysUntagged() { string pw = nameof(CertAndKeyTwice); @@ -873,6 +889,7 @@ public void CertAndKeyTwice_KeysUntagged() [Theory] [InlineData(false)] [InlineData(true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void CertTwice_KeyOnce(bool addLocalKeyId) { string pw = nameof(CertTwice_KeyOnce); @@ -930,6 +947,7 @@ public void CertTwice_KeyOnce(bool addLocalKeyId) [Theory] [InlineData(false)] [InlineData(true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void CertTwice_KeyOnce_OtherCertBetter(bool addLocalKeyId) { string pw = nameof(CertTwice_KeyOnce); @@ -990,6 +1008,7 @@ public void CertTwice_KeyOnce_OtherCertBetter(bool addLocalKeyId) [InlineData(false, true)] [InlineData(true, false)] [InlineData(true, true)] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public void TwoCerts_TwoKeys_ManySafeContentsValues(bool invertCertOrder, bool invertKeyOrder) { string pw = nameof(TwoCerts_TwoKeys_ManySafeContentsValues); diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs index bd853f1e098be6..1132d8d85a406b 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PfxTests.cs @@ -141,6 +141,7 @@ private static void VerifyPrivateKey(RSA rsa) [Theory] [MemberData(nameof(StorageFlags))] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS, "The PKCS#12 Exportable flag is not supported on iOS/MacCatalyst/tvOS")] public static void ExportWithPrivateKey(X509KeyStorageFlags keyStorageFlags) { using (var cert = new X509Certificate2(TestData.PfxData, TestData.PfxDataPassword, X509KeyStorageFlags.Exportable | keyStorageFlags)) diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PropsTests.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PropsTests.cs index 4a78718b91be33..a2759f5126dd46 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/PropsTests.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/PropsTests.cs @@ -389,6 +389,20 @@ public static void TestGetNameInfo() } } + [Theory] + [InlineData(true)] + [InlineData(false)] + public static void GetNameInfo_HandlesUtf8Encoding(bool issuer) + { + using (X509Certificate2 c = new X509Certificate2(TestData.CertificateWithUtf8)) + { + // Russian word for "potato" in Cyrillic, kartoshka. + string expected = "\u043A\u0430\u0440\u0442\u043E\u0448\u043A\u0430"; + string cn = c.GetNameInfo(X509NameType.SimpleName, issuer); + Assert.Equal(expected, cn); + } + } + [Fact] public static void ComplexGetNameInfo_SimpleName_Cert() { diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs index a738e45375ecab..df98b93190cf3c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/TestData.cs @@ -2463,6 +2463,33 @@ internal struct ECDsaCngKeyValues "028bedeefab9a2be80466fe278fdc50db1b9530e1796b23271b4df2cddd9" + "4769c8a21a8f66c6d4bc181713").HexToByteArray(); + internal static byte[] CertificateWithUtf8 = ( + "30820315308201fda003020102020900e48b784d93645921300d06092a864886" + + "f70d01010b0500301b3119301706035504030c10d0bad0b0d180d182d0bed188" + + "d0bad0b0301e170d3231303931343230353635365a170d333230383237323035" + + "3635365a301b3119301706035504030c10d0bad0b0d180d182d0bed188d0bad0" + + "b030820122300d06092a864886f70d01010105000382010f003082010a028201" + + "0100c394711b3839a612aaadafde855ccc3479bc1dbe253a29e508cc46464efb" + + "ab09b16b85fb67e4be0ab8b09fa6ff73cb3ec5d8f8b7d2869a79c414d025a43e" + + "4c158c9711638dbfb070ef92b3633037d5e633a870ed024ab9017c97e26f02de" + + "2273dd92c0837a95ff12229981cd661b140afd841671d3397fd44aea05878dd0" + + "9362bd2de8da17225dd3caf0181aadf2c9e13faefbbce3ce80ef355dcc15c1b9" + + "c6e86bb1cddf32b3113e7a72ad3799cc67f64ea34c0518c22727972802084801" + + "e6565b2323e87fd20019a9db151e87b2b1db004583e15dd64c5393439a0ba5ed" + + "3b9fd262c8d8bf0263dcba092ca5591d4d34f990daa9ee41811cec6229f2121b" + + "582f0203010001a35c305a301b0603551d11041430128210786e2d2d38306161" + + "326162746c6f3363301d0603551d250416301406082b0601050507030106082b" + + "06010505070302300f0603551d130101ff040530030101ff300b0603551d0f04" + + "040302028c300d06092a864886f70d01010b050003820101001c0512d3d99267" + + "4ca3a1fdf942052064ffbda824aaeff07d9869eefa86e592102afca0dba4e267" + + "e54753552fc23da97b18f739ea437794aac5bb2ae7413ae54ce921b4b96fe420" + + "f3fd86f922adcab202589823c4095fc6e7904e61be1716faec7e09ce2d1bf431" + + "fa9fc2d7284689d2c940f7d027e16b9c3305f9cd6d5dc6bfee9089d85d342f5b" + + "d07920c51899288674a1732708a7e3a39fb11c152417d50a3bb9b09975852baa" + + "39767c289baea9330902ea38388932964c410cd22049415712223fb5710a21ef" + + "153ac22391a1603547ffb3f9b328c59e59b5d64568b9c451df233fe9a581116f" + + "05be8c67b92bc7df9984f30535ad53817cb4abcd77cb521856").HexToByteArray(); + internal static byte[] ConcatenatedPemFile = ByteUtils.AsciiBytes( @"-----BEGIN CERTIFICATE----- MIIFcDCCBFigAwIBAgIQB6krbZc11OZ5l2/FnU3CpTANBgkqhkiG9w0BAQsFADBG diff --git a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj index dca38dde22bf8b..b59549e50afa2c 100644 --- a/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/ref/System.Security.Cryptography.Xml.csproj @@ -13,7 +13,7 @@ - + diff --git a/src/libraries/System.Security.Cryptography.Xml/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.Cryptography.Xml/src/CompatibilitySuppressions.xml index 174055d48008ee..dd6795c03dbeae 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Security.Cryptography.Xml/src/CompatibilitySuppressions.xml @@ -1,7 +1,44 @@ - + + + CP0002 + F:System.Security.Cryptography.Xml.SignedXml.XmlDsigSHA256Url + lib/netstandard2.0/System.Security.Cryptography.Xml.dll + lib/net461/System.Security.Cryptography.Xml.dll + + + CP0002 + F:System.Security.Cryptography.Xml.SignedXml.XmlDsigRSASHA256Url + lib/netstandard2.0/System.Security.Cryptography.Xml.dll + lib/net461/System.Security.Cryptography.Xml.dll + + + CP0002 + F:System.Security.Cryptography.Xml.SignedXml.XmlDsigSHA384Url + lib/netstandard2.0/System.Security.Cryptography.Xml.dll + lib/net461/System.Security.Cryptography.Xml.dll + + + CP0002 + F:System.Security.Cryptography.Xml.SignedXml.XmlDsigRSASHA384Url + lib/netstandard2.0/System.Security.Cryptography.Xml.dll + lib/net461/System.Security.Cryptography.Xml.dll + + + CP0002 + F:System.Security.Cryptography.Xml.SignedXml.XmlDsigSHA512Url + lib/netstandard2.0/System.Security.Cryptography.Xml.dll + lib/net461/System.Security.Cryptography.Xml.dll + + + CP0002 + F:System.Security.Cryptography.Xml.SignedXml.XmlDsigRSASHA512Url + lib/netstandard2.0/System.Security.Cryptography.Xml.dll + lib/net461/System.Security.Cryptography.Xml.dll + CP0001 + T:System.Security.Cryptography.Xml.CryptoSignedXmlRecursionException lib/netstandard2.0/System.Security.Cryptography.Xml.dll lib/net461/System.Security.Cryptography.Xml.dll diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj index 2417c752edc4b7..133637ef9c56c5 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/src/System.Security.Cryptography.Xml.csproj @@ -1,7 +1,7 @@ true - $(NetCoreAppCurrent);netstandard2.0;net461 + $(NetCoreAppCurrent);netstandard2.0;net461-windows true Provides classes to support the creation and validation of XML digital signatures. The classes in this namespace implement the World Wide Web Consortium Recommendation, "XML-Signature Syntax and Processing", described at http://www.w3.org/TR/xmldsig-core/. @@ -131,7 +131,7 @@ System.Security.Cryptography.Xml.XmlLicenseTransform Link="Common\System\HexConverter.cs" /> - + @@ -143,7 +143,6 @@ System.Security.Cryptography.Xml.XmlLicenseTransform - diff --git a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index cd32ff9c8c4e14..c219bf3e947640 100644 --- a/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);net461 + $(NetCoreAppCurrent);net461-windows GetSymmetricAlgorithms(bool private static readonly byte[] SampleDsaPfx = Convert.FromBase64String( // [SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Suppression approved. Unit test dummy certificate.")] "MIIF+QIBAzCCBb8GCSqGSIb3DQEHAaCCBbAEggWsMIIFqDCCA9cGCSqGSIb3DQEH" + - "BqCCA8gwggPEAgEAMIIDvQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQIbzDq" + - "jr8PwpMCAggAgIIDkJrcDboxMkMgEusycJ0w7QdbskZ7SBvnziqhQ0e2DohHjhrm" + - "p19VRk8nyw0TuHgIVK39KhFbGrfOLWxAE2xvnDVOeWWMLcxDn2zoxPdM202HvXVB" + - "SFE0zAmVOVHD7NMa0pcXeCblqpihGnVgSW5RYHc3hJFaXkBmLe/GLX7rNl+LCXzb" + - "cScJfYw0CMqZHYnpcCG3M6n6aAUb79madtN7UHuVtyaCjStaPfcAUGetlacT79cV" + - "qR57yPG+5Rpb38d5oOE/Jeh/wzB/L2QOq6LWxeWHiXMmXlOJ8xCK64YvfASoIpiQ" + - "xTqtgY2SKA0bOqUcerr4945MAdjR93qLeaEOQAeR+EweSYgasGWyi5ZwDh5ul3bJ" + - "SX2OdK9IkdBnktekbnPvo1necVuN6OjLKLlXyyDLn5KEVTjsAUonLk1nXZ/aL3ZH" + - "iTHWEUB0HyvRN9sQB3Y49ggp6DwLSmKfiglPYMj95k1tAOpi/MD9LnfpTV5ur3q0" + - "sqgIgQgMctaHIUV6vVQ2Ngu8dmOObUgqgDR5Us3Hf1u71Lu2AJBGRoDm7V1hhbgv" + - "Ob4oRlJUdgssi79id5IHog1nnO7VDxxtkKujzUUbSBnrAnxc27/lNQ9jwmUYZnHH" + - "xg9lEI2HNK/3k6FZd6Tiy8hzNN1+fo8hNkwjorsnNPd/nWbVeM/Oti5jEiVoeMfV" + - "/uw1/cGj6KaTvCe3h/xgX9y0/sWZ7WqILXZ+3vAouemvmBRe531IWA1djz//hgSI" + - "VOK+OprshAeU0Pce7qXMbMlOD7CUKBDecn0L7xxWW8sg8ZWgwqZuJEcOjvUKezgK" + - "URivBV1lavevLYyLsBO8W0qLiOLYYOgQkavkz42DYvkDeCJfeE2DuY6tqRr7xBJ5" + - "qGxDWGZ4+oBZYmXkMa63A/VC/EF6ZSVooLxI8QsobyPaB7spKv+YP+LjQgJ7F7dR" + - "3YXxKivW0QuZ2cAkfWpy8CaTGUhucaay8dqBEm7i3aAXSUzWMOayYu2xieu9+2Gl" + - "UuBlr2ic63si37rYemztVcIfSg2Rrtb/ggLT5a22LYBH109LosbR1kMfk7r9Eaz+" + - "TSH3TBaKoN7L56en1I56CvikEmzCbXW9N9bih9+HL7IgHcBN0c/TLkcvTvj2Xm4l" + - "cKpITTGg+KBS7BRNT8DA9Zqpa9aPIaNMrhPPTWEPRYyiMwhFwJw+Of3YLUwmlkhf" + - "gCVpngUFmnJE19pydjCCAckGCSqGSIb3DQEHAaCCAboEggG2MIIBsjCCAa4GCyqG" + - "SIb3DQEMCgECoIIBdjCCAXIwHAYKKoZIhvcNAQwBAzAOBAjknYMUAVMMGwICCAAE" + - "ggFQ4yI0v5ZS62IfP9l1I3llZ1l8SyW8r0F6v/BXBYitXKHoCsK4WbDl6Z4enb/0" + - "DZ8/RyepbiD1S9bqJ5ICXaFEKaBpVSvkVK1EWJF6pM9qx9VzECxVMTFxewdg2UwB" + - "2JkuUAD4tXxmjwp0LQpgJdKHpq7cH0SdoEdNzTsypZnaPBXUIDHS+NfiqPScueqv" + - "W2MoIg8egHIM4qnwLy0/hSc0iMfOgAPVbDktnoq7wzPVG8L+esS84/bABOl9o/e9" + - "Cq8OjK1aVBNMLnktdt0e4I3K7yQFgEJTkq8PpHmpnesv8l7Lvjd9Mri9W8eHilOp" + - "ZICybwoK3A0APG1lswubo0ii/56+MA3DnE0irn1rn6bkpOMGJ8JZBeuGzbV14ah/" + - "4l4MMPjnIf3Cu6TGd2/YLnPdr5fE6vyJtVa1sBpawIAK7cDUJ+OOD8gs1uoMfOML" + - "k5VpMSUwIwYJKoZIhvcNAQkVMRYEFDdYxa4ZJsCeAQZDzHLZ+cdpC2z5MDEwITAJ" + - "BgUrDgMCGgUABBTv022RKjlx16b3xrtvZELrNDdQIAQIaYfksM5jcN8CAggA"); + "BqCCA8gwggPEAgEAMIIDvQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMwDgQIOSCt" + + "zaujK/MCAggAgIIDkEQdcESXtxlkTEwicjcfUahzjrHb8uWLi4AAGKqrchbiUJsj" + + "cAwATdijQhwffUAmQ7+i52P46MViik+aKDw2Otb0Tu5+MzUEQiV+x7ZCzgAinxkE" + + "TlH3Njk6Hfccy+TtITzFwaNXyJMIQS6LdZ1XweV0FdFXCfo9eN2OVM6JrUNhhH6h" + + "io2aujcedtM0iNIaNujgYcRALDVwnozCPj8eeUqlo0vftMPmbAN/y4lIFLj/cXbr" + + "2pSU0QOcB/i/7eMWN12H+E4jA/IXw8sPT0ADKERaDNcRTzeLRTyMTPuuySOiDHkk" + + "t7g8fQ6BXUtVw44TnK/es1BgNZRJvAiNJXrG228anPEXcVM4hiMQ6+/tHyDUaPBm" + + "TZ+bVI0ZD/14VxDicS7KjE7/4aHWY3DHCmtZAS5u4LXOjwEip82gRXcvyuhszbtU" + + "xc9lSptUriraKYj80bTHC4iK+1GJI+qo4cZiuH+qARXez1aT9IjyVlRog/uacrHx" + + "ycbl2fvo81VUyCPmUph93Zr9PWvKmO4BmW3mQeJVqgTZrHfQpkY+SelcyaheniMu" + + "+pdOwmoYWqE2bOg9uSPhlvh+duDBmOr4X+m1YDLb/3sRQcbhDFPANAlss39lLzpl" + + "QS/emRTuiyRpMixl3XHbGz1GF5nJo1OwEysWb5EbaV5w+FM5JzUqc8JAegBcp0Zf" + + "G3uTaC4Wc9Q3703jqV1bhGQK3clR2/O+p6fKwr/POOT/qFxws8o85QEGOYn5GFtz" + + "57gRxpXWWmpsm5QFu6LTWQ4kyMJ4m3CzU54ULjuaFTP63nRLDDCk5iQOvADP4UhH" + + "nfKNI5w7UMQEULTQeLPLz4bsbY0CfsVISaKtqrmyQQHB38YDEs5kdx+Xy6oNSVVh" + + "eIkW2ktgJiSgC8jsjXFDUKsj9rsk8xcCu41YZoWSEs1+lOo7qyReZZQl5AOzxHaZ" + + "3AGXQg8vzbPkUG6oRJLKTcncewUglCI9hMIN3JbgBnmQj0Vdtr4ou6qaxT96hrFJ" + + "mGKTqrOimKUOc0pAsQraIRfVbiezFFH0/fjgJuek+mwPpWIR0/jmye+uTK6kF1uX" + + "cQIIETfZHblJ7GmXm83uk/6hieM+47JhN4dEMfTnoqtilu5QR+NAXnVhmEKJp2Dx" + + "OLSKQ41uHxdguLHgaKMKXR1RYwnSsLrX0TXKDefX38dAxs0rdkTZb4wfT1y8JYhJ" + + "NWJGksBCZnOf9pL5IzCCAckGCSqGSIb3DQEHAaCCAboEggG2MIIBsjCCAa4GCyqG" + + "SIb3DQEMCgECoIIBdjCCAXIwHAYKKoZIhvcNAQwBAzAOBAiE35N4ijeQpwICCAAE" + + "ggFQ27yZqvji6lI03S0HBGRfGukbymgoKKV4k+dMaVt3cd+KGPzQMcwUjuNQiR32" + + "CzoElYvqaHo4KIhDukElLUxHQ+0ti5yaIabCRF2FRMtswhEVVRFvi0YZiBz7jzge" + + "Z0nqDtEKoDFBvbb34yVk51gDaNn2Is5AFBGZKY+Tas4qzJbe2ELbEosXBDk0Jvv6" + + "X13gDJfk67/J/8AE8IH2FY7/XDoG6luOxDG4Ebe68Qm+TY85vGiDMelvAaWyxGeY" + + "xndylDVyQSUGFoJHfvA4AgwaukR1rqc9/IZ/eJgz2ptMPZq2p+hsB1/IYaKzud1/" + + "QYpYtCkBfsT1DSRwvmJ6CingwEIL+NwrcdaD0F3C55BWzXRzbRE8XR754qq77gSv" + + "xk6gRR0kcO175AFeTDqwjmPPylaQ/okiSQ9a4yRFxHUnxigNRgD7tcVR6LuKGDBE" + + "v02cMSUwIwYJKoZIhvcNAQkVMRYEFDdYxa4ZJsCeAQZDzHLZ+cdpC2z5MDEwITAJ" + + "BgUrDgMCGgUABBS0CMJuJYzpHkxOFI+r0PA67eJbzQQI4yGr4jgshqECAggA"); public static X509Certificate2 GetSampleX509Certificate() { @@ -232,7 +232,7 @@ public static X509Certificate2 GetSampleX509Certificate() public static X509Certificate2 GetSampleDSAX509Certificate() { - return new X509Certificate2(SampleDsaPfx, "velleity"); + return new X509Certificate2(SampleDsaPfx, "PLACEHOLDER"); } public static Stream LoadResourceStream(string resourceName) diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs index ef7cb3ac3f7348..4d9a824761f533 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.Forwards.cs @@ -13,10 +13,8 @@ [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.SecurityAttribute))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.SecurityPermissionAttribute))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Permissions.SecurityPermissionFlag))] -#if NET6_0_OR_GREATER [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Policy.Evidence))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.Policy.EvidenceBase))] -#endif #if NETCOREAPP [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.IStackWalk))] [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Security.PermissionSet))] diff --git a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.csproj b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.csproj index 8c77b3223cb0c7..23b70b96d36aab 100644 --- a/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.csproj +++ b/src/libraries/System.Security.Permissions/ref/System.Security.Permissions.csproj @@ -6,7 +6,6 @@ - @@ -19,17 +18,14 @@ - - - - + + - diff --git a/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml index 40fce05b9e31bb..43191ba6888bed 100644 --- a/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml @@ -1,47 +1,86 @@  - CP0001 + CP0002 + M:System.Security.Permissions.KeyContainerPermissionAccessEntryCollection.CopyTo(System.Array,System.Int32) + lib/netstandard2.0/System.Security.Permissions.dll + lib/net461/System.Security.Permissions.dll + + + CP0002 + M:System.Security.Permissions.KeyContainerPermissionAccessEntryCollection.#ctor + lib/netstandard2.0/System.Security.Permissions.dll + lib/net461/System.Security.Permissions.dll + + + CP0002 + M:System.Security.Permissions.KeyContainerPermissionAccessEntryEnumerator.#ctor lib/netstandard2.0/System.Security.Permissions.dll lib/net461/System.Security.Permissions.dll CP0001 T:System.Security.Policy.Evidence - lib/net5.0/System.Security.Permissions.dll - lib/net6.0/System.Security.Permissions.dll + ref/net5.0/System.Security.Permissions.dll + lib/net5.0/System.Security.Permissions.dll + true CP0001 T:System.Security.Policy.EvidenceBase - lib/net5.0/System.Security.Permissions.dll - lib/net6.0/System.Security.Permissions.dll + ref/net5.0/System.Security.Permissions.dll + lib/net5.0/System.Security.Permissions.dll + true CP0001 - T:System.Security.IStackWalk - lib/netstandard2.0/System.Security.Permissions.dll - lib/netcoreapp3.1/System.Security.Permissions.dll + T:System.Xaml.Permissions.XamlLoadPermission + ref/netcoreapp3.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true CP0001 - T:System.Security.PermissionSet - lib/netstandard2.0/System.Security.Permissions.dll - lib/netcoreapp3.1/System.Security.Permissions.dll + T:System.Security.Policy.Evidence + ref/netcoreapp3.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true CP0001 - T:System.Security.Permissions.PermissionState - lib/netstandard2.0/System.Security.Permissions.dll - lib/netcoreapp3.1/System.Security.Permissions.dll + T:System.Security.Policy.EvidenceBase + ref/netcoreapp3.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true CP0001 - T:System.Xaml.Permissions.XamlLoadPermission - ref/netcoreapp3.0/System.Security.Permissions.dll + T:System.Security.Policy.Evidence + ref/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0001 + T:System.Security.Policy.EvidenceBase + ref/netstandard2.0/System.Security.Permissions.dll lib/netstandard2.0/System.Security.Permissions.dll true + + CP0001 + T:System.Security.Policy.Evidence + lib/net5.0/System.Security.Permissions.dll + lib/net5.0/System.Security.Permissions.dll + true + + + CP0001 + T:System.Security.Policy.EvidenceBase + lib/net5.0/System.Security.Permissions.dll + lib/net5.0/System.Security.Permissions.dll + true + CP0001 T:System.Xaml.Permissions.XamlLoadPermission @@ -50,9 +89,31 @@ true - CP0008 - T:System.Security.NamedPermissionSet + CP0001 + T:System.Security.Policy.Evidence + lib/netcoreapp3.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0001 + T:System.Security.Policy.EvidenceBase + lib/netcoreapp3.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0001 + T:System.Security.Policy.Evidence lib/netstandard2.0/System.Security.Permissions.dll - lib/netcoreapp3.1/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0001 + T:System.Security.Policy.EvidenceBase + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true \ No newline at end of file diff --git a/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj b/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj index 19be1eaf34dd8d..f1e8e0bb6148f8 100644 --- a/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj +++ b/src/libraries/System.Security.Permissions/src/System.Security.Permissions.csproj @@ -1,11 +1,11 @@ true - $(NetCoreAppCurrent);net5.0;netcoreapp3.1;netstandard2.0;net461 + $(NetCoreAppCurrent);net5.0;netcoreapp3.1;netstandard2.0;net461-windows true Provides types supporting Code Access Security (CAS). - + @@ -132,8 +132,6 @@ - - @@ -191,8 +189,8 @@ - - + + @@ -204,7 +202,6 @@ - diff --git a/src/libraries/System.Security.Principal.Windows/tests/WindowsIdentityImpersonatedTests.netcoreapp.cs b/src/libraries/System.Security.Principal.Windows/tests/WindowsIdentityImpersonatedTests.netcoreapp.cs index 868afcc8c1a4f5..0a7c1745ed9f42 100644 --- a/src/libraries/System.Security.Principal.Windows/tests/WindowsIdentityImpersonatedTests.netcoreapp.cs +++ b/src/libraries/System.Security.Principal.Windows/tests/WindowsIdentityImpersonatedTests.netcoreapp.cs @@ -26,7 +26,7 @@ public WindowsIdentityImpersonatedTests(WindowsIdentityFixture windowsIdentityFi Assert.False(string.IsNullOrEmpty(_fixture.TestAccount.AccountName)); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))] [OuterLoop] public async Task RunImpersonatedAsync_TaskAndTaskOfT() { @@ -60,7 +60,7 @@ void Asserts(WindowsIdentity currentWindowsIdentity) } } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))] [OuterLoop] public void RunImpersonated_NameResolution() { @@ -78,12 +78,15 @@ public void RunImpersonated_NameResolution() }); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.CanRunImpersonatedTests))] [OuterLoop] public async Task RunImpersonatedAsync_NameResolution() { WindowsIdentity currentWindowsIdentity = WindowsIdentity.GetCurrent(); + // make sure the assembly is loaded. + _ = Dns.GetHostAddresses(""); + await WindowsIdentity.RunImpersonatedAsync(_fixture.TestAccount.AccountTokenHandle, async () => { Assert.Equal(_fixture.TestAccount.AccountName, WindowsIdentity.GetCurrent().Name); @@ -96,129 +99,3 @@ await WindowsIdentity.RunImpersonatedAsync(_fixture.TestAccount.AccountTokenHand }); } } - -public class WindowsIdentityFixture : IDisposable -{ - public WindowsTestAccount TestAccount { get; private set; } - - public WindowsIdentityFixture() - { - TestAccount = new WindowsTestAccount("CorFxTstWiIde01kiu"); - } - - public void Dispose() - { - TestAccount.Dispose(); - } -} - -public sealed class WindowsTestAccount : IDisposable -{ - private readonly string _userName; - private SafeAccessTokenHandle _accountTokenHandle; - public SafeAccessTokenHandle AccountTokenHandle => _accountTokenHandle; - public string AccountName { get; private set; } - - public WindowsTestAccount(string userName) - { - _userName = userName; - CreateUser(); - } - - private void CreateUser() - { - string testAccountPassword; - using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) - { - byte[] randomBytes = new byte[33]; - rng.GetBytes(randomBytes); - - // Add special chars to ensure it satisfies password requirements. - testAccountPassword = Convert.ToBase64String(randomBytes) + "_-As@!%*(1)4#2"; - - USER_INFO_1 userInfo = new USER_INFO_1 - { - usri1_name = _userName, - usri1_password = testAccountPassword, - usri1_priv = 1 - }; - - // Create user and remove/create if already exists - uint result = NetUserAdd(null, 1, ref userInfo, out uint param_err); - - // error codes https://docs.microsoft.com/en-us/windows/desktop/netmgmt/network-management-error-codes - // 0 == NERR_Success - if (result == 2224) // NERR_UserExists - { - result = NetUserDel(null, userInfo.usri1_name); - if (result != 0) - { - throw new Win32Exception((int)result); - } - result = NetUserAdd(null, 1, ref userInfo, out param_err); - if (result != 0) - { - throw new Win32Exception((int)result); - } - } - - const int LOGON32_PROVIDER_DEFAULT = 0; - const int LOGON32_LOGON_INTERACTIVE = 2; - - if (!LogonUser(_userName, ".", testAccountPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out _accountTokenHandle)) - { - _accountTokenHandle = null; - throw new Exception($"Failed to get SafeAccessTokenHandle for test account {_userName}", new Win32Exception()); - } - - bool gotRef = false; - try - { - _accountTokenHandle.DangerousAddRef(ref gotRef); - IntPtr logonToken = _accountTokenHandle.DangerousGetHandle(); - AccountName = new WindowsIdentity(logonToken).Name; - } - finally - { - if (gotRef) - _accountTokenHandle.DangerousRelease(); - } - } - } - - [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern bool LogonUser(string userName, string domain, string password, int logonType, int logonProvider, out SafeAccessTokenHandle safeAccessTokenHandle); - - [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern uint NetUserAdd([MarshalAs(UnmanagedType.LPWStr)]string servername, uint level, ref USER_INFO_1 buf, out uint parm_err); - - [DllImport("netapi32.dll")] - internal static extern uint NetUserDel([MarshalAs(UnmanagedType.LPWStr)]string servername, [MarshalAs(UnmanagedType.LPWStr)]string username); - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct USER_INFO_1 - { - public string usri1_name; - public string usri1_password; - public uint usri1_password_age; - public uint usri1_priv; - public string usri1_home_dir; - public string usri1_comment; - public uint usri1_flags; - public string usri1_script_path; - } - - public void Dispose() - { - _accountTokenHandle?.Dispose(); - - uint result = NetUserDel(null, _userName); - - // 2221= NERR_UserNotFound - if (result != 0 && result != 2221) - { - throw new Win32Exception((int)result); - } - } -} - diff --git a/src/libraries/System.ServiceModel.Syndication/src/CompatibilitySuppressions.xml b/src/libraries/System.ServiceModel.Syndication/src/CompatibilitySuppressions.xml index 5cdd695b8805e5..8e2822b21ebb27 100644 --- a/src/libraries/System.ServiceModel.Syndication/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.ServiceModel.Syndication/src/CompatibilitySuppressions.xml @@ -1,7 +1,104 @@ - + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.get_Documentation + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.set_Documentation(System.ServiceModel.Syndication.SyndicationLink) + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.get_TimeToLive + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.set_TimeToLive(System.Nullable{System.TimeSpan}) + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.get_SkipHours + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.get_SkipDays + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.get_TextInput + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeed.set_TextInput(System.ServiceModel.Syndication.SyndicationTextInput) + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeedFormatter.get_UriParser + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeedFormatter.set_UriParser(System.ServiceModel.Syndication.TryParseUriCallback) + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeedFormatter.get_DateTimeParser + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0002 + M:System.ServiceModel.Syndication.SyndicationFeedFormatter.set_DateTimeParser(System.ServiceModel.Syndication.TryParseDateTimeCallback) + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0001 + T:System.ServiceModel.Syndication.TryParseDateTimeCallback + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0001 + T:System.ServiceModel.Syndication.TryParseUriCallback + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0001 + T:System.ServiceModel.Syndication.SyndicationTextInput + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + + + CP0001 + T:System.ServiceModel.Syndication.XmlDateTimeData + lib/netstandard2.0/System.ServiceModel.Syndication.dll + lib/net461/System.ServiceModel.Syndication.dll + CP0001 + T:System.ServiceModel.Syndication.XmlUriData lib/netstandard2.0/System.ServiceModel.Syndication.dll lib/net461/System.ServiceModel.Syndication.dll diff --git a/src/libraries/System.ServiceModel.Syndication/tests/System.ServiceModel.Syndication.Tests.csproj b/src/libraries/System.ServiceModel.Syndication/tests/System.ServiceModel.Syndication.Tests.csproj index 037fe58d8b95c3..368d45236e1617 100644 --- a/src/libraries/System.ServiceModel.Syndication/tests/System.ServiceModel.Syndication.Tests.csproj +++ b/src/libraries/System.ServiceModel.Syndication/tests/System.ServiceModel.Syndication.Tests.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);net461-windows + $(NetCoreAppCurrent);net461 diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/CompatibilitySuppressions.xml b/src/libraries/System.ServiceProcess.ServiceController/src/CompatibilitySuppressions.xml index d26132f552badf..b8d2693f9cf6c9 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.ServiceProcess.ServiceController/src/CompatibilitySuppressions.xml @@ -1,10 +1,5 @@ - + - - CP0001 - lib/netstandard2.0/System.ServiceProcess.ServiceController.dll - lib/net461/System.ServiceProcess.ServiceController.dll - PKV006 .NETStandard,Version=v1.4 diff --git a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj index 8886ffe02e9c85..a0300f8a838e9d 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/tests/System.ServiceProcess.ServiceController.TestService/System.ServiceProcess.ServiceController.TestService.csproj @@ -2,7 +2,7 @@ true Exe - $(NetCoreAppCurrent);net461 + $(NetCoreAppCurrent);net461-windows annotations @@ -40,4 +40,7 @@ + + + \ No newline at end of file diff --git a/src/libraries/System.Text.Json/Common/JsonConstants.cs b/src/libraries/System.Text.Json/Common/JsonConstants.cs index a97b11cf15bf2d..0d121d9c6ffbc8 100644 --- a/src/libraries/System.Text.Json/Common/JsonConstants.cs +++ b/src/libraries/System.Text.Json/Common/JsonConstants.cs @@ -7,5 +7,9 @@ internal static partial class JsonConstants { // The maximum number of parameters a constructor can have where it can be supported by the serializer. public const int MaxParameterCount = 64; + + // Standard format for double and single on non-inbox frameworks. + public const string DoubleFormatString = "G17"; + public const string SingleFormatString = "G9"; } } diff --git a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs index 84ffc3d5414b34..45f11a41063ccb 100644 --- a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs +++ b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs @@ -30,11 +30,6 @@ sealed class JsonSourceGenerationOptionsAttribute : JsonAttribute /// public bool IgnoreReadOnlyProperties { get; set; } - /// - /// Specifies whether to ignore custom converters provided at run time. - /// - public bool IgnoreRuntimeCustomConverters { get; set; } - /// /// Specifies whether to include fields for serialization and deserialization. /// diff --git a/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs b/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs index 8a1a58a97a2cba..09ecc45077fe06 100644 --- a/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/Common/ReflectionExtensions.cs @@ -310,5 +310,18 @@ public static bool TryGetDeserializationConstructor( deserializationCtor = ctorWithAttribute ?? publicParameterlessCtor ?? lonePublicCtor; return true; } + + public static object? GetDefaultValue(this ParameterInfo parameterInfo) + { + object? defaultValue = parameterInfo.DefaultValue; + + // DBNull.Value is sometimes used as the default value (returned by reflection) of nullable params in place of null. + if (defaultValue == DBNull.Value && parameterInfo.ParameterType != typeof(DBNull)) + { + return null; + } + + return defaultValue; + } } } diff --git a/src/libraries/System.Text.Json/System.Text.Json.sln b/src/libraries/System.Text.Json/System.Text.Json.sln index b8309363a7b30a..5c21cd8805632e 100644 --- a/src/libraries/System.Text.Json/System.Text.Json.sln +++ b/src/libraries/System.Text.Json/System.Text.Json.sln @@ -21,7 +21,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", "..\System.Text.Encodings.Web\src\System.Text.Encodings.Web.csproj", "{9BCCDA15-8907-4AE3-8871-2F17775DDE4C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration", "gen\System.Text.Json.SourceGeneration.csproj", "{6485EED4-C313-4551-9865-8ADCED603629}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.0", "gen\System.Text.Json.SourceGeneration.Roslyn4.0.csproj", "{6485EED4-C313-4551-9865-8ADCED603629}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "ref\System.Text.Json.csproj", "{7015E94D-D20D-48C8-86D7-6A996BE99E0E}" EndProject @@ -29,7 +29,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json", "src\Sys EndProject Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "System.Text.Json.FSharp.Tests", "tests\System.Text.Json.FSharp.Tests\System.Text.Json.FSharp.Tests.fsproj", "{5720BF06-2031-4AD8-B9B4-31A01E27ABB8}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Tests", "tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Tests.csproj", "{33599A6C-F340-4E1B-9B4D-CB8946C22140}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.0.Tests", "tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj", "{33599A6C-F340-4E1B-9B4D-CB8946C22140}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests", "tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj", "{F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.Tests", "tests\System.Text.Json.Tests\System.Text.Json.Tests.csproj", "{A0178BAA-A1AF-4C69-8E4A-A700A2723DDC}" EndProject @@ -43,7 +45,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Encodings.Web", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Collections.Immutable", "..\System.Collections.Immutable\ref\System.Collections.Immutable.csproj", "{BE27618A-2916-4269-9AD5-6BC5EDC32B30}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Text.Json.SourceGeneration.UnitTests", "tests\System.Text.Json.SourceGeneration.UnitTests\System.Text.Json.SourceGeneration.UnitTests.csproj", "{F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn3.11", "gen\System.Text.Json.SourceGeneration.Roslyn3.11.csproj", "{04AEB008-EE4F-44DE-A361-2DBD2D0FD6A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests", "tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj", "{256A4653-4287-44B3-BDEF-67FC1522ED2F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Text.Json.SourceGeneration.Roslyn3.11.Tests", "tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj", "{66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -123,6 +129,18 @@ Global {F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}.Debug|Any CPU.Build.0 = Debug|Any CPU {F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}.Release|Any CPU.ActiveCfg = Release|Any CPU {F6A18EB5-A8CC-4A39-9E85-5FA226019C3D}.Release|Any CPU.Build.0 = Release|Any CPU + {04AEB008-EE4F-44DE-A361-2DBD2D0FD6A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {04AEB008-EE4F-44DE-A361-2DBD2D0FD6A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {04AEB008-EE4F-44DE-A361-2DBD2D0FD6A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {04AEB008-EE4F-44DE-A361-2DBD2D0FD6A4}.Release|Any CPU.Build.0 = Release|Any CPU + {256A4653-4287-44B3-BDEF-67FC1522ED2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {256A4653-4287-44B3-BDEF-67FC1522ED2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {256A4653-4287-44B3-BDEF-67FC1522ED2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {256A4653-4287-44B3-BDEF-67FC1522ED2F}.Release|Any CPU.Build.0 = Release|Any CPU + {66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -131,11 +149,13 @@ Global {102945CA-3736-4B2C-8E68-242A0B247F2B} = {E07C6980-EB71-4D19-A80A-7BEB80B635B1} {73D5739C-E382-4E22-A7D3-B82705C58C74} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {E9AA0AEB-AEAE-4B28-8D4D-17A6D7C89D17} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} + {BE27618A-2916-4269-9AD5-6BC5EDC32B30} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {1C8262DB-7355-40A8-A2EC-4EED7363134A} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} {4774F56D-16A8-4ABB-8C73-5F57609F1773} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {D05FD93A-BC51-466E-BD56-3F3D6BBE6B06} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} {E2077991-EB83-471C-B17F-72F569FFCE6D} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {7909EB27-0D6E-46E6-B9F9-8A1EFD557018} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} + {C56337BB-8CBC-4EE5-AB4D-8BB0A922813E} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {9BCCDA15-8907-4AE3-8871-2F17775DDE4C} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} {6485EED4-C313-4551-9865-8ADCED603629} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} {7015E94D-D20D-48C8-86D7-6A996BE99E0E} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} @@ -146,6 +166,10 @@ Global {C56337BB-8CBC-4EE5-AB4D-8BB0A922813E} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {BE27618A-2916-4269-9AD5-6BC5EDC32B30} = {0371C5D8-D5F5-4747-9810-D91D71D8C0E4} {F6A18EB5-A8CC-4A39-9E85-5FA226019C3D} = {E07C6980-EB71-4D19-A80A-7BEB80B635B1} + {A0178BAA-A1AF-4C69-8E4A-A700A2723DDC} = {E07C6980-EB71-4D19-A80A-7BEB80B635B1} + {04AEB008-EE4F-44DE-A361-2DBD2D0FD6A4} = {E49881A9-09F6-442F-9E1D-6D87F5F837F1} + {256A4653-4287-44B3-BDEF-67FC1522ED2F} = {E07C6980-EB71-4D19-A80A-7BEB80B635B1} + {66AD4B7E-CF15-4A8F-8BF8-7E1BC6176D07} = {E07C6980-EB71-4D19-A80A-7BEB80B635B1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5868B757-D821-41FC-952E-2113A0519506} diff --git a/src/libraries/System.Text.Json/gen/ClassType.cs b/src/libraries/System.Text.Json/gen/ClassType.cs index d0df94330ec8e0..80029b5792d4ff 100644 --- a/src/libraries/System.Text.Json/gen/ClassType.cs +++ b/src/libraries/System.Text.Json/gen/ClassType.cs @@ -9,13 +9,20 @@ namespace System.Text.Json.SourceGeneration { internal enum ClassType { + /// + /// Types that are not supported yet by source gen including types with constructor parameters. + /// TypeUnsupportedBySourceGen = 0, Object = 1, KnownType = 2, - TypeWithDesignTimeProvidedCustomConverter = 3, - Enumerable = 4, - Dictionary = 5, - Nullable = 6, - Enum = 7 + /// + /// Known types such as System.Type and System.IntPtr that throw NotSupportedException. + /// + KnownUnsupportedType = 3, + TypeWithDesignTimeProvidedCustomConverter = 4, + Enumerable = 5, + Dictionary = 6, + Nullable = 7, + Enum = 8 } } diff --git a/src/libraries/System.Text.Json/gen/ContextGenerationSpec.cs b/src/libraries/System.Text.Json/gen/ContextGenerationSpec.cs index 545d5628297b81..b88bd918672004 100644 --- a/src/libraries/System.Text.Json/gen/ContextGenerationSpec.cs +++ b/src/libraries/System.Text.Json/gen/ContextGenerationSpec.cs @@ -5,6 +5,7 @@ using System.Text.Json.Serialization; using System.Text.Json.Reflection; using System.Diagnostics; +using Microsoft.CodeAnalysis; namespace System.Text.Json.SourceGeneration { @@ -15,6 +16,8 @@ namespace System.Text.Json.SourceGeneration [DebuggerDisplay("ContextTypeRef={ContextTypeRef}")] internal sealed class ContextGenerationSpec { + public Location Location { get; init; } + public JsonSourceGenerationOptionsAttribute GenerationOptions { get; init; } public Type ContextType { get; init; } @@ -32,9 +35,11 @@ internal sealed class ContextGenerationSpec public HashSet TypesWithMetadataGenerated { get; } = new(); /// - /// Cache of runtime property names (statically determined) found accross the object graph of the JsonSerializerContext. + /// Cache of runtime property names (statically determined) found across the object graph of the JsonSerializerContext. + /// The dictionary Key is the JSON property name, and the Value is the variable name which is the same as the property + /// name except for cases where special characters are used with [JsonPropertyName]. /// - public HashSet RuntimePropertyNames { get; } = new(); + public Dictionary RuntimePropertyNames { get; } = new(); public string ContextTypeRef => ContextType.GetCompilableName(); } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.ExceptionMessages.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.ExceptionMessages.cs new file mode 100644 index 00000000000000..faa8529cfd73b8 --- /dev/null +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.ExceptionMessages.cs @@ -0,0 +1,36 @@ +// 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.Collections.Generic; +using System.Text; + +namespace System.Text.Json.SourceGeneration +{ + public sealed partial class JsonSourceGenerator + { + private sealed partial class Emitter + { + /// + /// Unlike sourcegen warnings, exception messages should not be localized so we keep them in source. + /// + private static class ExceptionMessages + { + public const string InaccessibleJsonIncludePropertiesNotSupported = + "The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."; + + public const string IncompatibleConverterType = + "The converter '{0}' is not compatible with the type '{1}'."; + + public const string InitOnlyPropertyDeserializationNotSupported = + "Deserialization of init-only properties is currently not supported in source generation mode."; + + public const string InvalidJsonConverterFactoryOutput = + "The converter '{0}' cannot return null or a JsonConverterFactory instance."; + + public const string InvalidSerializablePropertyConfiguration = + "Invalid serializable-property configuration specified for type '{0}'. For more information, see 'JsonSourceGenerationMode.Serialization'."; + }; + } + } +} diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index 75d8cdd978171c..0df820dcecf22e 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -4,11 +4,14 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Reflection; +using System.Reflection.Metadata; using System.Text.Json; using System.Text.Json.Reflection; using System.Text.Json.Serialization; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Text; namespace System.Text.Json.SourceGeneration @@ -18,17 +21,24 @@ public sealed partial class JsonSourceGenerator private sealed partial class Emitter { // Literals in generated source - private const string RuntimeCustomConverterFetchingMethodName = "GetRuntimeProvidedCustomConverter"; - private const string OptionsInstanceVariableName = "Options"; - private const string PropInitMethodNameSuffix = "PropInit"; - private const string CtorParamInitMethodNameSuffix = "CtorParamInit"; - private const string SerializeMethodNameSuffix = "Serialize"; private const string CreateValueInfoMethodName = "CreateValueInfo"; + private const string CtorParamInitMethodNameSuffix = "CtorParamInit"; private const string DefaultOptionsStaticVarName = "s_defaultOptions"; private const string DefaultContextBackingStaticVarName = "s_defaultContext"; - private const string WriterVarName = "writer"; - private const string ValueVarName = "value"; + private const string ElementInfoPropName = "ElementInfo"; + internal const string GetConverterFromFactoryMethodName = "GetConverterFromFactory"; + private const string InfoVarName = "info"; private const string JsonSerializerContextName = "JsonSerializerContext"; + internal const string JsonContextVarName = "jsonContext"; + private const string KeyInfoPropName = "KeyInfo"; + private const string NumberHandlingPropName = "NumberHandling"; + private const string ObjectCreatorPropName = "ObjectCreator"; + private const string OptionsInstanceVariableName = "Options"; + private const string PropInitMethodNameSuffix = "PropInit"; + private const string RuntimeCustomConverterFetchingMethodName = "GetRuntimeProvidedCustomConverter"; + private const string SerializeHandlerPropName = "SerializeHandler"; + private const string ValueVarName = "value"; + private const string WriterVarName = "writer"; private static AssemblyName _assemblyName = typeof(Emitter).Assembly.GetName(); private static readonly string s_generatedCodeAttributeSource = $@" @@ -45,7 +55,6 @@ private sealed partial class Emitter private const string IListTypeRef = "global::System.Collections.Generic.IList"; private const string KeyValuePairTypeRef = "global::System.Collections.Generic.KeyValuePair"; private const string ListTypeRef = "global::System.Collections.Generic.List"; - private const string DictionaryTypeRef = "global::System.Collections.Generic.Dictionary"; private const string JsonEncodedTextTypeRef = "global::System.Text.Json.JsonEncodedText"; private const string JsonNamingPolicyTypeRef = "global::System.Text.Json.JsonNamingPolicy"; private const string JsonSerializerTypeRef = "global::System.Text.Json.JsonSerializer"; @@ -53,6 +62,7 @@ private sealed partial class Emitter private const string Utf8JsonWriterTypeRef = "global::System.Text.Json.Utf8JsonWriter"; private const string JsonConverterTypeRef = "global::System.Text.Json.Serialization.JsonConverter"; private const string JsonConverterFactoryTypeRef = "global::System.Text.Json.Serialization.JsonConverterFactory"; + private const string JsonCollectionInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues"; private const string JsonIgnoreConditionTypeRef = "global::System.Text.Json.Serialization.JsonIgnoreCondition"; private const string JsonNumberHandlingTypeRef = "global::System.Text.Json.Serialization.JsonNumberHandling"; private const string JsonSerializerContextTypeRef = "global::System.Text.Json.Serialization.JsonSerializerContext"; @@ -60,7 +70,9 @@ private sealed partial class Emitter private const string JsonObjectInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues"; private const string JsonParameterInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues"; private const string JsonPropertyInfoTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo"; + private const string JsonPropertyInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues"; private const string JsonTypeInfoTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonTypeInfo"; + private const string NotSupportedExceptionTypeRef = "global::System.NotSupportedException"; private static DiagnosticDescriptor TypeNotSupported { get; } = new DiagnosticDescriptor( id: "SYSLIB1030", @@ -78,15 +90,20 @@ private sealed partial class Emitter defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true); - private readonly GeneratorExecutionContext _executionContext; + private readonly JsonSourceGenerationContext _sourceGenerationContext; private ContextGenerationSpec _currentContext = null!; - private readonly SourceGenerationSpec _generationSpec = null!; + private readonly SourceGenerationSpec _generationSpec; - public Emitter(in GeneratorExecutionContext executionContext, SourceGenerationSpec generationSpec) + private readonly HashSet _emittedPropertyFileNames = new(); + + private bool _generateGetConverterMethodForTypes = false; + private bool _generateGetConverterMethodForProperties = false; + + public Emitter(in JsonSourceGenerationContext sourceGenerationContext, SourceGenerationSpec generationSpec) { - _executionContext = executionContext; + _sourceGenerationContext = sourceGenerationContext; _generationSpec = generationSpec; } @@ -95,6 +112,8 @@ public void Emit() foreach (ContextGenerationSpec contextGenerationSpec in _generationSpec.ContextGenerationSpecList) { _currentContext = contextGenerationSpec; + _generateGetConverterMethodForTypes = false; + _generateGetConverterMethodForProperties = false; foreach (TypeGenerationSpec typeGenerationSpec in _currentContext.RootSerializableTypes) { @@ -104,7 +123,10 @@ public void Emit() string contextName = _currentContext.ContextType.Name; // Add root context implementation. - AddSource($"{contextName}.g.cs", GetRootJsonContextImplementation(), isRootContextDef: true); + AddSource( + $"{contextName}.g.cs", + GetRootJsonContextImplementation(), + isRootContextDef: true); // Add GetJsonTypeInfo override implementation. AddSource($"{contextName}.GetJsonTypeInfo.g.cs", GetGetTypeInfoImplementation()); @@ -126,7 +148,10 @@ private void AddSource(string fileName, string source, bool isRootContextDef = f bool isInGlobalNamespace = @namespace == JsonConstants.GlobalNamespaceValue; StringBuilder sb = new(@"// -#nullable enable"); +#nullable enable + +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618"); if (!isInGlobalNamespace) { @@ -165,7 +190,7 @@ namespace {@namespace} sb.AppendLine("}"); } - _executionContext.AddSource(fileName, SourceText.From(sb.ToString(), Encoding.UTF8)); + _sourceGenerationContext.AddSource(fileName, SourceText.From(sb.ToString(), Encoding.UTF8)); } private void GenerateTypeInfo(TypeGenerationSpec typeGenerationSpec) @@ -238,12 +263,24 @@ private void GenerateTypeInfo(TypeGenerationSpec typeGenerationSpec) GenerateTypeInfo(spec.TypeGenerationSpec); } } + + TypeGenerationSpec? extPropTypeSpec = typeGenerationSpec.ExtensionDataPropertyTypeSpec; + if (extPropTypeSpec != null) + { + GenerateTypeInfo(extPropTypeSpec); + } + } + break; + case ClassType.KnownUnsupportedType: + { + source = GenerateForUnsupportedType(typeGenerationSpec); } break; case ClassType.TypeUnsupportedBySourceGen: { - _executionContext.ReportDiagnostic( - Diagnostic.Create(TypeNotSupported, Location.None, new string[] { typeGenerationSpec.TypeRef })); + Location location = typeGenerationSpec.Type.GetDiagnosticLocation() ?? typeGenerationSpec.AttributeLocation ?? _currentContext.Location; + _sourceGenerationContext.ReportDiagnostic( + Diagnostic.Create(TypeNotSupported, location, new string[] { typeGenerationSpec.TypeRef })); return; } default: @@ -252,14 +289,21 @@ private void GenerateTypeInfo(TypeGenerationSpec typeGenerationSpec) } } - try + // Don't add a duplicate file, but instead raise a diagnostic to say the duplicate has been skipped. + // Workaround https://github.com/dotnet/roslyn/issues/54185 by keeping track of the file names we've used. + string propertyFileName = $"{_currentContext.ContextType.Name}.{typeGenerationSpec.TypeInfoPropertyName}.g.cs"; + if (_emittedPropertyFileNames.Add(propertyFileName)) { - AddSource($"{_currentContext.ContextType.Name}.{typeGenerationSpec.TypeInfoPropertyName}.g.cs", source); + AddSource(propertyFileName, source); } - catch (ArgumentException) + else { - _executionContext.ReportDiagnostic(Diagnostic.Create(DuplicateTypeName, Location.None, new string[] { typeGenerationSpec.TypeInfoPropertyName })); + Location location = typeGenerationSpec.AttributeLocation ?? _currentContext.Location; + _sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(DuplicateTypeName, location, new string[] { typeGenerationSpec.TypeInfoPropertyName })); } + + _generateGetConverterMethodForTypes |= typeGenerationSpec.HasTypeFactoryConverter; + _generateGetConverterMethodForProperties |= typeGenerationSpec.HasPropertyFactoryConverters; } private string GenerateForTypeWithKnownConverter(TypeGenerationSpec typeMetadata) @@ -277,40 +321,42 @@ private string GenerateForTypeWithUnknownConverter(TypeGenerationSpec typeMetada string typeCompilableName = typeMetadata.TypeRef; string typeFriendlyName = typeMetadata.TypeInfoPropertyName; - StringBuilder sb = new(); - // TODO (https://github.com/dotnet/runtime/issues/52218): consider moving this verification source to common helper. - string metadataInitSource = $@"{JsonConverterTypeRef} converter = {typeMetadata.ConverterInstantiationLogic}; - {TypeTypeRef} typeToConvert = typeof({typeCompilableName}); - if (!converter.CanConvert(typeToConvert)) - {{ - {TypeTypeRef}? underlyingType = {NullableTypeRef}.GetUnderlyingType(typeToConvert); - if (underlyingType != null && converter.CanConvert(underlyingType)) - {{ - {JsonConverterTypeRef}? actualConverter = converter; + StringBuilder metadataInitSource = new( + $@"{JsonConverterTypeRef} converter = {typeMetadata.ConverterInstantiationLogic}; + {TypeTypeRef} typeToConvert = typeof({typeCompilableName});"); - if (converter is {JsonConverterFactoryTypeRef} converterFactory) + if (typeMetadata.IsValueType) + { + metadataInitSource.Append($@" + if (!converter.CanConvert(typeToConvert)) + {{ + {TypeTypeRef}? underlyingType = {NullableTypeRef}.GetUnderlyingType(typeToConvert); + if (underlyingType != null && converter.CanConvert(underlyingType)) {{ - actualConverter = converterFactory.CreateConverter(underlyingType, {OptionsInstanceVariableName}); - - if (actualConverter == null || actualConverter is {JsonConverterFactoryTypeRef}) - {{ - throw new {InvalidOperationExceptionTypeRef}($""JsonConverterFactory '{{converter}} cannot return a 'null' or 'JsonConverterFactory' value.""); - }} + // Allow nullable handling to forward to the underlying type's converter. + converter = {JsonMetadataServicesTypeRef}.GetNullableConverter<{typeCompilableName}>(this.{typeFriendlyName})!; + converter = (({ JsonConverterFactoryTypeRef })converter).CreateConverter(typeToConvert, { OptionsInstanceVariableName })!; }} - - // Allow nullable handling to forward to the underlying type's converter. - converter = {JsonMetadataServicesTypeRef}.GetNullableConverter<{typeCompilableName}>(this.{typeFriendlyName}); - }} - else + else + {{ + throw new {InvalidOperationExceptionTypeRef}(string.Format(""{ExceptionMessages.IncompatibleConverterType}"", converter.GetType(), typeToConvert)); + }} + }}"); + } + else + { + metadataInitSource.Append($@" + if (!converter.CanConvert(typeToConvert)) {{ - throw new {InvalidOperationExceptionTypeRef}($""The converter '{{converter.GetType()}}' is not compatible with the type '{{typeToConvert}}'.""); - }} - }} + throw new {InvalidOperationExceptionTypeRef}(string.Format(""{ExceptionMessages.IncompatibleConverterType}"", converter.GetType(), typeToConvert)); + }}"); + } - _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeCompilableName)}({OptionsInstanceVariableName}, converter);"; + metadataInitSource.Append($@" + _{typeFriendlyName} = { JsonMetadataServicesTypeRef }.{ GetCreateValueInfoMethodRef(typeCompilableName)} ({ OptionsInstanceVariableName}, converter); "); - return GenerateForType(typeMetadata, metadataInitSource); + return GenerateForType(typeMetadata, metadataInitSource.ToString()); } private string GenerateForNullable(TypeGenerationSpec typeMetadata) @@ -334,6 +380,16 @@ private string GenerateForNullable(TypeGenerationSpec typeMetadata) return GenerateForType(typeMetadata, metadataInitSource); } + private string GenerateForUnsupportedType(TypeGenerationSpec typeMetadata) + { + string typeCompilableName = typeMetadata.TypeRef; + string typeFriendlyName = typeMetadata.TypeInfoPropertyName; + + string metadataInitSource = $"_{typeFriendlyName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeCompilableName)}({OptionsInstanceVariableName}, {JsonMetadataServicesTypeRef}.GetUnsupportedTypeConverter<{typeCompilableName}>());"; + + return GenerateForType(typeMetadata, metadataInitSource); + } + private string GenerateForEnum(TypeGenerationSpec typeMetadata) { string typeCompilableName = typeMetadata.TypeRef; @@ -376,29 +432,38 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec) string numberHandlingArg = $"{GetNumberHandlingAsStr(typeGenerationSpec.NumberHandling)}"; - string serializeFuncNamedArg; + string serializeHandlerValue; - string? serializeFuncSource; + string? serializeHandlerSource; if (!typeGenerationSpec.GenerateSerializationLogic) { - serializeFuncSource = null; - serializeFuncNamedArg = "serializeFunc: null"; + serializeHandlerSource = null; + serializeHandlerValue = "null"; } else { - serializeFuncSource = typeGenerationSpec.ClassType == ClassType.Enumerable + serializeHandlerSource = typeGenerationSpec.ClassType == ClassType.Enumerable ? GenerateFastPathFuncForEnumerable(typeGenerationSpec) : GenerateFastPathFuncForDictionary(typeGenerationSpec); - serializeFuncNamedArg = $"serializeFunc: {typeGenerationSpec.FastPathSerializeMethodName}"; + serializeHandlerValue = $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}"; } CollectionType collectionType = typeGenerationSpec.CollectionType; string typeRef = typeGenerationSpec.TypeRef; - string createObjectFuncArg = typeGenerationSpec.ConstructionStrategy == ObjectConstructionStrategy.ParameterlessConstructor - ? $"createObjectFunc: () => new {typeRef}()" - : "createObjectFunc: null"; + + string objectCreatorValue; + if (typeGenerationSpec.RuntimeTypeRef != null) + { + objectCreatorValue = $"() => new {typeGenerationSpec.RuntimeTypeRef}()"; + } + else + { + objectCreatorValue = typeGenerationSpec.ConstructionStrategy == ObjectConstructionStrategy.ParameterlessConstructor + ? $"() => new {typeRef}()" + : "null"; + } string collectionInfoCreationPrefix = collectionType switch { @@ -406,15 +471,15 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec) CollectionType.ICollectionOfT => $"{JsonMetadataServicesTypeRef}.CreateICollectionInfo<", CollectionType.StackOfT => $"{JsonMetadataServicesTypeRef}.CreateStackInfo<", CollectionType.QueueOfT => $"{JsonMetadataServicesTypeRef}.CreateQueueInfo<", - CollectionType.Stack => $"{JsonMetadataServicesTypeRef}.CreateStackOrQueueInfo<", - CollectionType.Queue => $"{JsonMetadataServicesTypeRef}.CreateStackOrQueueInfo<", + CollectionType.Stack => $"{JsonMetadataServicesTypeRef}.CreateStackInfo<", + CollectionType.Queue => $"{JsonMetadataServicesTypeRef}.CreateQueueInfo<", CollectionType.IEnumerableOfT => $"{JsonMetadataServicesTypeRef}.CreateIEnumerableInfo<", CollectionType.IDictionaryOfTKeyTValue => $"{JsonMetadataServicesTypeRef}.CreateIDictionaryInfo<", _ => $"{JsonMetadataServicesTypeRef}.Create{collectionType}Info<" }; - string dictInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {keyTypeCompilableName!}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}"; - string enumerableInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}"; + string dictInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {keyTypeCompilableName!}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {InfoVarName}"; + string enumerableInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {InfoVarName}"; string immutableCollectionCreationSuffix = $"createRangeFunc: {typeGenerationSpec.ImmutableCollectionBuilderName}"; string collectionTypeInfoValue; @@ -422,23 +487,23 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec) switch (collectionType) { case CollectionType.Array: - collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{valueTypeCompilableName}>({OptionsInstanceVariableName}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})"; + collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{valueTypeCompilableName}>({OptionsInstanceVariableName}, {InfoVarName})"; break; case CollectionType.IEnumerable: case CollectionType.IList: - collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})"; + collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {InfoVarName})"; break; case CollectionType.Stack: case CollectionType.Queue: string addMethod = collectionType == CollectionType.Stack ? "Push" : "Enqueue"; string addFuncNamedArg = $"addFunc: (collection, {ValueVarName}) => collection.{addMethod}({ValueVarName})"; - collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}, {addFuncNamedArg})"; + collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {InfoVarName}, {addFuncNamedArg})"; break; case CollectionType.ImmutableEnumerable: collectionTypeInfoValue = $"{enumerableInfoCreationPrefix}, {immutableCollectionCreationSuffix})"; break; case CollectionType.IDictionary: - collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})"; + collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {InfoVarName})"; break; case CollectionType.Dictionary: case CollectionType.IDictionaryOfTKeyTValue: @@ -453,9 +518,19 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec) break; } - string metadataInitSource = @$"_{typeGenerationSpec.TypeInfoPropertyName} = {collectionTypeInfoValue};"; + string metadataInitSource = @$"{JsonCollectionInfoValuesTypeRef}<{typeRef}> {InfoVarName} = new {JsonCollectionInfoValuesTypeRef}<{typeRef}>() + {{ + {ObjectCreatorPropName} = {objectCreatorValue}, + {KeyInfoPropName} = {keyTypeMetadataPropertyName!}, + {ElementInfoPropName} = {valueTypeMetadataPropertyName}, + {NumberHandlingPropName} = {numberHandlingArg}, + {SerializeHandlerPropName} = {serializeHandlerValue} + }}; - return GenerateForType(typeGenerationSpec, metadataInitSource, serializeFuncSource); + _{typeGenerationSpec.TypeInfoPropertyName} = {collectionTypeInfoValue}; +"; + + return GenerateForType(typeGenerationSpec, metadataInitSource, serializeHandlerSource); } private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerationSpec) @@ -464,7 +539,7 @@ private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerati Type elementType = valueTypeGenerationSpec.Type; string? writerMethodToCall = GetWriterMethod(elementType); - + string iterationLogic; string valueToWrite; @@ -493,7 +568,7 @@ private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerati } string elementSerializationLogic = writerMethodToCall == null - ? GetSerializeLogicForNonPrimitiveType(valueTypeGenerationSpec.TypeInfoPropertyName, valueToWrite, valueTypeGenerationSpec.GenerateSerializationLogic) + ? GetSerializeLogicForNonPrimitiveType(valueTypeGenerationSpec, valueToWrite) : $"{writerMethodToCall}Value({valueToWrite});"; string serializationLogic = $@"{WriterVarName}.WriteStartArray(); @@ -505,11 +580,7 @@ private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerati {WriterVarName}.WriteEndArray();"; - return GenerateFastPathFuncForType( - typeGenerationSpec.FastPathSerializeMethodName, - typeGenerationSpec.TypeRef, - serializationLogic, - typeGenerationSpec.CanBeNull); + return GenerateFastPathFuncForType(typeGenerationSpec, serializationLogic, emitNullCheck: typeGenerationSpec.CanBeNull); } private string GenerateFastPathFuncForDictionary(TypeGenerationSpec typeGenerationSpec) @@ -537,7 +608,7 @@ private string GenerateFastPathFuncForDictionary(TypeGenerationSpec typeGenerati else { elementSerializationLogic = $@"{WriterVarName}.WritePropertyName({keyToWrite}); - {GetSerializeLogicForNonPrimitiveType(valueTypeGenerationSpec.TypeInfoPropertyName, valueToWrite, valueTypeGenerationSpec.GenerateSerializationLogic)}"; + {GetSerializeLogicForNonPrimitiveType(valueTypeGenerationSpec, valueToWrite)}"; } string serializationLogic = $@"{WriterVarName}.WriteStartObject(); @@ -549,11 +620,7 @@ private string GenerateFastPathFuncForDictionary(TypeGenerationSpec typeGenerati {WriterVarName}.WriteEndObject();"; - return GenerateFastPathFuncForType( - typeGenerationSpec.FastPathSerializeMethodName, - typeGenerationSpec.TypeRef, - serializationLogic, - typeGenerationSpec.CanBeNull); + return GenerateFastPathFuncForType(typeGenerationSpec, serializationLogic, emitNullCheck: typeGenerationSpec.CanBeNull); } private string GenerateForObject(TypeGenerationSpec typeMetadata) @@ -592,23 +659,23 @@ private string GenerateForObject(TypeGenerationSpec typeMetadata) if (typeMetadata.GenerateSerializationLogic) { serializeFuncSource = GenerateFastPathFuncForObject(typeMetadata); - serializeMethodName = $"{typeFriendlyName}{SerializeMethodNameSuffix}"; + serializeMethodName = $"{typeFriendlyName}{SerializeHandlerPropName}"; } const string ObjectInfoVarName = "objectInfo"; string genericArg = typeMetadata.TypeRef; string objectInfoInitSource = $@"{JsonObjectInfoValuesTypeRef}<{genericArg}> {ObjectInfoVarName} = new {JsonObjectInfoValuesTypeRef}<{genericArg}>() - {{ - ObjectCreator = {creatorInvocation}, - ObjectWithParameterizedConstructorCreator = {parameterizedCreatorInvocation}, - PropertyMetadataInitializer = {propInitMethodName}, - ConstructorParameterMetadataInitializer = {ctorParamMetadataInitMethodName}, - NumberHandling = {GetNumberHandlingAsStr(typeMetadata.NumberHandling)}, - SerializeHandler = {serializeMethodName} - }}; + {{ + {ObjectCreatorPropName} = {creatorInvocation}, + ObjectWithParameterizedConstructorCreator = {parameterizedCreatorInvocation}, + PropertyMetadataInitializer = {propInitMethodName}, + ConstructorParameterMetadataInitializer = {ctorParamMetadataInitMethodName}, + {NumberHandlingPropName} = {GetNumberHandlingAsStr(typeMetadata.NumberHandling)}, + {SerializeHandlerPropName} = {serializeMethodName} + }}; - _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.CreateObjectInfo<{typeMetadata.TypeRef}>({OptionsInstanceVariableName}, {ObjectInfoVarName});"; + _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.CreateObjectInfo<{typeMetadata.TypeRef}>({OptionsInstanceVariableName}, {ObjectInfoVarName});"; string additionalSource = @$"{propMetadataInitFuncSource}{serializeFuncSource}{ctorParamMetadataInitFuncSource}"; @@ -618,7 +685,6 @@ private string GenerateForObject(TypeGenerationSpec typeMetadata) private string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenerationSpec) { const string PropVarName = "properties"; - const string JsonContextVarName = "jsonContext"; List properties = typeGenerationSpec.PropertyGenSpecList!; @@ -657,57 +723,66 @@ private string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenerationSpe ? "null" : $"{JsonContextVarName}.{memberTypeMetadata.TypeInfoPropertyName}"; - string typeTypeInfoNamedArg = $"propertyTypeInfo: {memberTypeFriendlyName}"; - - string jsonPropertyNameNamedArg = memberMetadata.JsonPropertyName != null - ? @$"jsonPropertyName: ""{memberMetadata.JsonPropertyName}""" - : "jsonPropertyName: null"; - - string getterNamedArg = memberMetadata.CanUseGetter - ? $"getter: static (obj) => (({declaringTypeCompilableName})obj).{clrPropertyName}" - : "getter: null"; + string jsonPropertyNameValue = memberMetadata.JsonPropertyName != null + ? @$"""{memberMetadata.JsonPropertyName}""" + : "null"; - string setterNamedArg; - if (memberMetadata.CanUseSetter) + string getterValue = memberMetadata switch { - string propMutation = typeGenerationSpec.IsValueType - ? @$"{UnsafeTypeRef}.Unbox<{declaringTypeCompilableName}>(obj).{clrPropertyName} = value!" - : $@"(({declaringTypeCompilableName})obj).{clrPropertyName} = value!"; - - setterNamedArg = $"setter: static (obj, value) => {propMutation}"; - } - else + { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "null", + { CanUseGetter: true } => $"static (obj) => (({declaringTypeCompilableName})obj).{clrPropertyName}{(memberMetadata.TypeGenerationSpec.CanContainNullableReferenceAnnotations ? "!" : "")}", + { CanUseGetter: false, HasJsonInclude: true } + => @$"static (obj) => throw new {InvalidOperationExceptionTypeRef}(""{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.Type.Name, memberMetadata.ClrName)}"")", + _ => "null" + }; + + string setterValue = memberMetadata switch { - setterNamedArg = "setter: null"; - } + { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "null", + { CanUseSetter: true, IsInitOnlySetter: true } + => @$"static (obj, value) => throw new {InvalidOperationExceptionTypeRef}(""{ExceptionMessages.InitOnlyPropertyDeserializationNotSupported}"")", + { CanUseSetter: true } when typeGenerationSpec.IsValueType + => $@"static (obj, value) => {UnsafeTypeRef}.Unbox<{declaringTypeCompilableName}>(obj).{clrPropertyName} = value!", + { CanUseSetter: true } + => @$"static (obj, value) => (({declaringTypeCompilableName})obj).{clrPropertyName} = value!", + { CanUseSetter: false, HasJsonInclude: true } + => @$"static (obj, value) => throw new {InvalidOperationExceptionTypeRef}(""{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.Type.Name, memberMetadata.ClrName)}"")", + _ => "null", + }; JsonIgnoreCondition? ignoreCondition = memberMetadata.DefaultIgnoreCondition; string ignoreConditionNamedArg = ignoreCondition.HasValue - ? $"ignoreCondition: {JsonIgnoreConditionTypeRef}.{ignoreCondition.Value}" - : "ignoreCondition: null"; + ? $"{JsonIgnoreConditionTypeRef}.{ignoreCondition.Value}" + : "null"; - string converterNamedArg = memberMetadata.ConverterInstantiationLogic == null - ? "converter: null" - : $"converter: {memberMetadata.ConverterInstantiationLogic}"; + string converterValue = memberMetadata.ConverterInstantiationLogic == null + ? "null" + : $"{memberMetadata.ConverterInstantiationLogic}"; string memberTypeCompilableName = memberTypeMetadata.TypeRef; + string infoVarName = $"{InfoVarName}{i}"; + sb.Append($@" - {PropVarName}[{i}] = {JsonMetadataServicesTypeRef}.CreatePropertyInfo<{memberTypeCompilableName}>( - options, - isProperty: {ToCSharpKeyword(memberMetadata.IsProperty)}, - isPublic: {ToCSharpKeyword(memberMetadata.IsPublic)}, - isVirtual: {ToCSharpKeyword(memberMetadata.IsVirtual)}, - declaringType: typeof({memberMetadata.DeclaringTypeRef}), - {typeTypeInfoNamedArg}, - {converterNamedArg}, - {getterNamedArg}, - {setterNamedArg}, - {ignoreConditionNamedArg}, - hasJsonInclude: {ToCSharpKeyword(memberMetadata.HasJsonInclude)}, - numberHandling: {GetNumberHandlingAsStr(memberMetadata.NumberHandling)}, - propertyName: ""{clrPropertyName}"", - {jsonPropertyNameNamedArg}); + {JsonPropertyInfoValuesTypeRef}<{memberTypeCompilableName}> {infoVarName} = new {JsonPropertyInfoValuesTypeRef}<{memberTypeCompilableName}>() + {{ + IsProperty = {FormatBool(memberMetadata.IsProperty)}, + IsPublic = {FormatBool(memberMetadata.IsPublic)}, + IsVirtual = {FormatBool(memberMetadata.IsVirtual)}, + DeclaringType = typeof({memberMetadata.DeclaringTypeRef}), + PropertyTypeInfo = {memberTypeFriendlyName}, + Converter = {converterValue}, + Getter = {getterValue}, + Setter = {setterValue}, + IgnoreCondition = {ignoreConditionNamedArg}, + HasJsonInclude = {FormatBool(memberMetadata.HasJsonInclude)}, + IsExtensionData = {FormatBool(memberMetadata.IsExtensionData)}, + NumberHandling = {GetNumberHandlingAsStr(memberMetadata.NumberHandling)}, + PropertyName = ""{clrPropertyName}"", + JsonPropertyName = {jsonPropertyNameValue} + }}; + + {PropVarName}[{i}] = {JsonMetadataServicesTypeRef}.CreatePropertyInfo<{memberTypeCompilableName}>(options, {infoVarName}); "); } @@ -721,7 +796,6 @@ private string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenerationSpe private string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerationSpec) { const string parametersVarName = "parameters"; - const string infoVarName = "info"; ParameterGenerationSpec[] parameters = typeGenerationSpec.CtorParamGenSpecArray; int paramCount = parameters.Length; @@ -738,17 +812,22 @@ private string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerati for (int i = 0; i < paramCount; i++) { ParameterInfo reflectionInfo = parameters[i].ParameterInfo; + Type parameterType = reflectionInfo.ParameterType; + string parameterTypeRef = parameterType.GetCompilableName(); + + object? defaultValue = reflectionInfo.GetDefaultValue(); + string defaultValueAsStr = GetParamDefaultValueAsString(defaultValue, parameterType, parameterTypeRef); sb.Append(@$" - {infoVarName} = new() + {InfoVarName} = new() {{ Name = ""{reflectionInfo.Name!}"", - ParameterType = typeof({reflectionInfo.ParameterType.GetCompilableName()}), + ParameterType = typeof({parameterTypeRef}), Position = {reflectionInfo.Position}, - HasDefaultValue = {ToCSharpKeyword(reflectionInfo.HasDefaultValue)}, - DefaultValue = {GetParamDefaultValueAsString(reflectionInfo.DefaultValue)} + HasDefaultValue = {FormatBool(reflectionInfo.HasDefaultValue)}, + DefaultValue = {defaultValueAsStr} }}; - {parametersVarName}[{i}] = {infoVarName}; + {parametersVarName}[{i}] = {InfoVarName}; "); } @@ -763,20 +842,17 @@ private string GenerateFastPathFuncForObject(TypeGenerationSpec typeGenSpec) { JsonSourceGenerationOptionsAttribute options = _currentContext.GenerationOptions; string typeRef = typeGenSpec.TypeRef; - string serializeMethodName = $"{typeGenSpec.TypeInfoPropertyName}{SerializeMethodNameSuffix}"; if (!typeGenSpec.TryFilterSerializableProps( options, out Dictionary? serializableProperties, out bool castingRequiredForProps)) { - string exceptionMessage = @$"""Invalid serializable-property configuration specified for type '{typeRef}'. For more information, use 'JsonSourceGenerationMode.Serialization'."""; + string exceptionMessage = string.Format(ExceptionMessages.InvalidSerializablePropertyConfiguration, typeRef); - return GenerateFastPathFuncForType( - serializeMethodName, - typeRef, - $@"throw new {InvalidOperationExceptionTypeRef}({exceptionMessage});", - canBeNull: false); // Skip null check since we want to throw an exception straightaway. + return GenerateFastPathFuncForType(typeGenSpec, + $@"throw new {InvalidOperationExceptionTypeRef}(""{exceptionMessage}"");", + emitNullCheck: false); // Skip null check since we want to throw an exception straightaway. } StringBuilder sb = new(); @@ -803,15 +879,16 @@ private string GenerateFastPathFuncForObject(TypeGenerationSpec typeGenSpec) TypeGenerationSpec propertyTypeSpec = propertyGenSpec.TypeGenerationSpec; string runtimePropName = propertyGenSpec.RuntimePropertyName; + string propVarName = propertyGenSpec.PropertyNameVarName; // Add the property names to the context-wide cache; we'll generate the source to initialize them at the end of generation. - _currentContext.RuntimePropertyNames.Add(runtimePropName); + Debug.Assert(!_currentContext.RuntimePropertyNames.TryGetValue(runtimePropName, out string? existingName) || existingName == propVarName); + _currentContext.RuntimePropertyNames.TryAdd(runtimePropName, propVarName); Type propertyType = propertyTypeSpec.Type; - string propName = $"{runtimePropName}PropName"; string? objectRef = castingRequiredForProps ? $"(({propertyGenSpec.DeclaringTypeRef}){ValueVarName})" : ValueVarName; string propValue = $"{objectRef}.{propertyGenSpec.ClrName}"; - string methodArgs = $"{propName}, {propValue}"; + string methodArgs = $"{propVarName}, {propValue}"; string? methodToCall = GetWriterMethod(propertyType); @@ -830,8 +907,8 @@ private string GenerateFastPathFuncForObject(TypeGenerationSpec typeGenSpec) else { serializationLogic = $@" - {WriterVarName}.WritePropertyName({propName}); - {GetSerializeLogicForNonPrimitiveType(propertyTypeSpec.TypeInfoPropertyName, propValue, propertyTypeSpec.GenerateSerializationLogic)}"; + {WriterVarName}.WritePropertyName({propVarName}); + {GetSerializeLogicForNonPrimitiveType(propertyTypeSpec, propValue)}"; } JsonIgnoreCondition ignoreCondition = propertyGenSpec.DefaultIgnoreCondition ?? options.DefaultIgnoreCondition; @@ -865,7 +942,7 @@ private string GenerateFastPathFuncForObject(TypeGenerationSpec typeGenSpec) sb.Append($@"((global::{JsonConstants.IJsonOnSerializedFullName}){ValueVarName}).OnSerialized();"); }; - return GenerateFastPathFuncForType(serializeMethodName, typeRef, sb.ToString(), typeGenSpec.CanBeNull); + return GenerateFastPathFuncForType(typeGenSpec, sb.ToString(), emitNullCheck: typeGenSpec.CanBeNull); } private static bool ShouldIncludePropertyForFastPath(PropertyGenerationSpec propertyGenSpec, JsonSourceGenerationOptionsAttribute options) @@ -965,14 +1042,20 @@ static string GetParamUnboxing(ParameterGenerationSpec spec, int index) return method; } - private string GenerateFastPathFuncForType(string serializeMethodName, string typeInfoTypeRef, string serializationLogic, bool canBeNull) + private string GenerateFastPathFuncForType(TypeGenerationSpec typeGenSpec, string serializeMethodBody, bool emitNullCheck) { + Debug.Assert(!emitNullCheck || typeGenSpec.CanBeNull); + + string serializeMethodName = $"{typeGenSpec.TypeInfoPropertyName}{SerializeHandlerPropName}"; + // fast path serializers for reference types always support null inputs. + string valueTypeRef = $"{typeGenSpec.TypeRef}{(typeGenSpec.IsValueType ? "" : "?")}"; + return $@" -private static void {serializeMethodName}({Utf8JsonWriterTypeRef} {WriterVarName}, {typeInfoTypeRef} {ValueVarName}) +private static void {serializeMethodName}({Utf8JsonWriterTypeRef} {WriterVarName}, {valueTypeRef} {ValueVarName}) {{ - {GetEarlyNullCheckSource(canBeNull)} - {serializationLogic} + {GetEarlyNullCheckSource(emitNullCheck)} + {serializeMethodBody} }}"; } @@ -988,16 +1071,17 @@ private string GetEarlyNullCheckSource(bool canBeNull) : null; } - private string GetSerializeLogicForNonPrimitiveType(string typeInfoPropertyName, string valueToWrite, bool serializationLogicGenerated) + private string GetSerializeLogicForNonPrimitiveType(TypeGenerationSpec typeGenerationSpec, string valueExpr) { - string typeInfoRef = $"{_currentContext.ContextTypeRef}.Default.{typeInfoPropertyName}"; + string valueExprSuffix = typeGenerationSpec.CanContainNullableReferenceAnnotations ? "!" : ""; - if (serializationLogicGenerated) + if (typeGenerationSpec.GenerateSerializationLogic) { - return $"{typeInfoPropertyName}{SerializeMethodNameSuffix}({WriterVarName}, {valueToWrite});"; + return $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}({WriterVarName}, {valueExpr}{valueExprSuffix});"; } - return $"{JsonSerializerTypeRef}.Serialize({WriterVarName}, {valueToWrite}, {typeInfoRef});"; + string typeInfoRef = $"{_currentContext.ContextTypeRef}.Default.{typeGenerationSpec.TypeInfoPropertyName}!"; + return $"{JsonSerializerTypeRef}.Serialize({WriterVarName}, {valueExpr}{valueExprSuffix}, {typeInfoRef});"; } private enum DefaultCheckType @@ -1044,7 +1128,7 @@ private string GenerateForType(TypeGenerationSpec typeMetadata, string metadataI {{ if (_{typeFriendlyName} == null) {{ - {WrapWithCheckForCustomConverterIfRequired(metadataInitSource, typeCompilableName, typeFriendlyName, GetNumberHandlingAsStr(typeMetadata.NumberHandling))} + {WrapWithCheckForCustomConverter(metadataInitSource, typeCompilableName, typeFriendlyName, GetNumberHandlingAsStr(typeMetadata.NumberHandling))} }} return _{typeFriendlyName}; @@ -1052,23 +1136,16 @@ private string GenerateForType(TypeGenerationSpec typeMetadata, string metadataI }}{additionalSource}"; } - private string WrapWithCheckForCustomConverterIfRequired(string source, string typeCompilableName, string typeFriendlyName, string numberHandlingNamedArg) - { - if (_currentContext.GenerationOptions.IgnoreRuntimeCustomConverters) - { - return source; - } - - return @$"{JsonConverterTypeRef}? customConverter; - if ({OptionsInstanceVariableName}.Converters.Count > 0 && (customConverter = {RuntimeCustomConverterFetchingMethodName}(typeof({typeCompilableName}))) != null) - {{ - _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeCompilableName)}({OptionsInstanceVariableName}, customConverter); - }} - else - {{ - {IndentSource(source, numIndentations: 1)} - }}"; - } + private string WrapWithCheckForCustomConverter(string source, string typeCompilableName, string typeFriendlyName, string numberHandlingNamedArg) + => @$"{JsonConverterTypeRef}? customConverter; + if ({OptionsInstanceVariableName}.Converters.Count > 0 && (customConverter = {RuntimeCustomConverterFetchingMethodName}(typeof({typeCompilableName}))) != null) + {{ + _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeCompilableName)}({OptionsInstanceVariableName}, customConverter); + }} + else + {{ + {IndentSource(source, numIndentations: 1)} + }}"; private string GetRootJsonContextImplementation() { @@ -1082,16 +1159,28 @@ private string GetRootJsonContextImplementation() private static {contextTypeRef}? {DefaultContextBackingStaticVarName}; public static {contextTypeRef} Default => {DefaultContextBackingStaticVarName} ??= new {contextTypeRef}(new {JsonSerializerOptionsTypeRef}({DefaultOptionsStaticVarName})); -public {contextTypeName}() : base(null, {DefaultOptionsStaticVarName}) +protected override {JsonSerializerOptionsTypeRef}? GeneratedSerializerOptions {{ get; }} = {DefaultOptionsStaticVarName}; + +public {contextTypeName}() : base(null) {{ }} -public {contextTypeName}({JsonSerializerOptionsTypeRef} options) : base(options, {DefaultOptionsStaticVarName}) +public {contextTypeName}({JsonSerializerOptionsTypeRef} options) : base(options) {{ }} {GetFetchLogicForRuntimeSpecifiedCustomConverter()}"); + if (_generateGetConverterMethodForProperties) + { + sb.Append(GetFetchLogicForGetCustomConverter_PropertiesWithFactories()); + } + + if (_generateGetConverterMethodForProperties || _generateGetConverterMethodForTypes) + { + sb.Append(GetFetchLogicForGetCustomConverter_TypesWithFactories()); + } + return sb.ToString(); } @@ -1108,20 +1197,15 @@ private string GetLogicForDefaultSerializerOptionsInit() private static {JsonSerializerOptionsTypeRef} {DefaultOptionsStaticVarName} {{ get; }} = new {JsonSerializerOptionsTypeRef}() {{ DefaultIgnoreCondition = {JsonIgnoreConditionTypeRef}.{options.DefaultIgnoreCondition}, - IgnoreReadOnlyFields = {ToCSharpKeyword(options.IgnoreReadOnlyFields)}, - IgnoreReadOnlyProperties = {ToCSharpKeyword(options.IgnoreReadOnlyProperties)}, - IncludeFields = {ToCSharpKeyword(options.IncludeFields)}, - WriteIndented = {ToCSharpKeyword(options.WriteIndented)},{namingPolicyInit} + IgnoreReadOnlyFields = {FormatBool(options.IgnoreReadOnlyFields)}, + IgnoreReadOnlyProperties = {FormatBool(options.IgnoreReadOnlyProperties)}, + IncludeFields = {FormatBool(options.IncludeFields)}, + WriteIndented = {FormatBool(options.WriteIndented)},{namingPolicyInit} }};"; } private string GetFetchLogicForRuntimeSpecifiedCustomConverter() { - if (_currentContext.GenerationOptions.IgnoreRuntimeCustomConverters) - { - return ""; - } - // TODO (https://github.com/dotnet/runtime/issues/52218): use a dictionary if count > ~15. return @$"private {JsonConverterTypeRef}? {RuntimeCustomConverterFetchingMethodName}({TypeTypeRef} type) {{ @@ -1138,7 +1222,7 @@ private string GetFetchLogicForRuntimeSpecifiedCustomConverter() converter = factory.CreateConverter(type, {OptionsInstanceVariableName}); if (converter == null || converter is {JsonConverterFactoryTypeRef}) {{ - throw new {InvalidOperationExceptionTypeRef}($""The converter '{{factory.GetType()}}' cannot return null or a JsonConverterFactory instance.""); + throw new {InvalidOperationExceptionTypeRef}(string.Format(""{ExceptionMessages.InvalidJsonConverterFactoryOutput}"", factory.GetType())); }} }} @@ -1150,6 +1234,32 @@ private string GetFetchLogicForRuntimeSpecifiedCustomConverter() }}"; } + private string GetFetchLogicForGetCustomConverter_PropertiesWithFactories() + { + return @$" + +private {JsonConverterTypeRef} {GetConverterFromFactoryMethodName}({JsonConverterFactoryTypeRef} factory) +{{ + return ({JsonConverterTypeRef}) {GetConverterFromFactoryMethodName}(typeof(T), factory); +}}"; + } + + private string GetFetchLogicForGetCustomConverter_TypesWithFactories() + { + return @$" + +private {JsonConverterTypeRef} {GetConverterFromFactoryMethodName}({TypeTypeRef} type, {JsonConverterFactoryTypeRef} factory) +{{ + {JsonConverterTypeRef}? converter = factory.CreateConverter(type, {Emitter.OptionsInstanceVariableName}); + if (converter == null || converter is {JsonConverterFactoryTypeRef}) + {{ + throw new {InvalidOperationExceptionTypeRef}(string.Format(""{ExceptionMessages.InvalidJsonConverterFactoryOutput}"", factory.GetType())); + }} + + return converter; +}}"; + } + private string GetGetTypeInfoImplementation() { StringBuilder sb = new(); @@ -1190,10 +1300,10 @@ private string GetPropertyNameInitialization() StringBuilder sb = new(); - foreach (string propName in _currentContext.RuntimePropertyNames) + foreach (KeyValuePair name_varName_pair in _currentContext.RuntimePropertyNames) { sb.Append($@" -private static {JsonEncodedTextTypeRef} {propName}PropName = {JsonEncodedTextTypeRef}.Encode(""{propName}"");"); +private static readonly {JsonEncodedTextTypeRef} {name_varName_pair.Value} = {JsonEncodedTextTypeRef}.Encode(""{name_varName_pair.Key}"");"); } return sb.ToString(); @@ -1211,20 +1321,64 @@ private static string GetNumberHandlingAsStr(JsonNumberHandling? numberHandling) : "default"; private static string GetCreateValueInfoMethodRef(string typeCompilableName) => $"{CreateValueInfoMethodName}<{typeCompilableName}>"; - } - private static string ToCSharpKeyword(bool value) => value.ToString().ToLowerInvariant(); + private static string FormatBool(bool value) => value ? "true" : "false"; - private static string GetParamDefaultValueAsString(object? value) - { - switch (value) + private string GetParamDefaultValueAsString(object? value, Type type, string typeRef) { - case null: - return "null"; - case bool boolVal: - return ToCSharpKeyword(boolVal); - default: - return value!.ToString(); + if (value == null) + { + return $"default({typeRef})"; + } + + if (type.IsEnum) + { + // Roslyn gives us an instance of the underlying type, which is numerical. +#if DEBUG + Type runtimeType = _generationSpec.MetadataLoadContext.Resolve(value.GetType()); + Debug.Assert(_generationSpec.IsNumberType(runtimeType)); +#endif + + // Return the numeric value. + return FormatNumber(); + } + + switch (value) + { + case string @string: + return SymbolDisplay.FormatLiteral(@string, quote: true); ; + case char @char: + return SymbolDisplay.FormatLiteral(@char, quote: true); + case double.NegativeInfinity: + return "double.NegativeInfinity"; + case double.PositiveInfinity: + return "double.PositiveInfinity"; + case double.NaN: + return "double.NaN"; + case double @double: + return $"({typeRef})({@double.ToString(JsonConstants.DoubleFormatString, CultureInfo.InvariantCulture)})"; + case float.NegativeInfinity: + return "float.NegativeInfinity"; + case float.PositiveInfinity: + return "float.PositiveInfinity"; + case float.NaN: + return "float.NaN"; + case float @float: + return $"({typeRef})({@float.ToString(JsonConstants.SingleFormatString, CultureInfo.InvariantCulture)})"; + case decimal.MaxValue: + return "decimal.MaxValue"; + case decimal.MinValue: + return "decimal.MinValue"; + case decimal @decimal: + return @decimal.ToString(CultureInfo.InvariantCulture); + case bool @bool: + return FormatBool(@bool); + default: + // Assume this is a number. + return FormatNumber(); + } + + string FormatNumber() => $"({typeRef})({Convert.ToString(value, CultureInfo.InvariantCulture)})"; } } } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index 33a60562a3a10e..92c60d4ace019c 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -13,6 +14,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; using Microsoft.CodeAnalysis.Text; namespace System.Text.Json.SourceGeneration @@ -23,15 +25,32 @@ private sealed class Parser { private const string SystemTextJsonNamespace = "System.Text.Json"; private const string JsonConverterAttributeFullName = "System.Text.Json.Serialization.JsonConverterAttribute"; + private const string JsonConverterFactoryFullName = "System.Text.Json.Serialization.JsonConverterFactory"; + private const string JsonConverterOfTFullName = "System.Text.Json.Serialization.JsonConverter`1"; + private const string JsonArrayFullName = "System.Text.Json.Nodes.JsonArray"; private const string JsonElementFullName = "System.Text.Json.JsonElement"; + private const string JsonExtensionDataAttributeFullName = "System.Text.Json.Serialization.JsonExtensionDataAttribute"; + private const string JsonNodeFullName = "System.Text.Json.Nodes.JsonNode"; + private const string JsonObjectFullName = "System.Text.Json.Nodes.JsonObject"; + private const string JsonValueFullName = "System.Text.Json.Nodes.JsonValue"; private const string JsonIgnoreAttributeFullName = "System.Text.Json.Serialization.JsonIgnoreAttribute"; private const string JsonIgnoreConditionFullName = "System.Text.Json.Serialization.JsonIgnoreCondition"; private const string JsonIncludeAttributeFullName = "System.Text.Json.Serialization.JsonIncludeAttribute"; private const string JsonNumberHandlingAttributeFullName = "System.Text.Json.Serialization.JsonNumberHandlingAttribute"; private const string JsonPropertyNameAttributeFullName = "System.Text.Json.Serialization.JsonPropertyNameAttribute"; private const string JsonPropertyOrderAttributeFullName = "System.Text.Json.Serialization.JsonPropertyOrderAttribute"; + private const string JsonSerializerContextFullName = "System.Text.Json.Serialization.JsonSerializerContext"; + private const string JsonSerializerAttributeFullName = "System.Text.Json.Serialization.JsonSerializableAttribute"; + private const string JsonSourceGenerationOptionsAttributeFullName = "System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute"; - private readonly GeneratorExecutionContext _executionContext; + private const string DateOnlyFullName = "System.DateOnly"; + private const string TimeOnlyFullName = "System.TimeOnly"; + private const string IAsyncEnumerableFullName = "System.Collections.Generic.IAsyncEnumerable`1"; + + private const string DictionaryTypeRef = "global::System.Collections.Generic.Dictionary"; + + private readonly Compilation _compilation; + private readonly JsonSourceGenerationContext _sourceGenerationContext; private readonly MetadataLoadContextInternal _metadataLoadContext; private readonly Type _ilistOfTType; @@ -43,7 +62,7 @@ private sealed class Parser private readonly Type? _dictionaryType; private readonly Type? _idictionaryOfTKeyTValueType; private readonly Type? _ireadonlyDictionaryType; - private readonly Type? _isetType; + private readonly Type? _isetType; private readonly Type? _stackOfTType; private readonly Type? _queueOfTType; private readonly Type? _concurrentStackType; @@ -61,15 +80,36 @@ private sealed class Parser private readonly Type _objectType; private readonly Type _stringType; + private readonly Type? _timeSpanType; private readonly Type? _dateTimeOffsetType; private readonly Type? _byteArrayType; private readonly Type? _guidType; private readonly Type? _uriType; private readonly Type? _versionType; + private readonly Type? _jsonArrayType; private readonly Type? _jsonElementType; + private readonly Type? _jsonNodeType; + private readonly Type? _jsonObjectType; + private readonly Type? _jsonValueType; + + // Unsupported types + private readonly Type _delegateType; + private readonly Type _typeType; + private readonly Type _serializationInfoType; + private readonly Type _intPtrType; + private readonly Type _uIntPtrType; + + // Unsupported types that may not resolve + private readonly Type? _iAsyncEnumerableGenericType; + private readonly Type? _dateOnlyType; + private readonly Type? _timeOnlyType; + + // Needed for converter validation + private readonly Type _jsonConverterOfTType; private readonly HashSet _numberTypes = new(); private readonly HashSet _knownTypes = new(); + private readonly HashSet _knownUnsupportedTypes = new(); /// /// Type information for member types in input object graphs. @@ -78,6 +118,14 @@ private sealed class Parser private readonly HashSet _implicitlyRegisteredTypes = new(); + /// + /// A list of diagnostics emitted at the type level. This is cached and emitted between the processing of context types + /// in order to properly retrieve [JsonSerializable] attribute applications for top-level types (since a type might occur + /// both at top-level and in nested object graphs, with no guarantee of the order that we will see the type). + /// The element tuple types specifies the serializable type, the kind of diagnostic to emit, and the diagnostic message. + /// + private readonly List<(Type, DiagnosticDescriptor, string[])> _typeLevelDiagnostics = new(); + private JsonKnownNamingPolicy _currentContextNamingPolicy; private static DiagnosticDescriptor ContextClassesMustBePartial { get; } = new DiagnosticDescriptor( @@ -96,10 +144,43 @@ private sealed class Parser defaultSeverity: DiagnosticSeverity.Error, isEnabledByDefault: true); - public Parser(in GeneratorExecutionContext executionContext) + private static DiagnosticDescriptor MultipleJsonExtensionDataAttribute { get; } = new DiagnosticDescriptor( + id: "SYSLIB1035", + title: new LocalizableResourceString(nameof(SR.MultipleJsonExtensionDataAttributeTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + messageFormat: new LocalizableResourceString(nameof(SR.MultipleJsonExtensionDataAttributeFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + category: JsonConstants.SystemTextJsonSourceGenerationName, + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true); + + private static DiagnosticDescriptor DataExtensionPropertyInvalid { get; } = new DiagnosticDescriptor( + id: "SYSLIB1036", + title: new LocalizableResourceString(nameof(SR.DataExtensionPropertyInvalidTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + messageFormat: new LocalizableResourceString(nameof(SR.DataExtensionPropertyInvalidFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + category: JsonConstants.SystemTextJsonSourceGenerationName, + defaultSeverity: DiagnosticSeverity.Error, + isEnabledByDefault: true); + + private static DiagnosticDescriptor InitOnlyPropertyDeserializationNotSupported { get; } = new DiagnosticDescriptor( + id: "SYSLIB1037", + title: new LocalizableResourceString(nameof(SR.InitOnlyPropertyDeserializationNotSupportedTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + messageFormat: new LocalizableResourceString(nameof(SR.InitOnlyPropertyDeserializationNotSupportedFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + category: JsonConstants.SystemTextJsonSourceGenerationName, + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + private static DiagnosticDescriptor InaccessibleJsonIncludePropertiesNotSupported { get; } = new DiagnosticDescriptor( + id: "SYSLIB1038", + title: new LocalizableResourceString(nameof(SR.InaccessibleJsonIncludePropertiesNotSupportedTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + messageFormat: new LocalizableResourceString(nameof(SR.InaccessibleJsonIncludePropertiesNotSupportedFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + category: JsonConstants.SystemTextJsonSourceGenerationName, + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + public Parser(Compilation compilation, in JsonSourceGenerationContext sourceGenerationContext) { - _executionContext = executionContext; - _metadataLoadContext = new MetadataLoadContextInternal(executionContext.Compilation); + _compilation = compilation; + _sourceGenerationContext = sourceGenerationContext; + _metadataLoadContext = new MetadataLoadContextInternal(_compilation); _ilistOfTType = _metadataLoadContext.Resolve(SpecialType.System_Collections_Generic_IList_T); _icollectionOfTType = _metadataLoadContext.Resolve(SpecialType.System_Collections_Generic_ICollection_T); @@ -123,29 +204,50 @@ public Parser(in GeneratorExecutionContext executionContext) _booleanType = _metadataLoadContext.Resolve(SpecialType.System_Boolean); _charType = _metadataLoadContext.Resolve(SpecialType.System_Char); + _timeSpanType = _metadataLoadContext.Resolve(typeof(TimeSpan)); _dateTimeType = _metadataLoadContext.Resolve(SpecialType.System_DateTime); _nullableOfTType = _metadataLoadContext.Resolve(SpecialType.System_Nullable_T); _objectType = _metadataLoadContext.Resolve(SpecialType.System_Object); _stringType = _metadataLoadContext.Resolve(SpecialType.System_String); _dateTimeOffsetType = _metadataLoadContext.Resolve(typeof(DateTimeOffset)); - _byteArrayType = _metadataLoadContext.Resolve(typeof(byte[])); + _byteArrayType = _metadataLoadContext.Resolve(typeof(byte)).MakeArrayType(); _guidType = _metadataLoadContext.Resolve(typeof(Guid)); _uriType = _metadataLoadContext.Resolve(typeof(Uri)); _versionType = _metadataLoadContext.Resolve(typeof(Version)); + _jsonArrayType = _metadataLoadContext.Resolve(JsonArrayFullName); _jsonElementType = _metadataLoadContext.Resolve(JsonElementFullName); + _jsonNodeType = _metadataLoadContext.Resolve(JsonNodeFullName); + _jsonObjectType = _metadataLoadContext.Resolve(JsonObjectFullName); + _jsonValueType = _metadataLoadContext.Resolve(JsonValueFullName); + + // Unsupported types. + _delegateType = _metadataLoadContext.Resolve(SpecialType.System_Delegate); + _typeType = _metadataLoadContext.Resolve(typeof(Type)); + _serializationInfoType = _metadataLoadContext.Resolve(typeof(Runtime.Serialization.SerializationInfo)); + _intPtrType = _metadataLoadContext.Resolve(typeof(IntPtr)); + _uIntPtrType = _metadataLoadContext.Resolve(typeof(UIntPtr)); + _iAsyncEnumerableGenericType = _metadataLoadContext.Resolve(IAsyncEnumerableFullName); + _dateOnlyType = _metadataLoadContext.Resolve(DateOnlyFullName); + _timeOnlyType = _metadataLoadContext.Resolve(TimeOnlyFullName); + + _jsonConverterOfTType = _metadataLoadContext.Resolve(JsonConverterOfTFullName); PopulateKnownTypes(); } - public SourceGenerationSpec? GetGenerationSpec(List classDeclarationSyntaxList) + public SourceGenerationSpec? GetGenerationSpec(IEnumerable classDeclarationSyntaxList) { - Compilation compilation = _executionContext.Compilation; - INamedTypeSymbol jsonSerializerContextSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSerializerContext"); - INamedTypeSymbol jsonSerializableAttributeSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSerializableAttribute"); - INamedTypeSymbol jsonSourceGenerationOptionsAttributeSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute"); - - if (jsonSerializerContextSymbol == null || jsonSerializableAttributeSymbol == null || jsonSourceGenerationOptionsAttributeSymbol == null) + Compilation compilation = _compilation; + INamedTypeSymbol jsonSerializerContextSymbol = compilation.GetBestTypeByMetadataName(JsonSerializerContextFullName); + INamedTypeSymbol jsonSerializableAttributeSymbol = compilation.GetBestTypeByMetadataName(JsonSerializerAttributeFullName); + INamedTypeSymbol jsonSourceGenerationOptionsAttributeSymbol = compilation.GetBestTypeByMetadataName(JsonSourceGenerationOptionsAttributeFullName); + INamedTypeSymbol jsonConverterOfTAttributeSymbol = compilation.GetBestTypeByMetadataName(JsonConverterOfTFullName); + + if (jsonSerializerContextSymbol == null || + jsonSerializableAttributeSymbol == null || + jsonSourceGenerationOptionsAttributeSymbol == null || + jsonConverterOfTAttributeSymbol == null) { return null; } @@ -154,6 +256,11 @@ public Parser(in GeneratorExecutionContext executionContext) foreach (ClassDeclarationSyntax classDeclarationSyntax in classDeclarationSyntaxList) { + // Ensure context-scoped metadata caches are empty. + Debug.Assert(_typeGenerationSpecCache.Count == 0); + Debug.Assert(_implicitlyRegisteredTypes.Count == 0); + Debug.Assert(_typeLevelDiagnostics.Count == 0); + CompilationUnitSyntax compilationUnitSyntax = classDeclarationSyntax.FirstAncestorOrSelf(); SemanticModel compilationSemanticModel = compilation.GetSemanticModel(compilationUnitSyntax.SyntaxTree); @@ -195,15 +302,18 @@ public Parser(in GeneratorExecutionContext executionContext) INamedTypeSymbol contextTypeSymbol = (INamedTypeSymbol)compilationSemanticModel.GetDeclaredSymbol(classDeclarationSyntax); Debug.Assert(contextTypeSymbol != null); + Location contextLocation = contextTypeSymbol.Locations.Length > 0 ? contextTypeSymbol.Locations[0] : Location.None; + if (!TryGetClassDeclarationList(contextTypeSymbol, out List classDeclarationList)) { // Class or one of its containing types is not partial so we can't add to it. - _executionContext.ReportDiagnostic(Diagnostic.Create(ContextClassesMustBePartial, Location.None, new string[] { contextTypeSymbol.Name })); + _sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(ContextClassesMustBePartial, contextLocation, new string[] { contextTypeSymbol.Name })); continue; } ContextGenerationSpec contextGenSpec = new() { + Location = contextLocation, GenerationOptions = options ?? new JsonSourceGenerationOptionsAttribute(), ContextType = contextTypeSymbol.AsType(_metadataLoadContext), ContextClassDeclarationList = classDeclarationList @@ -226,14 +336,31 @@ public Parser(in GeneratorExecutionContext executionContext) continue; } + // Emit type-level diagnostics + foreach ((Type Type, DiagnosticDescriptor Descriptor, string[] MessageArgs) diagnostic in _typeLevelDiagnostics) + { + Type type = diagnostic.Type; + Location location = type.GetDiagnosticLocation(); + + if (location == null) + { + TypeGenerationSpec spec = _typeGenerationSpecCache[type]; + location = spec.AttributeLocation; + } + + location ??= contextLocation; + _sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(diagnostic.Descriptor, location, diagnostic.MessageArgs)); + } + contextGenSpec.ImplicitlyRegisteredTypes.UnionWith(_implicitlyRegisteredTypes); contextGenSpecList ??= new List(); contextGenSpecList.Add(contextGenSpec); - // Clear the cache of generated metadata between the processing of context classes. + // Clear the caches of generated metadata between the processing of context classes. _typeGenerationSpecCache.Clear(); _implicitlyRegisteredTypes.Clear(); + _typeLevelDiagnostics.Clear(); } if (contextGenSpecList == null) @@ -252,6 +379,9 @@ public Parser(in GeneratorExecutionContext executionContext) GuidType = _guidType, StringType = _stringType, NumberTypes = _numberTypes, +#if DEBUG + MetadataLoadContext = _metadataLoadContext, +#endif }; } @@ -397,9 +527,41 @@ private static bool TryGetClassDeclarationList(INamedTypeSymbol typeSymbol, [Not typeGenerationSpec.GenerationMode = generationMode; } + typeGenerationSpec.AttributeLocation = attributeSyntax.GetLocation(); + return typeGenerationSpec; } + internal static bool IsSyntaxTargetForGeneration(SyntaxNode node) => node is ClassDeclarationSyntax { AttributeLists: { Count: > 0 }, BaseList: { Types : {Count : > 0 } } }; + + internal static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context) + { + var classDeclarationSyntax = (ClassDeclarationSyntax)context.Node; + + foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists) + { + foreach (AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) + { + IMethodSymbol attributeSymbol = context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol as IMethodSymbol; + if (attributeSymbol == null) + { + continue; + } + + INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType; + string fullName = attributeContainingTypeSymbol.ToDisplayString(); + + if (fullName == "System.Text.Json.Serialization.JsonSerializableAttribute") + { + return classDeclarationSyntax; + } + } + + } + + return null; + } + private static JsonSourceGenerationMode? GetJsonSourceGenerationModeEnumVal(SyntaxNode propertyValueMode) { IEnumerable enumTokens = propertyValueMode @@ -465,14 +627,6 @@ private static bool TryGetClassDeclarationList(INamedTypeSymbol typeSymbol, [Not } } break; - case nameof(JsonSourceGenerationOptionsAttribute.IgnoreRuntimeCustomConverters): - { - if (bool.TryParse(propertyValueStr, out bool value)) - { - options.IgnoreRuntimeCustomConverters = value; - } - } - break; case nameof(JsonSourceGenerationOptionsAttribute.IncludeFields): { if (bool.TryParse(propertyValueStr, out bool value)) @@ -526,9 +680,11 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener _typeGenerationSpecCache[type] = typeMetadata; ClassType classType; - Type? collectionKeyType = null; - Type? collectionValueType = null; + TypeGenerationSpec? collectionKeyTypeSpec = null; + TypeGenerationSpec? collectionValueTypeSpec = null; TypeGenerationSpec? nullableUnderlyingTypeGenSpec = null; + TypeGenerationSpec? dataExtensionPropGenSpec = null; + string? runtimeTypeRef = null; List? propGenSpecList = null; ObjectConstructionStrategy constructionStrategy = default; ParameterGenerationSpec[]? paramGenSpecArray = null; @@ -538,6 +694,10 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener string? converterInstatiationLogic = null; bool implementsIJsonOnSerialized = false; bool implementsIJsonOnSerializing = false; + bool hasInitOnlyProperties = false; + bool hasTypeFactoryConverter = false; + bool hasPropertyFactoryConverters = false; + bool canContainNullableReferenceAnnotations = type.CanContainNullableReferenceTypeAnnotations(); IList attributeDataList = CustomAttributeData.GetCustomAttributes(type); foreach (CustomAttributeData attributeData in attributeDataList) @@ -552,7 +712,11 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener else if (!foundDesignTimeCustomConverter && attributeType.GetCompatibleBaseClass(JsonConverterAttributeFullName) != null) { foundDesignTimeCustomConverter = true; - converterInstatiationLogic = GetConverterInstantiationLogic(attributeData); + converterInstatiationLogic = GetConverterInstantiationLogic( + type, + attributeData, + forType: true, + ref hasTypeFactoryConverter); } } @@ -585,6 +749,9 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener } Type actualTypeToConvert; + Type? keyType = null; + Type valueType; + bool needsRuntimeType = false; if (type.IsArray) { @@ -592,13 +759,13 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener ? ClassType.TypeUnsupportedBySourceGen // Multi-dimentional arrays are not supported in STJ. : ClassType.Enumerable; collectionType = CollectionType.Array; - collectionValueType = type.GetElementType(); + valueType = type.GetElementType(); } else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _listOfTType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.List; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _dictionaryType)) != null) { @@ -606,8 +773,8 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener collectionType = CollectionType.Dictionary; Type[] genericArgs = actualTypeToConvert.GetGenericArguments(); - collectionKeyType = genericArgs[0]; - collectionValueType = genericArgs[1]; + keyType = genericArgs[0]; + valueType = genericArgs[1]; } else if (type.IsImmutableDictionaryType(sourceGenType: true)) { @@ -615,8 +782,8 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener collectionType = CollectionType.ImmutableDictionary; Type[] genericArgs = type.GetGenericArguments(); - collectionKeyType = genericArgs[0]; - collectionValueType = genericArgs[1]; + keyType = genericArgs[0]; + valueType = genericArgs[1]; } else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_idictionaryOfTKeyTValueType)) != null) { @@ -624,8 +791,10 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener collectionType = CollectionType.IDictionaryOfTKeyTValue; Type[] genericArgs = actualTypeToConvert.GetGenericArguments(); - collectionKeyType = genericArgs[0]; - collectionValueType = genericArgs[1]; + keyType = genericArgs[0]; + valueType = genericArgs[1]; + + needsRuntimeType = type == actualTypeToConvert; } else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_ireadonlyDictionaryType)) != null) { @@ -633,94 +802,116 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener collectionType = CollectionType.IReadOnlyDictionary; Type[] genericArgs = actualTypeToConvert.GetGenericArguments(); - collectionKeyType = genericArgs[0]; - collectionValueType = genericArgs[1]; + keyType = genericArgs[0]; + valueType = genericArgs[1]; + + needsRuntimeType = type == actualTypeToConvert; } else if (type.IsImmutableEnumerableType(sourceGenType: true)) { classType = ClassType.Enumerable; collectionType = CollectionType.ImmutableEnumerable; - collectionValueType = type.GetGenericArguments()[0]; + valueType = type.GetGenericArguments()[0]; } else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_ilistOfTType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.IListOfT; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_isetType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.ISet; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_icollectionOfTType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.ICollectionOfT; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _stackOfTType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.StackOfT; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = GetCompatibleGenericBaseClass(type, _queueOfTType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.QueueOfT; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = type.GetCompatibleGenericBaseClass(_concurrentStackType, _objectType, sourceGenType: true)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.ConcurrentStack; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = type.GetCompatibleGenericBaseClass(_concurrentQueueType, _objectType, sourceGenType: true)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.ConcurrentQueue; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if ((actualTypeToConvert = type.GetCompatibleGenericInterface(_ienumerableOfTType)) != null) { classType = ClassType.Enumerable; collectionType = CollectionType.IEnumerableOfT; - collectionValueType = actualTypeToConvert.GetGenericArguments()[0]; + valueType = actualTypeToConvert.GetGenericArguments()[0]; } else if (_idictionaryType.IsAssignableFrom(type)) { classType = ClassType.Dictionary; collectionType = CollectionType.IDictionary; - collectionKeyType = _stringType; - collectionValueType = _objectType; + keyType = _stringType; + valueType = _objectType; + + needsRuntimeType = type == actualTypeToConvert; } else if (_ilistType.IsAssignableFrom(type)) { classType = ClassType.Enumerable; collectionType = CollectionType.IList; - collectionValueType = _objectType; + valueType = _objectType; } else if (_stackType.IsAssignableFrom(type)) { classType = ClassType.Enumerable; collectionType = CollectionType.Stack; - collectionValueType = _objectType; + valueType = _objectType; } else if (_queueType.IsAssignableFrom(type)) { classType = ClassType.Enumerable; collectionType = CollectionType.Queue; - collectionValueType = _objectType; + valueType = _objectType; } else { classType = ClassType.Enumerable; collectionType = CollectionType.IEnumerable; - collectionValueType = _objectType; + valueType = _objectType; } + + collectionValueTypeSpec = GetOrAddTypeGenerationSpec(valueType, generationMode); + + if (keyType != null) + { + collectionKeyTypeSpec = GetOrAddTypeGenerationSpec(keyType, generationMode); + + if (needsRuntimeType) + { + runtimeTypeRef = GetDictionaryTypeRef(collectionKeyTypeSpec, collectionValueTypeSpec); + } + } + } + else if (_knownUnsupportedTypes.Contains(type) || + ImplementsIAsyncEnumerableInterface(type) || + _delegateType.IsAssignableFrom(type)) + { + classType = ClassType.KnownUnsupportedType; } else { @@ -729,7 +920,7 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener if (!type.TryGetDeserializationConstructor(useDefaultCtorInAnnotatedStructs, out ConstructorInfo? constructor)) { classType = ClassType.TypeUnsupportedBySourceGen; - _executionContext.ReportDiagnostic(Diagnostic.Create(MultipleJsonConstructorAttribute, Location.None, new string[] { $"{type}" })); + _typeLevelDiagnostics.Add((type, MultipleJsonConstructorAttribute, new string[] { $"{type}" })); } else { @@ -783,6 +974,8 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener for (Type? currentType = type; currentType != null; currentType = currentType.BaseType) { + PropertyGenerationSpec spec; + foreach (PropertyInfo propertyInfo in currentType.GetProperties(bindingFlags)) { bool isVirtual = propertyInfo.IsVirtual(); @@ -793,9 +986,8 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener continue; } - PropertyGenerationSpec spec = GetPropertyGenerationSpec(propertyInfo, isVirtual, generationMode); - CacheMember(spec, ref propGenSpecList, ref ignoredMembers); - propertyOrderSpecified |= spec.Order != 0; + spec = GetPropertyGenerationSpec(propertyInfo, isVirtual, generationMode); + CacheMemberHelper(propertyInfo.GetDiagnosticLocation()); } foreach (FieldInfo fieldInfo in currentType.GetFields(bindingFlags)) @@ -805,9 +997,47 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener continue; } - PropertyGenerationSpec spec = GetPropertyGenerationSpec(fieldInfo, isVirtual: false, generationMode); + spec = GetPropertyGenerationSpec(fieldInfo, isVirtual: false, generationMode); + CacheMemberHelper(fieldInfo.GetDiagnosticLocation()); + } + + void CacheMemberHelper(Location memberLocation) + { CacheMember(spec, ref propGenSpecList, ref ignoredMembers); + propertyOrderSpecified |= spec.Order != 0; + hasPropertyFactoryConverters |= spec.HasFactoryConverter; + + // The property type may be implicitly in the context, so add that as well. + hasTypeFactoryConverter |= spec.TypeGenerationSpec.HasTypeFactoryConverter; + + if (spec.IsExtensionData) + { + if (dataExtensionPropGenSpec != null) + { + _typeLevelDiagnostics.Add((type, MultipleJsonExtensionDataAttribute, new string[] { type.Name })); + } + + Type propType = spec.TypeGenerationSpec.Type; + if (!IsValidDataExtensionPropertyType(propType)) + { + _sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(DataExtensionPropertyInvalid, memberLocation, new string[] { type.Name, spec.ClrName })); + } + + dataExtensionPropGenSpec = GetOrAddTypeGenerationSpec(propType, generationMode); + _implicitlyRegisteredTypes.Add(dataExtensionPropGenSpec); + } + + if (!hasInitOnlyProperties && spec.CanUseSetter && spec.IsInitOnlySetter) + { + _sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(InitOnlyPropertyDeserializationNotSupported, memberLocation, new string[] { type.Name })); + hasInitOnlyProperties = true; + } + + if (spec.HasJsonInclude && (!spec.CanUseGetter || !spec.CanUseSetter || !spec.IsPublic)) + { + _sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(InaccessibleJsonIncludePropertiesNotSupported, memberLocation, new string[] { type.Name, spec.ClrName })); + } } } @@ -826,17 +1056,52 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener propGenSpecList, paramGenSpecArray, collectionType, - collectionKeyTypeMetadata: collectionKeyType != null ? GetOrAddTypeGenerationSpec(collectionKeyType, generationMode) : null, - collectionValueTypeMetadata: collectionValueType != null ? GetOrAddTypeGenerationSpec(collectionValueType, generationMode) : null, + collectionKeyTypeSpec, + collectionValueTypeSpec, constructionStrategy, nullableUnderlyingTypeMetadata: nullableUnderlyingTypeGenSpec, + runtimeTypeRef, + dataExtensionPropGenSpec, converterInstatiationLogic, - implementsIJsonOnSerialized, - implementsIJsonOnSerializing); + implementsIJsonOnSerialized : implementsIJsonOnSerialized, + implementsIJsonOnSerializing : implementsIJsonOnSerializing, + canContainNullableReferenceAnnotations: canContainNullableReferenceAnnotations, + hasTypeFactoryConverter : hasTypeFactoryConverter, + hasPropertyFactoryConverters : hasPropertyFactoryConverters); return typeMetadata; } + private bool ImplementsIAsyncEnumerableInterface(Type type) + { + if (_iAsyncEnumerableGenericType == null) + { + return false; + } + + return type.GetCompatibleGenericInterface(_iAsyncEnumerableGenericType) is not null; + } + + private static string GetDictionaryTypeRef(TypeGenerationSpec keyType, TypeGenerationSpec valueType) + => $"{DictionaryTypeRef}<{keyType.TypeRef}, {valueType.TypeRef}>"; + + private bool IsValidDataExtensionPropertyType(Type type) + { + if (type == _jsonObjectType) + { + return true; + } + + Type? actualDictionaryType = type.GetCompatibleGenericInterface(_idictionaryOfTKeyTValueType); + if (actualDictionaryType == null) + { + return false; + } + + Type[] genericArguments = actualDictionaryType.GetGenericArguments(); + return genericArguments[0] == _stringType && (genericArguments[1] == _objectType || genericArguments[1] == _jsonElementType); + } + private Type GetCompatibleGenericBaseClass(Type type, Type baseType) => type.GetCompatibleGenericBaseClass(baseType, _objectType); @@ -870,18 +1135,106 @@ private static bool PropertyIsOverridenAndIgnored( ignoredMember.IsVirtual; } - private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, bool isVirtual, JsonSourceGenerationMode generationMode) + private PropertyGenerationSpec GetPropertyGenerationSpec( + MemberInfo memberInfo, + bool isVirtual, + JsonSourceGenerationMode generationMode) { + Type memberCLRType = GetMemberClrType(memberInfo); IList attributeDataList = CustomAttributeData.GetCustomAttributes(memberInfo); - bool hasJsonInclude = false; - JsonIgnoreCondition? ignoreCondition = null; - JsonNumberHandling? numberHandling = null; - string? jsonPropertyName = null; + ProcessMemberCustomAttributes( + attributeDataList, + memberCLRType, + out bool hasJsonInclude, + out string? jsonPropertyName, + out JsonIgnoreCondition? ignoreCondition, + out JsonNumberHandling? numberHandling, + out string? converterInstantiationLogic, + out int order, + out bool hasFactoryConverter, + out bool isExtensionData); + + ProcessMember( + memberInfo, + memberCLRType, + hasJsonInclude, + out bool isReadOnly, + out bool isPublic, + out bool canUseGetter, + out bool canUseSetter, + out bool getterIsVirtual, + out bool setterIsVirtual, + out bool setterIsInitOnly); + + string clrName = memberInfo.Name; + string runtimePropertyName = DetermineRuntimePropName(clrName, jsonPropertyName, _currentContextNamingPolicy); + string propertyNameVarName = DeterminePropNameIdentifier(runtimePropertyName); + + return new PropertyGenerationSpec + { + ClrName = clrName, + IsProperty = memberInfo.MemberType == MemberTypes.Property, + IsPublic = isPublic, + IsVirtual = isVirtual, + JsonPropertyName = jsonPropertyName, + RuntimePropertyName = runtimePropertyName, + PropertyNameVarName = propertyNameVarName, + IsReadOnly = isReadOnly, + IsInitOnlySetter = setterIsInitOnly, + CanUseGetter = canUseGetter, + CanUseSetter = canUseSetter, + GetterIsVirtual = getterIsVirtual, + SetterIsVirtual = setterIsVirtual, + DefaultIgnoreCondition = ignoreCondition, + NumberHandling = numberHandling, + Order = order, + HasJsonInclude = hasJsonInclude, + IsExtensionData = isExtensionData, + TypeGenerationSpec = GetOrAddTypeGenerationSpec(memberCLRType, generationMode), + DeclaringTypeRef = memberInfo.DeclaringType.GetCompilableName(), + ConverterInstantiationLogic = converterInstantiationLogic, + HasFactoryConverter = hasFactoryConverter + }; + } + + private Type GetMemberClrType(MemberInfo memberInfo) + { + if (memberInfo is PropertyInfo propertyInfo) + { + return propertyInfo.PropertyType; + } + + if (memberInfo is FieldInfo fieldInfo) + { + return fieldInfo.FieldType; + } + + throw new InvalidOperationException(); + } + + private void ProcessMemberCustomAttributes( + IList attributeDataList, + Type memberCLRType, + out bool hasJsonInclude, + out string? jsonPropertyName, + out JsonIgnoreCondition? ignoreCondition, + out JsonNumberHandling? numberHandling, + out string? converterInstantiationLogic, + out int order, + out bool hasFactoryConverter, + out bool isExtensionData) + { + hasJsonInclude = false; + jsonPropertyName = null; + ignoreCondition = default; + numberHandling = default; + converterInstantiationLogic = null; + order = 0; + isExtensionData = false; bool foundDesignTimeCustomConverter = false; - string? converterInstantiationLogic = null; - int order = 0; + hasFactoryConverter = false; foreach (CustomAttributeData attributeData in attributeDataList) { @@ -890,7 +1243,11 @@ private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, if (!foundDesignTimeCustomConverter && attributeType.GetCompatibleBaseClass(JsonConverterAttributeFullName) != null) { foundDesignTimeCustomConverter = true; - converterInstantiationLogic = GetConverterInstantiationLogic(attributeData); + converterInstantiationLogic = GetConverterInstantiationLogic( + memberCLRType, + attributeData, + forType: false, + ref hasFactoryConverter); } else if (attributeType.Assembly.FullName == SystemTextJsonNamespace) { @@ -936,26 +1293,41 @@ private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, order = (int)ctorArgs[0].Value; } break; + case JsonExtensionDataAttributeFullName: + { + isExtensionData = true; + } + break; default: break; } } } + } - Type memberCLRType; - bool isReadOnly; - bool isPublic = false; - bool canUseGetter = false; - bool canUseSetter = false; - bool getterIsVirtual = false; - bool setterIsVirtual = false; + private static void ProcessMember( + MemberInfo memberInfo, + Type memberClrType, + bool hasJsonInclude, + out bool isReadOnly, + out bool isPublic, + out bool canUseGetter, + out bool canUseSetter, + out bool getterIsVirtual, + out bool setterIsVirtual, + out bool setterIsInitOnly) + { + isPublic = false; + canUseGetter = false; + canUseSetter = false; + getterIsVirtual = false; + setterIsVirtual = false; + setterIsInitOnly = false; switch (memberInfo) { case PropertyInfo propertyInfo: { - memberCLRType = propertyInfo.PropertyType; - MethodInfo? getMethod = propertyInfo.GetMethod; MethodInfo? setMethod = propertyInfo.SetMethod; @@ -977,15 +1349,16 @@ private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, if (setMethod != null) { isReadOnly = false; + setterIsInitOnly = setMethod.IsInitOnly(); if (setMethod.IsPublic) { isPublic = true; - canUseSetter = !setMethod.IsInitOnly(); + canUseSetter = true; } else if (setMethod.IsAssembly) { - canUseSetter = hasJsonInclude && !setMethod.IsInitOnly(); + canUseSetter = hasJsonInclude; } setterIsVirtual = setMethod.IsVirtual; @@ -998,7 +1371,6 @@ private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, break; case FieldInfo fieldInfo: { - memberCLRType = fieldInfo.FieldType; isPublic = fieldInfo.IsPublic; isReadOnly = fieldInfo.IsInitOnly; @@ -1012,36 +1384,15 @@ private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, default: throw new InvalidOperationException(); } - - string clrName = memberInfo.Name; - - return new PropertyGenerationSpec - { - ClrName = clrName, - IsProperty = memberInfo.MemberType == MemberTypes.Property, - IsPublic = isPublic, - IsVirtual = isVirtual, - JsonPropertyName = jsonPropertyName, - RuntimePropertyName = DetermineRuntimePropName(clrName, jsonPropertyName, _currentContextNamingPolicy), - IsReadOnly = isReadOnly, - CanUseGetter = canUseGetter, - CanUseSetter = canUseSetter, - GetterIsVirtual = getterIsVirtual, - SetterIsVirtual = setterIsVirtual, - DefaultIgnoreCondition = ignoreCondition, - NumberHandling = numberHandling, - Order = order, - HasJsonInclude = hasJsonInclude, - TypeGenerationSpec = GetOrAddTypeGenerationSpec(memberCLRType, generationMode), - DeclaringTypeRef = memberInfo.DeclaringType.GetCompilableName(), - ConverterInstantiationLogic = converterInstantiationLogic - }; } private static bool PropertyAccessorCanBeReferenced(MethodInfo? accessor) => accessor != null && (accessor.IsPublic || accessor.IsAssembly); - private string? GetConverterInstantiationLogic(CustomAttributeData attributeData) + private string? GetConverterInstantiationLogic( + Type type, CustomAttributeData attributeData, + bool forType, // whether for a type or a property + ref bool hasFactoryConverter) { if (attributeData.AttributeType.FullName != JsonConverterAttributeFullName) { @@ -1056,7 +1407,28 @@ private static bool PropertyAccessorCanBeReferenced(MethodInfo? accessor) return null; } - return $"new {converterType.GetCompilableName()}()"; + // Validated when creating the source generation spec. + Debug.Assert(_jsonConverterOfTType != null); + + if (converterType.GetCompatibleGenericBaseClass(_jsonConverterOfTType) != null) + { + return $"new {converterType.GetCompilableName()}()"; + } + else if (converterType.GetCompatibleBaseClass(JsonConverterFactoryFullName) != null) + { + hasFactoryConverter = true; + + if (forType) + { + return $"{Emitter.GetConverterFromFactoryMethodName}(typeof({type.GetCompilableName()}), new {converterType.GetCompilableName()}())"; + } + else + { + return $"{Emitter.JsonContextVarName}.{Emitter.GetConverterFromFactoryMethodName}<{type.GetCompilableName()}>(new {converterType.GetCompilableName()}())"; + } + } + + return null; } private static string DetermineRuntimePropName(string clrPropName, string? jsonPropName, JsonKnownNamingPolicy namingPolicy) @@ -1079,6 +1451,37 @@ private static string DetermineRuntimePropName(string clrPropName, string? jsonP return runtimePropName; } + private static string DeterminePropNameIdentifier(string runtimePropName) + { + const string PropName = "PropName_"; + + // Use a different prefix to avoid possible collisions with "PropName_" in + // the rare case there is a C# property in a hex format. + const string EncodedPropName = "EncodedPropName_"; + + if (SyntaxFacts.IsValidIdentifier(runtimePropName)) + { + return PropName + runtimePropName; + } + + // Encode the string to a byte[] and then convert to hexadecimal. + // To make the generated code more readable, we could use a different strategy in the future + // such as including the full class name + the CLR property name when there are duplicates, + // but that will create unnecessary JsonEncodedText properties. + byte[] utf8Json = Encoding.UTF8.GetBytes(runtimePropName); + + StringBuilder sb = new StringBuilder( + EncodedPropName, + capacity: EncodedPropName.Length + utf8Json.Length * 2); + + for (int i = 0; i < utf8Json.Length; i++) + { + sb.Append(utf8Json[i].ToString("X2")); // X2 is hex format + } + + return sb.ToString(); + } + private void PopulateNumberTypes() { Debug.Assert(_numberTypes != null); @@ -1098,21 +1501,45 @@ private void PopulateNumberTypes() private void PopulateKnownTypes() { PopulateNumberTypes(); + Debug.Assert(_knownTypes != null); Debug.Assert(_numberTypes != null); + Debug.Assert(_knownUnsupportedTypes != null); _knownTypes.UnionWith(_numberTypes); _knownTypes.Add(_booleanType); - _knownTypes.Add(_byteArrayType); _knownTypes.Add(_charType); _knownTypes.Add(_dateTimeType); - _knownTypes.Add(_dateTimeOffsetType); - _knownTypes.Add(_guidType); _knownTypes.Add(_objectType); _knownTypes.Add(_stringType); - _knownTypes.Add(_uriType); - _knownTypes.Add(_versionType); - _knownTypes.Add(_jsonElementType); + + AddTypeIfNotNull(_knownTypes, _byteArrayType); + AddTypeIfNotNull(_knownTypes, _timeSpanType); + AddTypeIfNotNull(_knownTypes, _dateTimeOffsetType); + AddTypeIfNotNull(_knownTypes, _guidType); + AddTypeIfNotNull(_knownTypes, _uriType); + AddTypeIfNotNull(_knownTypes, _versionType); + AddTypeIfNotNull(_knownTypes, _jsonArrayType); + AddTypeIfNotNull(_knownTypes, _jsonElementType); + AddTypeIfNotNull(_knownTypes, _jsonNodeType); + AddTypeIfNotNull(_knownTypes, _jsonObjectType); + AddTypeIfNotNull(_knownTypes, _jsonValueType); + + _knownUnsupportedTypes.Add(_typeType); + _knownUnsupportedTypes.Add(_serializationInfoType); + _knownUnsupportedTypes.Add(_intPtrType); + _knownUnsupportedTypes.Add(_uIntPtrType); + + AddTypeIfNotNull(_knownUnsupportedTypes, _dateOnlyType); + AddTypeIfNotNull(_knownUnsupportedTypes, _timeOnlyType); + + static void AddTypeIfNotNull(HashSet types, Type? type) + { + if (type != null) + { + types.Add(type); + } + } } } } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn3.11.cs similarity index 58% rename from src/libraries/System.Text.Json/gen/JsonSourceGenerator.cs rename to src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn3.11.cs index 51b548e57892ba..6fd0dedabb8ab8 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn3.11.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +//#define LAUNCH_DEBUGGER using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Reflection; @@ -9,6 +11,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; namespace System.Text.Json.SourceGeneration { @@ -24,7 +27,7 @@ public sealed partial class JsonSourceGenerator : ISourceGenerator /// public void Initialize(GeneratorInitializationContext context) { - context.RegisterForSyntaxNotifications(() => new SyntaxReceiver()); + context.RegisterForSyntaxNotifications(() => new SyntaxContextReceiver()); } /// @@ -39,33 +42,37 @@ public void Execute(GeneratorExecutionContext executionContext) Diagnostics.Debugger.Launch(); } #endif - SyntaxReceiver receiver = (SyntaxReceiver)executionContext.SyntaxReceiver; - List? contextClasses = receiver.ClassDeclarationSyntaxList; - if (contextClasses == null) + if (executionContext.SyntaxContextReceiver is not SyntaxContextReceiver receiver || receiver.ClassDeclarationSyntaxList == null) { + // nothing to do yet return; } - Parser parser = new(executionContext); + JsonSourceGenerationContext context = new JsonSourceGenerationContext(executionContext); + Parser parser = new(executionContext.Compilation, context); SourceGenerationSpec? spec = parser.GetGenerationSpec(receiver.ClassDeclarationSyntaxList); if (spec != null) { _rootTypes = spec.ContextGenerationSpecList[0].RootSerializableTypes; - Emitter emitter = new(executionContext, spec); + Emitter emitter = new(context, spec); emitter.Emit(); } } - private sealed class SyntaxReceiver : ISyntaxReceiver + private sealed class SyntaxContextReceiver : ISyntaxContextReceiver { public List? ClassDeclarationSyntaxList { get; private set; } - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + public void OnVisitSyntaxNode(GeneratorSyntaxContext context) { - if (syntaxNode is ClassDeclarationSyntax cds) + if (Parser.IsSyntaxTargetForGeneration(context.Node)) { - (ClassDeclarationSyntaxList ??= new List()).Add(cds); + ClassDeclarationSyntax classSyntax = Parser.GetSemanticTargetForGeneration(context); + if (classSyntax != null) + { + (ClassDeclarationSyntaxList ??= new List()).Add(classSyntax); + } } } } @@ -76,4 +83,24 @@ public void OnVisitSyntaxNode(SyntaxNode syntaxNode) public Dictionary? GetSerializableTypes() => _rootTypes?.ToDictionary(p => p.Type.FullName, p => p.Type); private List? _rootTypes; } + + internal readonly struct JsonSourceGenerationContext + { + private readonly GeneratorExecutionContext _context; + + public JsonSourceGenerationContext(GeneratorExecutionContext context) + { + _context = context; + } + + public void ReportDiagnostic(Diagnostic diagnostic) + { + _context.ReportDiagnostic(diagnostic); + } + + public void AddSource(string hintName, SourceText sourceText) + { + _context.AddSource(hintName, sourceText); + } + } } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs new file mode 100644 index 00000000000000..2f4fba241f097a --- /dev/null +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Roslyn4.0.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//#define LAUNCH_DEBUGGER +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text.Json.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +namespace System.Text.Json.SourceGeneration +{ + /// + /// Generates source code to optimize serialization and deserialization with JsonSerializer. + /// + [Generator] + public sealed partial class JsonSourceGenerator : IIncrementalGenerator + { + public void Initialize(IncrementalGeneratorInitializationContext context) + { + IncrementalValuesProvider classDeclarations = context.SyntaxProvider + .CreateSyntaxProvider(static (s, _) => Parser.IsSyntaxTargetForGeneration(s), static (s, _) => Parser.GetSemanticTargetForGeneration(s)) + .Where(static c => c is not null); + + IncrementalValueProvider<(Compilation, ImmutableArray)> compilationAndClasses = + context.CompilationProvider.Combine(classDeclarations.Collect()); + + context.RegisterSourceOutput(compilationAndClasses, (spc, source) => Execute(source.Item1, source.Item2, spc)); + } + + private void Execute(Compilation compilation, ImmutableArray contextClasses, SourceProductionContext sourceProductionContext) + { +#if LAUNCH_DEBUGGER + if (!Diagnostics.Debugger.IsAttached) + { + Diagnostics.Debugger.Launch(); + } +#endif + if (contextClasses.IsDefaultOrEmpty) + { + return; + } + + JsonSourceGenerationContext context = new JsonSourceGenerationContext(sourceProductionContext); + Parser parser = new(compilation, context); + SourceGenerationSpec? spec = parser.GetGenerationSpec(contextClasses); + if (spec != null) + { + _rootTypes = spec.ContextGenerationSpecList[0].RootSerializableTypes; + + Emitter emitter = new(context, spec); + emitter.Emit(); + } + } + + /// + /// Helper for unit tests. + /// + public Dictionary? GetSerializableTypes() => _rootTypes?.ToDictionary(p => p.Type.FullName, p => p.Type); + private List? _rootTypes; + } + + internal readonly struct JsonSourceGenerationContext + { + private readonly SourceProductionContext _context; + + public JsonSourceGenerationContext(SourceProductionContext context) + { + _context = context; + } + + public void ReportDiagnostic(Diagnostic diagnostic) + { + _context.ReportDiagnostic(diagnostic); + } + + public void AddSource(string hintName, SourceText sourceText) + { + _context.AddSource(hintName, sourceText); + } + } +} diff --git a/src/libraries/System.Text.Json/gen/PropertyGenerationSpec.cs b/src/libraries/System.Text.Json/gen/PropertyGenerationSpec.cs index 9d05fdf297cddc..c9c4cbd3ddc516 100644 --- a/src/libraries/System.Text.Json/gen/PropertyGenerationSpec.cs +++ b/src/libraries/System.Text.Json/gen/PropertyGenerationSpec.cs @@ -16,6 +16,9 @@ internal sealed class PropertyGenerationSpec /// public bool IsProperty { get; init; } + /// + /// If representing a property, returns true if either the getter or setter are public. + /// public bool IsPublic { get; init; } public bool IsVirtual { get; init; } @@ -32,11 +35,18 @@ internal sealed class PropertyGenerationSpec /// public string RuntimePropertyName { get; init; } + public string PropertyNameVarName { get; init; } + /// /// Whether the property has a set method. /// public bool IsReadOnly { get; init; } + /// + /// Whether the property has an init-only set method. + /// + public bool IsInitOnlySetter { get; init; } + /// /// Whether the property has a public or internal (only usable when JsonIncludeAttribute is specified) /// getter that can be referenced in generated source code. @@ -73,6 +83,11 @@ internal sealed class PropertyGenerationSpec /// public bool HasJsonInclude { get; init; } + /// + /// Whether the property has the JsonExtensionDataAttribute. + /// + public bool IsExtensionData { get; init; } + /// /// Generation specification for the property's type. /// @@ -87,5 +102,7 @@ internal sealed class PropertyGenerationSpec /// Source code to instantiate design-time specified custom converter. /// public string? ConverterInstantiationLogic { get; init; } + + public bool HasFactoryConverter { get; init; } } } diff --git a/src/libraries/System.Text.Json/gen/Reflection/FieldInfoWrapper.cs b/src/libraries/System.Text.Json/gen/Reflection/FieldInfoWrapper.cs index 66e00c0de20bb7..d06c264ab04563 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/FieldInfoWrapper.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/FieldInfoWrapper.cs @@ -100,5 +100,7 @@ public override void SetValue(object obj, object value, BindingFlags invokeAttr, { throw new NotImplementedException(); } + + public Location? Location => _field.Locations.Length > 0 ? _field.Locations[0] : null; } } diff --git a/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs b/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs index c088cc6d7e1cbf..e04adf3c21c308 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/MetadataLoadContextInternal.cs @@ -3,10 +3,12 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.DotnetRuntime.Extensions; namespace System.Text.Json.Reflection { @@ -19,11 +21,17 @@ public MetadataLoadContextInternal(Compilation compilation) _compilation = compilation; } - public Type? Resolve(Type type) => Resolve(type.FullName!); + public Compilation Compilation => _compilation; + + public Type? Resolve(Type type) + { + Debug.Assert(!type.IsArray, "Resolution logic only capable of handling named types."); + return Resolve(type.FullName!); + } public Type? Resolve(string fullyQualifiedMetadataName) { - INamedTypeSymbol? typeSymbol = _compilation.GetTypeByMetadataName(fullyQualifiedMetadataName); + INamedTypeSymbol? typeSymbol = _compilation.GetBestTypeByMetadataName(fullyQualifiedMetadataName); return typeSymbol.AsType(this); } diff --git a/src/libraries/System.Text.Json/gen/Reflection/PropertyInfoWrapper.cs b/src/libraries/System.Text.Json/gen/Reflection/PropertyInfoWrapper.cs index bfb593f992fbd0..d7eea3323416ba 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/PropertyInfoWrapper.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/PropertyInfoWrapper.cs @@ -92,5 +92,7 @@ public override void SetValue(object obj, object value, BindingFlags invokeAttr, { throw new NotSupportedException(); } + + public Location? Location => _property.Locations.Length > 0 ? _property.Locations[0] : null; } } diff --git a/src/libraries/System.Text.Json/gen/Reflection/ReflectionExtensions.cs b/src/libraries/System.Text.Json/gen/Reflection/ReflectionExtensions.cs index 101f3e48fbfb7e..d0bc8e59b147c2 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/ReflectionExtensions.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/ReflectionExtensions.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Linq; using System.Reflection; +using Microsoft.CodeAnalysis; namespace System.Text.Json.Reflection { @@ -45,5 +46,23 @@ private static bool HasJsonConstructorAttribute(ConstructorInfo constructorInfo) return false; } + + public static Location? GetDiagnosticLocation(this Type type) + { + Debug.Assert(type is TypeWrapper); + return ((TypeWrapper)type).Location; + } + + public static Location? GetDiagnosticLocation(this PropertyInfo propertyInfo) + { + Debug.Assert(propertyInfo is PropertyInfoWrapper); + return ((PropertyInfoWrapper)propertyInfo).Location; + } + + public static Location? GetDiagnosticLocation(this FieldInfo fieldInfo) + { + Debug.Assert(fieldInfo is FieldInfoWrapper); + return ((FieldInfoWrapper)fieldInfo).Location; + } } } diff --git a/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs b/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs index 4e2479784de13e..37c7217a919cc7 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/RoslynExtensions.cs @@ -37,7 +37,7 @@ public static MethodAttributes GetMethodAttributes(this IMethodSymbol methodSymb if (methodSymbol.IsAbstract) { - attributes |= MethodAttributes.Abstract; + attributes |= MethodAttributes.Abstract | MethodAttributes.Virtual; } if (methodSymbol.IsStatic) @@ -67,3 +67,4 @@ public static MethodAttributes GetMethodAttributes(this IMethodSymbol methodSymb } } } + diff --git a/src/libraries/System.Text.Json/gen/Reflection/TypeExtensions.cs b/src/libraries/System.Text.Json/gen/Reflection/TypeExtensions.cs index ba20339565cbf9..b5b02c4f7d6556 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/TypeExtensions.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/TypeExtensions.cs @@ -109,6 +109,30 @@ public static bool IsNullableValueType(this Type type, out Type? underlyingType) return false; } + public static bool CanContainNullableReferenceTypeAnnotations(this Type type) + { + // Returns true iff Type instance has potential for receiving nullable reference type annotations, + // i.e. the type is a reference type or contains generic parameters that are reference types. + + if (!type.IsValueType) + { + return true; + } + + if (type.IsGenericType) + { + foreach (Type genericParam in type.GetGenericArguments()) + { + if (CanContainNullableReferenceTypeAnnotations(genericParam)) + { + return true; + } + } + } + + return false; + } + public static bool IsObjectType(this Type type) => type.FullName == "System.Object"; public static bool IsStringType(this Type type) => type.FullName == "System.String"; diff --git a/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs b/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs index 50d76bf0e2878e..c084c6f614823c 100644 --- a/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs +++ b/src/libraries/System.Text.Json/gen/Reflection/TypeWrapper.cs @@ -281,6 +281,11 @@ public override Type GetElementType() return _elementType; } + public override Type MakeArrayType() + { + return _metadataLoadContext.Compilation.CreateArrayTypeSymbol(_typeSymbol).AsType(_metadataLoadContext); + } + public override EventInfo GetEvent(string name, BindingFlags bindingAttr) { throw new NotImplementedException(); @@ -311,7 +316,9 @@ public override FieldInfo[] GetFields(BindingFlags bindingAttr) // we want a static field and this is not static (BindingFlags.Static & bindingAttr) != 0 && !fieldSymbol.IsStatic || // we want an instance field and this is static or a constant - (BindingFlags.Instance & bindingAttr) != 0 && (fieldSymbol.IsStatic || fieldSymbol.IsConst)) + (BindingFlags.Instance & bindingAttr) != 0 && (fieldSymbol.IsStatic || fieldSymbol.IsConst) || + // symbol represents an explicitly named tuple element + fieldSymbol.IsExplicitlyNamedTupleElement) { continue; } @@ -389,12 +396,6 @@ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { if (item is IPropertySymbol propertySymbol) { - // Skip auto-generated properties on records. - if (_typeSymbol.IsRecord && propertySymbol.DeclaringSyntaxReferences.Length == 0) - { - continue; - } - // Skip if: if ( // we want a static property and this is not static @@ -593,5 +594,7 @@ public override bool Equals(Type o) } return base.Equals(o); } + + public Location? Location => _typeSymbol.Locations.Length > 0 ? _typeSymbol.Locations[0] : null; } } diff --git a/src/libraries/System.Text.Json/gen/Resources/Strings.resx b/src/libraries/System.Text.Json/gen/Resources/Strings.resx index 5e60f5e377c5d6..1074f0eb468179 100644 --- a/src/libraries/System.Text.Json/gen/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/gen/Resources/Strings.resx @@ -141,4 +141,28 @@ Type has multiple constructors annotated with JsonConstructorAttribute. - \ No newline at end of file + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + Type has multiple members annotated with JsonExtensionDataAttribute. + + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + Data extension property type invalid. + + + Deserialization of init-only properties is currently not supported in source generation mode. + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf index 4bde155b650b24..3b613f37f21660 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf @@ -12,6 +12,16 @@ Odvozené typy JsonSerializerContext a všechny obsahující typy musí být částečné. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Existuje několik typů s názvem {0}. Zdroj se vygeneroval pro první zjištěný typ. Tuto kolizi vyřešíte pomocí JsonSerializableAttribute.TypeInfoPropertyName. @@ -22,6 +32,26 @@ Duplicitní název typu + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Typ {0} má více konstruktorů anotovaných s JsonConstructorAttribute. @@ -32,6 +62,16 @@ Typ obsahuje více konstruktorů anotovaných s JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Nevygenerovala se metadata serializace pro typ {0}. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf index 093d8a6cdb4715..80ee5a4c3927c9 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf @@ -12,6 +12,16 @@ Abgeleitete JsonSerializerContext-Typen und alle enthaltenden Typen müssen partiell sein. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Es sind mehrere Typen namens "{0}" vorhanden. Die Quelle wurde für den ersten festgestellten Typ generiert. Verwenden Sie "JsonSerializableAttribute.TypeInfoPropertyName", um diesen Konflikt zu beheben. @@ -22,6 +32,26 @@ Doppelter Typname + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Typ "{0}" weist mehrere Konstruktoren mit dem Kommentar "JsonConstructorAttribute" auf. @@ -32,6 +62,16 @@ Der Typ weist mehrere Konstruktoren mit dem Kommentar JsonConstructorAttribute auf. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Die Serialisierungsmetadaten für den Typ "{0}" wurden nicht generiert. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf index ed12d993f5c5a6..383c9b6e1cd3ce 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf @@ -12,6 +12,16 @@ Los tipos derivados "JsonSerializerContext" y todos los tipos que contienen deben ser parciales. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Hay varios tipos denominados {0}. El origen se generó para el primero detectado. Use "JsonSerializableAttribute.TypeInfoPropertyName" para resolver esta colisión. @@ -22,6 +32,26 @@ Nombre de tipo duplicado. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. El tipo '{0}' tiene varios constructores anotados con 'JsonConstructorAttribute'. @@ -32,6 +62,16 @@ El tipo tiene varios constructores anotados con JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. No generó metadatos de serialización para el tipo '{0}". diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf index ddea910bd05ba9..abf9fecd62cf1e 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf @@ -12,6 +12,16 @@ Les types dérivés 'JsonSerializerContext' et tous les types conteneurs doivent être partiels. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Plusieurs types nommés {0}. La source a été générée pour la première détection détectée. Utilisez « JsonSerializableAttribute.TypeInfoPropertyName » pour résoudre cette collision. @@ -22,6 +32,26 @@ Nom de type dupliqué. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Le type' {0} 'a plusieurs constructeurs annotés avec’JsonConstructorAttribute'. @@ -32,6 +62,16 @@ Le type a plusieurs constructeurs annotés avec JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Les métadonnées de sérialisation pour le type « {0} » n’ont pas été générées. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf index d26aba1c84f9b9..9edb25fc978211 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf @@ -12,6 +12,16 @@ I tipi derivati 'JsonSerializerContext' e tutti i tipi contenenti devono essere parziali. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Sono presenti più tipi denominati {0}. L'origine è stata generata per il primo tipo rilevato. Per risolvere questa collisione, usare 'JsonSerializableAttribute.TypeInfoPropertyName'. @@ -22,6 +32,26 @@ Nome di tipo duplicato. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Il tipo '{0}' contiene più costruttori che presentano l'annotazione 'JsonConstructorAttribute'. @@ -32,6 +62,16 @@ Il tipo contiene più costruttori che presentano l'annotazione JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Non sono stati generati metadati di serializzazione per il tipo '{0}'. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf index 50270d6c4d401d..b3312d606a2dbd 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf @@ -12,6 +12,16 @@ 派生した 'JsonSerializerContext' 型と含まれているすべての型は部分的である必要があります。 + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. {0} と名前が付けられた種類が複数あります。最初に検出されたものに対してソースが生成されました。この問題を解決するには、'JsonSerializableAttribute.TypeInfoPropertyName' を使用します。 @@ -22,6 +32,26 @@ 重複した種類名。 + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. 型 '{0}' には、'JsonConstructorAttribute' で注釈が付けられた複数のコンストラクターがあります。 @@ -32,6 +62,16 @@ 型には、JsonConstructorAttribute で注釈が付けられた複数のコンストラクターがあります。 + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. '{0}'型 のシリアル化メタデータを生成ませんでした。 diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf index a1fd856af18575..1214ae9ffa70c2 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf @@ -12,6 +12,16 @@ 파생된 'JsonSerializerContext' 형식과 포함하는 모든 형식은 부분이어야 합니다. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. 이름이 {0}인 형식이 여러 개 있습니다. 처음 검색한 원본에 대해 원본이 생성되었습니다. 이 충돌을 해결하려면 'JsonSerializableAttribute.TypeInfoPropertyName'을 사용하세요. @@ -22,6 +32,26 @@ 중복된 형식 이름입니다. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. '{0}' 형식에 'JsonConstructorAttribute'로 주석이 추가된 여러 생성자가 있습니다. @@ -32,6 +62,16 @@ 해당 형식에 JsonConstructorAttribute로 주석이 추가된 여러 생성자가 있습니다. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. '{0}' 형식에 대한 직렬화 메타데이터가 생성되지 않았습니다. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf index e04db80de054be..257006c2b352e0 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf @@ -12,6 +12,16 @@ Pochodne typy "JsonSerializerContext" i wszystkich zawierające typy muszą być częściowe. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Istnieje wiele typów o nazwie {0}. Wygenerowano źródło dla pierwszego wykrytego elementu. Aby rozwiązać tę kolizję, użyj „JsonSerializableAttribute. TypeInfoPropertyName”. @@ -22,6 +32,26 @@ Zduplikowana nazwa typu. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Typ "{0}" ma wiele konstruktorów z adnotacją "JsonConstructorAttribute". @@ -32,6 +62,16 @@ Typ ma wiele konstruktorów z adnotacją JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Nie wygenerowano metadanych serializacji dla typu „{0}”. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf index bd08c889d012fd..11492c23762969 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf @@ -12,6 +12,16 @@ Os tipos derivados de 'JsonSerializerContext' e todos os tipos contidos devem ser parciais. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Existem vários tipos chamados {0}. A fonte foi gerada para o primeiro detectado. Use 'JsonSerializableAttribute.TypeInfoPropertyName' para resolver esta colisão. @@ -22,6 +32,26 @@ Nome de tipo duplicado. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. O tipo '{0}' tem vários construtores anotados com 'JsonConstructorAttribute'. @@ -32,6 +62,16 @@ O tipo tem vários construtores anotados com JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Não gerou metadados de serialização para o tipo '{0}'. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf index fdd7824a1f54eb..f1bb2a252c0438 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf @@ -12,6 +12,16 @@ Производные типы "JsonSerializerContext" и все содержащие типы должны быть частичными. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. Существует несколько типов с именем {0}. Исходный код сформирован для первого обнаруженного типа. Используйте JsonSerializableAttribute.TypeInfoPropertyName для устранения этого конфликта. @@ -22,6 +32,26 @@ Дублирующееся имя типа. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Тип "{0}" имеет несколько конструкторов, аннотированных с использованием JsonConstructorAttribute. @@ -32,6 +62,16 @@ Тип имеет несколько конструкторов, аннотированных с использованием JsonConstructorAttribute. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. Метаданные сериализации для типа "{0}" не сформированы. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf index 7844892dcbb498..3d5e138aebe4cb 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf @@ -12,6 +12,16 @@ Türetilmiş 'JsonSerializerContext' türleri ve bunları içeren tüm türler kısmi olmalıdır. + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. {0} adını taşıyan birden çok tür var. Kaynak, algılanan ilk tür için oluşturuldu. Bu çarpışmayı çözmek için 'JsonSerializableAttribute.TypeInfoPropertyName' özelliğini kullanın. @@ -22,6 +32,26 @@ Yinelenen tür adı. + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. '{0}' türünün 'JsonConstructorAttribute' ile açıklanan birden çok oluşturucusu var. @@ -32,6 +62,16 @@ Türün JsonConstructorAttribute ile açıklanan birden çok oluşturucusu var. + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. '{0}' türü için serileştirme meta verileri oluşturulmadı. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf index 10e68c87ede68d..a934f5c4d315f1 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -12,6 +12,16 @@ 派生的 “JsonSerializerContext” 类型以及所有包含类型必须是部分。 + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. 有多个名为 {0} 的类型。已为第一个检测到类型的生成源。请使用 'JsonSerializableAttribute.TypeInfoPropertyName' 以解决此冲突。 @@ -22,6 +32,26 @@ 重复的类型名称。 + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. 类型“{0}”具有用 “JsonConstructorAttribute” 批注的多个构造函数。 @@ -32,6 +62,16 @@ 类型具有用 JsonConstructorAttribute 批注的多个构造函数。 + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. 未生成类型 '{0}' 的序列化元数据。 diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf index 2b5a59991a12a7..4e236ab87e0030 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -12,6 +12,16 @@ 衍生的 'JsonSerializerContext' 類型和所有包含類型必須是部份。 + + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. + + + + Data extension property type invalid. + Data extension property type invalid. + + There are multiple types named {0}. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision. 有多個名為 {0} 的類型。已為偵測到的第一個項目產生來源。請使用 'JsonSerializableAttribute.TypeInfoPropertyName' 解決此衝突。 @@ -22,6 +32,26 @@ 重複類型名稱。 + + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator. + + + + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode. + + + + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + The type '{0}' defines init-only properties, deserialization of which is currently not supported in source generation mode. + + + + Deserialization of init-only properties is currently not supported in source generation mode. + Deserialization of init-only properties is currently not supported in source generation mode. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. 類型 '{0}' 包含多個以 'JsonConstructorAttribute' 註解的建構函式。 @@ -32,6 +62,16 @@ 類型包含多個以 JsonConstructorAttribute 註解的建構函式。 + + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + Type '{0}' has multiple members annotated with 'JsonExtensionDataAttribute'. + + + + Type has multiple members annotated with JsonExtensionDataAttribute. + Type has multiple members annotated with JsonExtensionDataAttribute. + + Did not generate serialization metadata for type '{0}'. 未產生類型 '{0}' 的序列化中繼資料。 diff --git a/src/libraries/System.Text.Json/gen/SourceGenerationSpec.cs b/src/libraries/System.Text.Json/gen/SourceGenerationSpec.cs index 0019dc524955aa..09865cd403c5fa 100644 --- a/src/libraries/System.Text.Json/gen/SourceGenerationSpec.cs +++ b/src/libraries/System.Text.Json/gen/SourceGenerationSpec.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Text; +using System.Text.Json.Reflection; +using Microsoft.CodeAnalysis; namespace System.Text.Json.SourceGeneration { @@ -11,6 +13,9 @@ internal sealed class SourceGenerationSpec { public List ContextGenerationSpecList { get; init; } +#if DEBUG + public MetadataLoadContextInternal MetadataLoadContext { get; init; } +#endif public Type BooleanType { get; init; } public Type ByteArrayType { get; init; } public Type CharType { get; init; } diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn3.11.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn3.11.csproj new file mode 100644 index 00000000000000..5168388eb18916 --- /dev/null +++ b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn3.11.csproj @@ -0,0 +1,14 @@ + + + + 3.11 + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion_3_11) + + + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.0.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.0.csproj new file mode 100644 index 00000000000000..b088862764623d --- /dev/null +++ b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.Roslyn4.0.csproj @@ -0,0 +1,16 @@ + + + + true + 4.0 + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion) + $(DefineConstants);ROSLYN4_0_OR_GREATER + + + + + + + + + diff --git a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.csproj b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.targets similarity index 87% rename from src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.csproj rename to src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.targets index de7b135a86f188..97d78152396485 100644 --- a/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.csproj +++ b/src/libraries/System.Text.Json/gen/System.Text.Json.SourceGeneration.targets @@ -1,13 +1,16 @@ - + netstandard2.0 + $(MSBuildThisFileName) + $(MSBuildThisFileName) + SR + FxResources.$(RootNamespace).$(StringResourcesClassName) false enable CS1574 false true - true cs @@ -17,10 +20,8 @@ - + - - @@ -37,11 +38,12 @@ + - + diff --git a/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs b/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs index 4c2eb61e27d669..e2a391990c8a06 100644 --- a/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs +++ b/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Text.Json.Reflection; using System.Text.Json.Serialization; +using Microsoft.CodeAnalysis; namespace System.Text.Json.SourceGeneration { @@ -18,6 +19,11 @@ internal class TypeGenerationSpec /// public string TypeRef { get; private set; } + /// + /// If specified as a root type via JsonSerializableAttribute, specifies the location of the attribute application. + /// + public Location? AttributeLocation { get; set; } + /// /// The name of the public JsonTypeInfo property for this type on the generated context class. /// For example, if the context class is named MyJsonContext, and the value of this property is JsonMessage; @@ -58,16 +64,24 @@ internal class TypeGenerationSpec public TypeGenerationSpec? NullableUnderlyingTypeMetadata { get; private set; } + /// + /// Supports deserialization of extension data dictionaries typed as I[ReadOnly]Dictionary. + /// Specifies a concrete type to instanciate, which would be Dictionary. + /// + public string? RuntimeTypeRef { get; private set; } + + public TypeGenerationSpec? ExtensionDataPropertyTypeSpec { get; private set; } + public string? ConverterInstantiationLogic { get; private set; } - public string FastPathSerializeMethodName - { - get - { - Debug.Assert(GenerateSerializationLogic); - return $"{TypeInfoPropertyName}Serialize"; - } - } + // Only generate certain helper methods if necessary. + public bool HasPropertyFactoryConverters { get; private set; } + public bool HasTypeFactoryConverter { get; private set; } + + // The spec is derived from cached `System.Type` instances, which are generally annotation-agnostic. + // Hence we can only record the potential for nullable annotations being possible for the runtime type. + // TODO: consider deriving the generation spec from the Roslyn symbols directly. + public bool CanContainNullableReferenceAnnotations { get; private set; } public string? ImmutableCollectionBuilderName { @@ -105,9 +119,14 @@ public void Initialize( TypeGenerationSpec? collectionValueTypeMetadata, ObjectConstructionStrategy constructionStrategy, TypeGenerationSpec? nullableUnderlyingTypeMetadata, + string? runtimeTypeRef, + TypeGenerationSpec? extensionDataPropertyTypeSpec, string? converterInstantiationLogic, bool implementsIJsonOnSerialized, - bool implementsIJsonOnSerializing) + bool implementsIJsonOnSerializing, + bool hasTypeFactoryConverter, + bool canContainNullableReferenceAnnotations, + bool hasPropertyFactoryConverters) { GenerationMode = generationMode; TypeRef = type.GetCompilableName(); @@ -124,9 +143,14 @@ public void Initialize( CollectionValueTypeMetadata = collectionValueTypeMetadata; ConstructionStrategy = constructionStrategy; NullableUnderlyingTypeMetadata = nullableUnderlyingTypeMetadata; + RuntimeTypeRef = runtimeTypeRef; + ExtensionDataPropertyTypeSpec = extensionDataPropertyTypeSpec; ConverterInstantiationLogic = converterInstantiationLogic; ImplementsIJsonOnSerialized = implementsIJsonOnSerialized; ImplementsIJsonOnSerializing = implementsIJsonOnSerializing; + CanContainNullableReferenceAnnotations = canContainNullableReferenceAnnotations; + HasTypeFactoryConverter = hasTypeFactoryConverter; + HasPropertyFactoryConverters = hasPropertyFactoryConverters; } public bool TryFilterSerializableProps( @@ -140,7 +164,6 @@ public bool TryFilterSerializableProps( for (int i = 0; i < PropertyGenSpecList.Count; i++) { PropertyGenerationSpec propGenSpec = PropertyGenSpecList[i]; - bool hasJsonInclude = propGenSpec.HasJsonInclude; JsonIgnoreCondition? ignoreCondition = propGenSpec.DefaultIgnoreCondition; if (ignoreCondition == JsonIgnoreCondition.WhenWritingNull && !propGenSpec.TypeGenerationSpec.CanBeNull) @@ -148,17 +171,21 @@ public bool TryFilterSerializableProps( goto ReturnFalse; } - if (!propGenSpec.IsPublic) + // In case of JsonInclude fail if either: + // 1. the getter is not accessible by the source generator or + // 2. neither getter or setter methods are public. + if (propGenSpec.HasJsonInclude && (!propGenSpec.CanUseGetter || !propGenSpec.IsPublic)) { - if (hasJsonInclude) - { - goto ReturnFalse; - } + goto ReturnFalse; + } + // Discard any getters not accessible by the source generator. + if (!propGenSpec.CanUseGetter) + { continue; } - if (!propGenSpec.IsProperty && !hasJsonInclude && !options.IncludeFields) + if (!propGenSpec.IsProperty && !propGenSpec.HasJsonInclude && !options.IncludeFields) { continue; } @@ -203,7 +230,7 @@ public bool TryFilterSerializableProps( castingRequiredForProps = PropertyGenSpecList.Count > serializableProperties.Count; return true; -ReturnFalse: + ReturnFalse: serializableProperties = null; castingRequiredForProps = false; return false; @@ -213,11 +240,17 @@ private bool FastPathIsSupported() { if (ClassType == ClassType.Object) { + if (ExtensionDataPropertyTypeSpec != null) + { + return false; + } + foreach (PropertyGenerationSpec property in PropertyGenSpecList) { if (property.TypeGenerationSpec.Type.IsObjectType() || property.NumberHandling == JsonNumberHandling.AllowNamedFloatingPointLiterals || - property.NumberHandling == JsonNumberHandling.WriteAsString) + property.NumberHandling == JsonNumberHandling.WriteAsString || + property.ConverterInstantiationLogic is not null) { return false; } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.Typeforwards.netcoreapp.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.Typeforwards.netcoreapp.cs new file mode 100644 index 00000000000000..81030616268c3d --- /dev/null +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.Typeforwards.netcoreapp.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// The compiler emits a reference to the internal copy of this type in our non-NETCoreApp assembly +// so we must include a forward to be compatible with libraries compiled against non-NETCoreApp System.Text.Json +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))] diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index d4b05c6ea9f677..77d6c85b4376fe 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -798,7 +798,7 @@ public abstract partial class JsonConverter internal JsonConverter() { } public abstract bool CanConvert(System.Type typeToConvert); } - [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Interface | System.AttributeTargets.Enum | System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple=false)] + [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Interface | System.AttributeTargets.Enum | System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple = false)] public partial class JsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute { protected JsonConverterAttribute() { } @@ -890,7 +890,8 @@ public JsonSerializableAttribute(System.Type type) { } } public abstract partial class JsonSerializerContext { - protected JsonSerializerContext(System.Text.Json.JsonSerializerOptions? instanceOptions, System.Text.Json.JsonSerializerOptions? defaultOptions) { } + protected JsonSerializerContext(System.Text.Json.JsonSerializerOptions? options) { } + protected abstract System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; } public System.Text.Json.JsonSerializerOptions Options { get { throw null; } } public abstract System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(System.Type type); } @@ -901,11 +902,10 @@ public JsonSourceGenerationOptionsAttribute() { } public System.Text.Json.Serialization.JsonIgnoreCondition DefaultIgnoreCondition { get { throw null; } set { } } public bool IgnoreReadOnlyFields { get { throw null; } set { } } public bool IgnoreReadOnlyProperties { get { throw null; } set { } } - public bool IgnoreRuntimeCustomConverters { get { throw null; } set { } } public bool IncludeFields { get { throw null; } set { } } public System.Text.Json.Serialization.JsonKnownNamingPolicy PropertyNamingPolicy { get { throw null; } set { } } public bool WriteIndented { get { throw null; } set { } } - public JsonSourceGenerationMode GenerationMode { get { throw null; } set { } } + public System.Text.Json.Serialization.JsonSourceGenerationMode GenerationMode { get { throw null; } set { } } } [System.FlagsAttribute] public enum JsonSourceGenerationMode @@ -948,6 +948,15 @@ protected ReferenceResolver() { } } namespace System.Text.Json.Serialization.Metadata { + public sealed partial class JsonCollectionInfoValues + { + public JsonCollectionInfoValues() { } + public System.Func? ObjectCreator { get { throw null; } init { } } + public System.Text.Json.Serialization.Metadata.JsonTypeInfo ElementInfo { get { throw null; } init { } } + public System.Text.Json.Serialization.Metadata.JsonTypeInfo? KeyInfo { get { throw null; } init { } } + public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } init { } } + public System.Action? SerializeHandler { get { throw null; } init { } } + } public static partial class JsonMetadataServices { public static System.Text.Json.Serialization.JsonConverter BooleanConverter { get { throw null; } } @@ -962,7 +971,11 @@ public static partial class JsonMetadataServices public static System.Text.Json.Serialization.JsonConverter Int16Converter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter Int32Converter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter Int64Converter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonArrayConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter JsonElementConverter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonNodeConverter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonObjectConverter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonValueConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter ObjectConverter { get { throw null; } } [System.CLSCompliantAttribute(false)] public static System.Text.Json.Serialization.JsonConverter SByteConverter { get { throw null; } } @@ -977,42 +990,46 @@ public static partial class JsonMetadataServices public static System.Text.Json.Serialization.JsonConverter UInt64Converter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter UriConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter VersionConverter { get { throw null; } } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateArrayInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentQueue { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentStackInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentStack { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo keyInfo, System.Text.Json.Serialization.Metadata.JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.Dictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateICollectionInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.ICollection { throw null; } - public static JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo stringInfo, JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.IDictionary { throw null; } - public static JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IDictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.IEnumerable { throw null; } - public static JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IEnumerable { throw null; } - public static JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.IList { throw null; } - public static JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IList { throw null; } - public static JsonTypeInfo CreateImmutableDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc, System.Func>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateImmutableEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc, System.Func, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable { throw null; } - public static JsonTypeInfo CreateIReadOnlyDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateISetInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.ISet { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateListInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.List { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateArrayInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentQueue { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentStack { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Dictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateICollectionInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.ICollection { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IDictionary { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IDictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IList { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IList { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateImmutableDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Func>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateImmutableEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Func, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIReadOnlyDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateISetInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.ISet { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateListInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.List { throw null; } public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateObjectInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonObjectInfoValues objectInfo) where T : notnull { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo(System.Text.Json.JsonSerializerOptions options, bool isProperty, bool isPublic, bool isVirtual, System.Type declaringType, System.Text.Json.Serialization.Metadata.JsonTypeInfo propertyTypeInfo, System.Text.Json.Serialization.JsonConverter? converter, System.Func? getter, System.Action? setter, System.Text.Json.Serialization.JsonIgnoreCondition? ignoreCondition, bool hasJsonInclude, System.Text.Json.Serialization.JsonNumberHandling? numberHandling, string propertyName, string? jsonPropertyName) { throw null; } - public static JsonTypeInfo CreateQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.Queue { throw null; } - public static JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.Stack { throw null; } - public static JsonTypeInfo CreateStackOrQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues propertyInfo) { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Queue { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Stack { throw null; } public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateValueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.JsonConverter converter) { throw null; } + public static System.Text.Json.Serialization.JsonConverter GetUnsupportedTypeConverter() { throw null; } public static System.Text.Json.Serialization.JsonConverter GetEnumConverter(System.Text.Json.JsonSerializerOptions options) where T : struct { throw null; } public static System.Text.Json.Serialization.JsonConverter GetNullableConverter(System.Text.Json.Serialization.Metadata.JsonTypeInfo underlyingTypeInfo) where T : struct { throw null; } } public sealed partial class JsonObjectInfoValues { - public System.Func? ConstructorParameterMetadataInitializer { get; init; } - public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get; init; } - public System.Func? ObjectCreator { get; init; } - public System.Func? ObjectWithParameterizedConstructorCreator { get; init; } - public System.Func? PropertyMetadataInitializer { get; init; } - public System.Action? SerializeHandler { get; init; } + public JsonObjectInfoValues() { } + public System.Func? ConstructorParameterMetadataInitializer { get { throw null; } init { } } + public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } init { } } + public System.Func? ObjectCreator { get { throw null; } init { } } + public System.Func? ObjectWithParameterizedConstructorCreator { get { throw null; } init { } } + public System.Func? PropertyMetadataInitializer { get { throw null; } init { } } + public System.Action? SerializeHandler { get { throw null; } init { } } } - public sealed class JsonParameterInfoValues + public sealed partial class JsonParameterInfoValues { + public JsonParameterInfoValues() { } public object? DefaultValue { get { throw null; } init { } } public bool HasDefaultValue { get { throw null; } init { } } public string Name { get { throw null; } init { } } @@ -1023,6 +1040,24 @@ public abstract partial class JsonPropertyInfo { internal JsonPropertyInfo() { } } + public sealed partial class JsonPropertyInfoValues + { + public JsonPropertyInfoValues() { } + public System.Text.Json.Serialization.JsonConverter? Converter { get { throw null; } init { } } + public System.Type DeclaringType { get { throw null; } init { } } + public System.Func? Getter { get { throw null; } init { } } + public System.Text.Json.Serialization.JsonIgnoreCondition? IgnoreCondition { get { throw null; } init { } } + public bool HasJsonInclude { get { throw null; } init { } } + public bool IsExtensionData { get { throw null; } init { } } + public bool IsProperty { get { throw null; } init { } } + public bool IsPublic { get { throw null; } init { } } + public bool IsVirtual { get { throw null; } init { } } + public string? JsonPropertyName { get { throw null; } init { } } + public System.Text.Json.Serialization.JsonNumberHandling? NumberHandling { get { throw null; } init { } } + public string PropertyName { get { throw null; } init { } } + public System.Text.Json.Serialization.Metadata.JsonTypeInfo PropertyTypeInfo { get { throw null; } init { } } + public System.Action? Setter { get { throw null; } init { } } + } public partial class JsonTypeInfo { internal JsonTypeInfo() { } @@ -1030,6 +1065,6 @@ internal JsonTypeInfo() { } public abstract partial class JsonTypeInfo : System.Text.Json.Serialization.Metadata.JsonTypeInfo { internal JsonTypeInfo() { } - public System.Action? Serialize { get { throw null; } } + public System.Action? SerializeHandler { get { throw null; } } } } diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj index 6ef8f2ad1f044c..aa194d3641829b 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj @@ -7,6 +7,11 @@ + + + + + diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 7fc1bd8096676a..6485157058f537 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -349,7 +349,7 @@ The JSON property name for '{0}.{1}' cannot be null. - The data extension property '{0}.{1}' does not match the required signature of 'IDictionary<string, JsonElement>', 'IDictionary<string, object>' or 'JsonObject'. + The data extension property '{0}.{1}' is invalid. It must implement 'IDictionary<string, JsonElement>' or 'IDictionary<string, object>', or be 'JsonObject'. The type '{0}' cannot have more than one member that has the attribute '{1}'. @@ -492,7 +492,7 @@ The type '{0}' is invalid for serialization or deserialization because it is a pointer type, is a ref struct, or contains generic parameters that have not been replaced by specific types. - Serialization and deserialization of '{0}' instances are not supported and should be avoided since they can lead to security issues. + Serialization and deserialization of '{0}' instances are not supported. The non-public property '{0}' on type '{1}' is annotated with 'JsonIncludeAttribute' which is invalid. diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.Typeforwards.netcoreapp.cs b/src/libraries/System.Text.Json/src/System.Text.Json.Typeforwards.netcoreapp.cs new file mode 100644 index 00000000000000..81030616268c3d --- /dev/null +++ b/src/libraries/System.Text.Json/src/System.Text.Json.Typeforwards.netcoreapp.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// The compiler emits a reference to the internal copy of this type in our non-NETCoreApp assembly +// so we must include a forward to be compatible with libraries compiled against non-NETCoreApp System.Text.Json +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))] diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 3a363de469a909..9fa6bfb8a500ba 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -5,10 +5,11 @@ - + CS8969 enable true true + 2 Provides high-performance and low-allocating types that serialize objects to JavaScript Object Notation (JSON) text and deserialize JSON text to objects, with UTF-8 support built-in. Also provides types to read and write JSON text encoded as UTF-8, and to create an in-memory document object model (DOM), that is read-only, for random access of the JSON elements within a structured view of the data. Commonly Used Types: @@ -117,13 +118,6 @@ System.Text.Json.Utf8JsonReader - - - - - - - @@ -179,8 +173,6 @@ System.Text.Json.Utf8JsonReader - - @@ -201,6 +193,8 @@ System.Text.Json.Utf8JsonReader + + @@ -230,14 +224,23 @@ System.Text.Json.Utf8JsonReader + + + + + + - + + + + @@ -308,6 +311,7 @@ System.Text.Json.Utf8JsonReader + @@ -349,6 +353,8 @@ System.Text.Json.Utf8JsonReader - + + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs index 2cb13212373b4d..6b075966bb7363 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Document/JsonDocument.cs @@ -54,7 +54,7 @@ private JsonDocument( _utf8Json = utf8Json; _parsedData = parsedData; - if (_extraRentedArrayPoolBytes != null) + if (extraRentedArrayPoolBytes != null) { _hasExtraRentedArrayPoolBytes = true; _extraRentedArrayPoolBytes = extraRentedArrayPoolBytes; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs index b539d6d82bb74a..4c4b4e076a92e0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs @@ -372,7 +372,7 @@ internal static void Unescape(ReadOnlySpan source, Span destination, else if (currentByte == 'u') { // The source is known to be valid JSON, and hence if we see a \u, it is guaranteed to have 4 hex digits following it - // Otherwise, the Utf8JsonReader would have alreayd thrown an exception. + // Otherwise, the Utf8JsonReader would have already thrown an exception. Debug.Assert(source.Length >= idx + 5); bool result = Utf8Parser.TryParse(source.Slice(idx + 1, 4), out int scalar, out int bytesConsumed, 'x'); @@ -399,7 +399,7 @@ internal static void Unescape(ReadOnlySpan source, Span destination, } // The source is known to be valid JSON, and hence if we see a \u, it is guaranteed to have 4 hex digits following it - // Otherwise, the Utf8JsonReader would have alreayd thrown an exception. + // Otherwise, the Utf8JsonReader would have already thrown an exception. result = Utf8Parser.TryParse(source.Slice(idx, 4), out int lowSurrogate, out bytesConsumed, 'x'); Debug.Assert(result); Debug.Assert(bytesConsumed == 4); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IAsyncEnumerableOfTConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IAsyncEnumerableOfTConverter.cs index 20dcedf4dbd321..7466fbeb78e302 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IAsyncEnumerableOfTConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/IAsyncEnumerableOfTConverter.cs @@ -59,6 +59,16 @@ protected override bool OnWriteResume(Utf8JsonWriter writer, TAsyncEnumerable va // ensure the enumerator already is stored // in the WriteStack for proper disposal. moveNextTask = enumerator.MoveNextAsync(); + + if (!moveNextTask.IsCompleted) + { + // It is common for first-time MoveNextAsync() calls to return pending tasks, + // since typically that is when underlying network connections are being established. + // For this case only, suppress flushing the current buffer contents (e.g. the leading '[' token of the written array) + // to give the stream owner the ability to recover in case of a connection error. + state.SuppressFlush = true; + goto SuspendDueToPendingTask; + } } else { @@ -81,10 +91,11 @@ protected override bool OnWriteResume(Utf8JsonWriter writer, TAsyncEnumerable va } } + Debug.Assert(moveNextTask.IsCompleted); JsonConverter converter = GetElementConverter(ref state); // iterate through the enumerator while elements are being returned synchronously - for (; moveNextTask.IsCompleted; moveNextTask = enumerator.MoveNextAsync()) + do { if (!moveNextTask.Result) { @@ -105,8 +116,11 @@ protected override bool OnWriteResume(Utf8JsonWriter writer, TAsyncEnumerable va { return false; } - } + moveNextTask = enumerator.MoveNextAsync(); + } while (moveNextTask.IsCompleted); + + SuspendDueToPendingTask: // we have a pending MoveNextAsync() call; // wrap inside a regular task so that it can be awaited multiple times; // mark the current stackframe as pending completion. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs index 88b93f95d1c487..5ee913f18d9482 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs @@ -8,7 +8,7 @@ namespace System.Text.Json.Serialization.Converters { /// /// Provides a mechanism to invoke "fast-path" serialization logic via - /// . This type holds an optional + /// . This type holds an optional /// reference to an actual for the type /// , to provide a fallback when the fast path cannot be used. /// @@ -22,7 +22,7 @@ internal sealed class JsonMetadataServicesConverter : JsonResumableConverter< private JsonConverter? _converter; // A backing converter for when fast-path logic cannot be used. - private JsonConverter Converter + internal JsonConverter Converter { get { @@ -75,10 +75,10 @@ internal override bool OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializer if (!state.SupportContinuation && jsonTypeInfo is JsonTypeInfo info && - info.Serialize != null && + info.SerializeHandler != null && info.Options._context?.CanUseSerializationLogic == true) { - info.Serialize(writer, value); + info.SerializeHandler(writer, value); return true; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs index 8d0f7bb437f10d..5dd032cc743e03 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs @@ -11,7 +11,7 @@ namespace System.Text.Json.Serialization.Converters /// Converter for JsonNode-derived types. The {T} value must be Object and not JsonNode /// since we allow Object-declared members\variables to deserialize as {JsonNode}. /// - internal sealed class JsonNodeConverter : JsonConverter + internal sealed class JsonNodeConverter : JsonConverter { private static JsonNodeConverter? s_nodeConverter; private static JsonArrayConverter? s_arrayConverter; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs index 60708ae8eee52f..c12debeb618560 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectDefaultConverter.cs @@ -16,9 +16,6 @@ internal class ObjectDefaultConverter : JsonObjectConverter where T : notn { internal override bool CanHaveIdMetadata => true; -#if NET6_0_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveOptimization)] -#endif internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo; @@ -249,9 +246,6 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, return true; } -#if NET6_0_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveOptimization)] -#endif internal sealed override bool OnTryWrite( Utf8JsonWriter writer, T value, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs index 3e25b10c13a237..f820ffbfe3a858 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs @@ -67,10 +67,7 @@ protected sealed override void InitializeConstructorArgumentCaches(ref ReadStack { JsonParameterInfo? parameterInfo = cache[i].Value; Debug.Assert(parameterInfo != null); - - arguments[parameterInfo.ClrInfo.Position] = parameterInfo.ShouldDeserialize - ? parameterInfo.DefaultValue - : parameterInfo.ClrDefaultValue; + arguments[parameterInfo.ClrInfo.Position] = parameterInfo.DefaultValue; } state.Current.CtorArgumentState!.Arguments = arguments; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ObjectConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ObjectConverter.cs index ddb2a899947b64..7ce4a2cb706b55 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ObjectConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/ObjectConverter.cs @@ -7,11 +7,6 @@ namespace System.Text.Json.Serialization.Converters { internal sealed class ObjectConverter : JsonConverter { - public ObjectConverter() - { - IsInternalConverterForNumberType = true; - } - public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonElement) @@ -50,15 +45,5 @@ internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, object? va runtimeConverter.WriteAsPropertyNameCoreAsObject(writer, value, options, isWritingExtensionDataProperty); } - - internal override object? ReadNumberWithCustomHandling(ref Utf8JsonReader reader, JsonNumberHandling handling, JsonSerializerOptions options) - { - if (options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonElement) - { - return JsonElement.ParseValue(ref reader); - } - - return JsonNodeConverter.Instance.Read(ref reader, typeof(object), options); - } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DisallowedTypeConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverter.cs similarity index 89% rename from src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DisallowedTypeConverter.cs rename to src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverter.cs index 27ed644b1ba3f1..d4a432e9b95c47 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DisallowedTypeConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverter.cs @@ -3,7 +3,7 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class DisallowedTypeConverter : JsonConverter + internal sealed class UnsupportedTypeConverter : JsonConverter { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => throw new NotSupportedException(SR.Format(SR.SerializeTypeInstanceNotSupported, typeof(T).FullName)); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DisallowedTypeConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs similarity index 86% rename from src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DisallowedTypeConverterFactory.cs rename to src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs index e771889bc46316..f211939119505b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DisallowedTypeConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs @@ -6,12 +6,11 @@ namespace System.Text.Json.Serialization.Converters { - internal sealed class DisallowedTypeConverterFactory : JsonConverterFactory + internal sealed class UnsupportedTypeConverterFactory : JsonConverterFactory { public override bool CanConvert(Type type) { - // If a value type is added, also add a test that - // shows NSE is thrown when Nullable is (de)serialized. + // If a type is added, also add to the SourceGeneration project. return // There's no safe way to construct a Type from untrusted user input. @@ -24,6 +23,8 @@ public override bool CanConvert(Type type) type == typeof(SerializationInfo) || type == typeof(IntPtr) || type == typeof(UIntPtr) || + // Exlude delegates. + typeof(Delegate).IsAssignableFrom(type) || // DateOnly/TimeOnly support to be added in future releases; // guard against invalid object-based serializations for now. // cf. https://github.com/dotnet/runtime/issues/53539 @@ -42,7 +43,7 @@ public override bool CanConvert(Type type) public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) { JsonConverter converter = (JsonConverter)Activator.CreateInstance( - typeof(DisallowedTypeConverter<>).MakeGenericType(type), + typeof(UnsupportedTypeConverter<>).MakeGenericType(type), BindingFlags.Instance | BindingFlags.Public, binder: null, args: null, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs index e15200546851d7..3deefaf77a6edc 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterOfT.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; +using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; namespace System.Text.Json.Serialization @@ -144,9 +145,6 @@ internal virtual bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, J /// Note that the value of determines if the converter handles null JSON tokens. public abstract T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options); -#if NET6_0_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveOptimization)] -#endif internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T? value) { if (ConverterStrategy == ConverterStrategy.Value) @@ -320,9 +318,6 @@ internal override sealed bool TryReadAsObject(ref Utf8JsonReader reader, JsonSer /// private static bool IsNull(T value) => value is null; -#if NET6_0_OR_GREATER - [MethodImpl(MethodImplOptions.AggressiveOptimization)] -#endif internal bool TryWrite(Utf8JsonWriter writer, in T value, JsonSerializerOptions options, ref WriteStack state) { if (writer.CurrentDepth >= options.EffectiveMaxDepth) @@ -504,7 +499,10 @@ internal bool TryWriteDataExtensionProperty(Utf8JsonWriter writer, T value, Json return TryWrite(writer, value, options, ref state); } - if (this is not JsonDictionaryConverter dictionaryConverter) + JsonDictionaryConverter? dictionaryConverter = this as JsonDictionaryConverter + ?? (this as JsonMetadataServicesConverter)?.Converter as JsonDictionaryConverter; + + if (dictionaryConverter == null) { // If not JsonDictionaryConverter then we are JsonObject. // Avoid a type reference to JsonObject and its converter to support trimming. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs index 4f100523bf486c..761798f14d921d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs @@ -43,8 +43,8 @@ private static void WriteUsingGeneratedSerializer(Utf8JsonWriter writer, jsonTypeInfo is JsonTypeInfo typedInfo && typedInfo.Options._context?.CanUseSerializationLogic == true) { - Debug.Assert(typedInfo.Serialize != null); - typedInfo.Serialize(writer, value); + Debug.Assert(typedInfo.SerializeHandler != null); + typedInfo.SerializeHandler(writer, value); writer.Flush(); } else diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs index 04b7b108a0d9b0..6351ef0ebd6c08 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Stream.cs @@ -18,8 +18,8 @@ public static partial class JsonSerializer // needs to be expanded\doubled because it is not large enough to write the current property or element. // We check for flush after each JSON property and element is written to the buffer. // Once the buffer is expanded to contain the largest single element\property, a 90% thresold - // means the buffer may be expanded a maximum of 4 times: 1-(1\(2^4))==.9375. - private const float FlushThreshold = .9f; + // means the buffer may be expanded a maximum of 4 times: 1-(1/(2^4))==.9375. + private const float FlushThreshold = .90f; /// /// Converts the provided value to UTF-8 encoded JSON text and write it to the . @@ -325,8 +325,18 @@ private static async Task WriteStreamAsync( try { isFinalBlock = WriteCore(converter, writer, value, options, ref state); - await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false); - bufferWriter.Clear(); + + if (state.SuppressFlush) + { + Debug.Assert(!isFinalBlock); + Debug.Assert(state.PendingTask is not null); + state.SuppressFlush = false; + } + else + { + await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false); + bufferWriter.Clear(); + } } finally { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs index 688fd91a3b91cb..0ce18180072c9e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs @@ -13,10 +13,30 @@ namespace System.Text.Json.Serialization public abstract partial class JsonSerializerContext { private bool? _canUseSerializationLogic; - private JsonSerializerOptions? _defaultOptions; internal JsonSerializerOptions? _options; + /// + /// Gets the run time specified options of the context. If no options were passed + /// when instanciating the context, then a new instance is bound and returned. + /// + /// + /// The instance cannot be mutated once it is bound with the context instance. + /// + public JsonSerializerOptions Options + { + get + { + if (_options == null) + { + _options = new JsonSerializerOptions(); + _options._context = this; + } + + return _options; + } + } + /// /// Indicates whether pre-generated serialization logic for types in the context /// is compatible with the run time specified . @@ -27,7 +47,7 @@ internal bool CanUseSerializationLogic { if (!_canUseSerializationLogic.HasValue) { - if (_defaultOptions == null) + if (GeneratedSerializerOptions == null) { _canUseSerializationLogic = false; } @@ -46,13 +66,13 @@ internal bool CanUseSerializationLogic #pragma warning restore SYSLIB0020 // Ensure options values are consistent with expected defaults. - Options.DefaultIgnoreCondition == _defaultOptions.DefaultIgnoreCondition && - Options.IgnoreReadOnlyFields == _defaultOptions.IgnoreReadOnlyFields && - Options.IgnoreReadOnlyProperties == _defaultOptions.IgnoreReadOnlyProperties && - Options.IncludeFields == _defaultOptions.IncludeFields && - Options.PropertyNamingPolicy == _defaultOptions.PropertyNamingPolicy && - Options.DictionaryKeyPolicy == _defaultOptions.DictionaryKeyPolicy && - Options.WriteIndented == _defaultOptions.WriteIndented; + Options.DefaultIgnoreCondition == GeneratedSerializerOptions.DefaultIgnoreCondition && + Options.IgnoreReadOnlyFields == GeneratedSerializerOptions.IgnoreReadOnlyFields && + Options.IgnoreReadOnlyProperties == GeneratedSerializerOptions.IgnoreReadOnlyProperties && + Options.IncludeFields == GeneratedSerializerOptions.IncludeFields && + Options.PropertyNamingPolicy == GeneratedSerializerOptions.PropertyNamingPolicy && + Options.DictionaryKeyPolicy == GeneratedSerializerOptions.DictionaryKeyPolicy && + Options.WriteIndented == GeneratedSerializerOptions.WriteIndented; } } @@ -61,49 +81,30 @@ internal bool CanUseSerializationLogic } /// - /// Gets the run time specified options of the context. If no options were passed - /// when instanciating the context, then a new instance is bound and returned. + /// The default run time options for the context. Its values are defined at design-time via . /// - /// - /// The instance cannot be mutated once it is bound with the context instance. - /// - public JsonSerializerOptions Options - { - get - { - if (_options == null) - { - _options = new JsonSerializerOptions(); - _options._context = this; - } - - return _options; - } - } + protected abstract JsonSerializerOptions? GeneratedSerializerOptions { get; } /// /// Creates an instance of and binds it with the indicated . /// - /// The run time provided options for the context instance. - /// The default run time options for the context. Its values are defined at design-time via . + /// The run time provided options for the context instance. /// /// If no instance options are passed, then no options are set until the context is bound using , /// or until is called, where a new options instance is created and bound. /// - protected JsonSerializerContext(JsonSerializerOptions? instanceOptions, JsonSerializerOptions? defaultOptions) + protected JsonSerializerContext(JsonSerializerOptions? options) { - if (instanceOptions != null) + if (options != null) { - if (instanceOptions._context != null) + if (options._context != null) { ThrowHelper.ThrowInvalidOperationException_JsonSerializerOptionsAlreadyBoundToContext(); } - _options = instanceOptions; - instanceOptions._context = this; + _options = options; + options._context = this; } - - _defaultOptions = defaultOptions; } /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs index 912cabef9e69ba..77b5d7071f7120 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs @@ -30,23 +30,26 @@ public sealed partial class JsonSerializerOptions [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)] private void RootBuiltInConverters() { - s_defaultSimpleConverters = GetDefaultSimpleConverters(); - s_defaultFactoryConverters = new JsonConverter[] + if (s_defaultSimpleConverters is null) { - // Check for disallowed types. - new DisallowedTypeConverterFactory(), - // Nullable converter should always be next since it forwards to any nullable type. - new NullableConverterFactory(), - new EnumConverterFactory(), - new JsonNodeConverterFactory(), - new FSharpTypeConverterFactory(), - // IAsyncEnumerable takes precedence over IEnumerable. - new IAsyncEnumerableConverterFactory(), - // IEnumerable should always be second to last since they can convert any IEnumerable. - new IEnumerableConverterFactory(), - // Object should always be last since it converts any type. - new ObjectConverterFactory() - }; + s_defaultSimpleConverters = GetDefaultSimpleConverters(); + s_defaultFactoryConverters = new JsonConverter[] + { + // Check for disallowed types. + new UnsupportedTypeConverterFactory(), + // Nullable converter should always be next since it forwards to any nullable type. + new NullableConverterFactory(), + new EnumConverterFactory(), + new JsonNodeConverterFactory(), + new FSharpTypeConverterFactory(), + // IAsyncEnumerable takes precedence over IEnumerable. + new IAsyncEnumerableConverterFactory(), + // IEnumerable should always be second to last since they can convert any IEnumerable. + new IEnumerableConverterFactory(), + // Object should always be last since it converts any type. + new ObjectConverterFactory() + }; + } } private static Dictionary GetDefaultSimpleConverters() diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs index 2d23e7c5c9200b..f81025bbc460e5 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.cs @@ -600,9 +600,7 @@ internal JsonTypeInfo GetOrAddClass(Type type) { _haveTypesBeenCreated = true; - // todo: for performance and reduced instances, consider using the converters and JsonTypeInfo from s_defaultOptions by cloning (or reference directly if no changes). - // https://github.com/dotnet/runtime/issues/32357 - if (!_classes.TryGetValue(type, out JsonTypeInfo? result)) + if (!TryGetClass(type, out JsonTypeInfo? result)) { result = _classes.GetOrAdd(type, GetClassFromContextOrCreate(type)); } @@ -644,6 +642,20 @@ internal JsonTypeInfo GetOrAddClassForRootType(Type type) return jsonTypeInfo; } + internal bool TryGetClass(Type type, [NotNullWhen(true)] out JsonTypeInfo? jsonTypeInfo) + { + // todo: for performance and reduced instances, consider using the converters and JsonTypeInfo from s_defaultOptions by cloning (or reference directly if no changes). + // https://github.com/dotnet/runtime/issues/32357 + if (!_classes.TryGetValue(type, out JsonTypeInfo? result)) + { + jsonTypeInfo = null; + return false; + } + + jsonTypeInfo = result; + return true; + } + internal bool TypeIsCached(Type type) { return _classes.ContainsKey(type); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs index a144c11d398c9d..2c143f95e59cc9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/GenericMethodHolder.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.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Text.Json.Reflection; @@ -12,10 +13,24 @@ namespace System.Text.Json.Serialization.Metadata /// internal abstract class GenericMethodHolder { + /// + /// Returns the default value for the specified type. + /// + public abstract object? DefaultValue { get; } + /// /// Returns true if contains only default values. /// public abstract bool IsDefaultValue(object value); + + /// + /// Creates a holder instance representing a type. + /// + public static GenericMethodHolder CreateHolder(Type type) + { + Type holderType = typeof(GenericMethodHolder<>).MakeGenericType(type); + return (GenericMethodHolder)Activator.CreateInstance(holderType)!; + } } /// @@ -23,6 +38,8 @@ internal abstract class GenericMethodHolder /// internal sealed class GenericMethodHolder : GenericMethodHolder { + public override object? DefaultValue => default(T); + public override bool IsDefaultValue(object value) { // For performance, we only want to call this method for non-nullable value types. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs new file mode 100644 index 00000000000000..b1fef6a4c934f2 --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.Json.Serialization.Metadata +{ + /// + /// Provides serialization metadata about a collection type. + /// + /// The collection type. + public sealed class JsonCollectionInfoValues + { + /// + /// A to create an instance of the collection when deserializing. + /// + public Func? ObjectCreator { get; init; } + + /// + /// If a dictionary type, the instance representing the key type. + /// + public JsonTypeInfo? KeyInfo { get; init; } + + /// + /// A instance representing the element type. + /// + public JsonTypeInfo ElementInfo { get; init; } = null!; + + /// + /// The option to apply to number collection elements. + /// + public JsonNumberHandling NumberHandling { get; init; } + + /// + /// An optimized serialization implementation assuming pre-determined defaults. + /// + public Action? SerializeHandler { get; init; } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs index 71f48ad41b0eff..4b1708652961cf 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs @@ -11,552 +11,368 @@ namespace System.Text.Json.Serialization.Metadata public static partial class JsonMetadataServices { /// - /// Creates metadata for an array. + /// Creates serialization metadata for an array. /// /// The generic definition of the element type. /// The to use. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// - public static JsonTypeInfo CreateArrayInfo( - JsonSerializerOptions options, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. + public static JsonTypeInfo CreateArrayInfo(JsonSerializerOptions options, JsonCollectionInfoValues collectionInfo) => new JsonTypeInfoInternal( options, - createObjectFunc: null, - () => new ArrayConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ArrayConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. - /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// The to use. + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateListInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : List => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ListOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ListOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : Dictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new DictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue)); + collectionInfo, + () => new DictionaryOfTKeyTValueConverter()); #pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved /// - /// Creates metadata for and + /// Creates serialization metadata for and /// types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. + /// Provides serialization metadata about the collection type. /// A method to create an immutable dictionary instance. - /// + /// Serialization metadata for the given type. #pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved public static JsonTypeInfo CreateImmutableDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, + JsonCollectionInfoValues collectionInfo, Func>, TCollection> createRangeFunc) where TCollection : IReadOnlyDictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, + collectionInfo, () => new ImmutableDictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue), - createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); + createObjectWithArgs: createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IDictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IDictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue)); + collectionInfo, + () => new IDictionaryOfTKeyTValueConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIReadOnlyDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IReadOnlyDictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IReadOnlyDictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue)); + collectionInfo, + () => new IReadOnlyDictionaryOfTKeyTValueConverter()); #pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved /// - /// Creates metadata for non-dictionary immutable collection types. + /// Creates serialization metadata for non-dictionary immutable collection types. /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. + /// Provides serialization metadata about the collection type. /// A method to create an immutable dictionary instance. - /// + /// Serialization metadata for the given type. #pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved public static JsonTypeInfo CreateImmutableEnumerableInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, + JsonCollectionInfoValues collectionInfo, Func, TCollection> createRangeFunc) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, + collectionInfo, () => new ImmutableEnumerableOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement), - createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); + createObjectWithArgs: createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIListInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo objectInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IList => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IListConverter(), - objectInfo, - numberHandling, - serializeFunc, - typeof(object)); + collectionInfo, + () => new IListConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIListInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IList => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IListOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new IListOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateISetInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ISet => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ISetOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ISetOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateICollectionInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ICollection => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ICollectionOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ICollectionOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateStackInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : Stack => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new StackOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new StackOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateQueueInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : Queue => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new QueueOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new QueueOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateConcurrentStackInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ConcurrentStack => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ConcurrentStackOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ConcurrentStackOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateConcurrentQueueInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ConcurrentQueue => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ConcurrentQueueOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ConcurrentQueueOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIEnumerableInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IEnumerableOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new IEnumerableOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing instances. - /// A instance representing instances. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo stringInfo, - JsonTypeInfo objectInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IDictionary => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IDictionaryConverter(), - keyInfo: stringInfo, - valueInfo: objectInfo, - numberHandling, - serializeFunc, - typeof(string), - typeof(object)); + collectionInfo, + () => new IDictionaryConverter()); + +#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved + /// + /// Creates serialization metadata for types. + /// + /// The generic definition of the type. + /// + /// Provides serialization metadata about the collection type. + /// A method for adding elements to the collection when using the serializer's code-paths. + /// Serialization metadata for the given type. +#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved + public static JsonTypeInfo CreateStackInfo( + JsonSerializerOptions options, + JsonCollectionInfoValues collectionInfo, + Action addFunc) + where TCollection : IEnumerable + => CreateStackOrQueueInfo(options, collectionInfo, addFunc); +#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types. /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. + /// Provides serialization metadata about the collection type. /// A method for adding elements to the collection when using the serializer's code-paths. - /// - public static JsonTypeInfo CreateStackOrQueueInfo( + /// Serialization metadata for the given type. +#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved + public static JsonTypeInfo CreateQueueInfo( + JsonSerializerOptions options, + JsonCollectionInfoValues collectionInfo, + Action addFunc) + where TCollection : IEnumerable + => CreateStackOrQueueInfo(options, collectionInfo, addFunc); + + private static JsonTypeInfo CreateStackOrQueueInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, + JsonCollectionInfoValues collectionInfo, Action addFunc) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, + collectionInfo, () => new StackOrQueueConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(object), createObjectWithArgs: null, addFunc: addFunc ?? throw new ArgumentNullException(nameof(addFunc))); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIEnumerableInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IEnumerableConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(object)); + collectionInfo, + () => new IEnumerableConverter()); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs index 39ad153d48da1d..5cf7292e2b4551 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Text.Json.Nodes; using System.Text.Json.Serialization.Converters; namespace System.Text.Json.Serialization.Metadata @@ -80,12 +81,36 @@ public static partial class JsonMetadataServices public static JsonConverter Int64Converter => s_int64Converter ??= new Int64Converter(); private static JsonConverter? s_int64Converter; + /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonArrayConverter => s_jsonArrayConverter ??= new JsonArrayConverter(); + private static JsonConverter? s_jsonArrayConverter; + /// /// Returns a instance that converts values. /// public static JsonConverter JsonElementConverter => s_jsonElementConverter ??= new JsonElementConverter(); private static JsonConverter? s_jsonElementConverter; + /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonNodeConverter => s_jsonNodeConverter ??= new JsonNodeConverter(); + private static JsonConverter? s_jsonNodeConverter; + + /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonObjectConverter => s_jsonObjectConverter ??= new JsonObjectConverter(); + private static JsonConverter? s_jsonObjectConverter; + + /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonValueConverter => s_jsonValueConverter ??= new JsonValueConverter(); + private static JsonConverter? s_jsonValueConverter; + /// /// Returns a instance that converts values. /// @@ -150,12 +175,20 @@ public static partial class JsonMetadataServices public static JsonConverter VersionConverter => s_versionConverter ??= new VersionConverter(); private static JsonConverter? s_versionConverter; + /// + /// Creates a instance that throws . + /// + /// The generic definition for the type. + /// A instance that throws + public static JsonConverter GetUnsupportedTypeConverter() + => new UnsupportedTypeConverter(); + /// /// Creates a instance that converts values. /// /// The generic definition for the enum type. /// The to use for serialization and deserialization. - /// + /// A instance that converts values. public static JsonConverter GetEnumConverter(JsonSerializerOptions options) where T : struct, Enum => new EnumConverter(EnumConverterOptions.AllowNumbers, options ?? throw new ArgumentNullException(nameof(options))); @@ -164,7 +197,7 @@ public static JsonConverter GetEnumConverter(JsonSerializerOptions options /// /// The generic definition for the underlying nullable type. /// Serialization metadata for the underlying nullable type. - /// + /// A instance that converts values public static JsonConverter GetNullableConverter(JsonTypeInfo underlyingTypeInfo) where T : struct { if (underlyingTypeInfo == null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs index 20b33ac2e28761..e9b0578b863d92 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs @@ -1,7 +1,6 @@ // 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.ComponentModel; namespace System.Text.Json.Serialization.Metadata @@ -17,56 +16,39 @@ public static partial class JsonMetadataServices /// /// The type that the converter for the property returns or accepts when converting JSON data. /// The to initialize the metadata with. - /// Whether the CLR member is a property or field. - /// Whether the CLR member is public. - /// Whether the CLR member is a virtual property. - /// The declaring type of the property or field. - /// The info for the property or field's type. - /// A for the property or field, specified by . - /// Provides a mechanism to get the property or field's value. - /// Provides a mechanism to set the property or field's value. - /// Specifies a condition for the property to be ignored. - /// If the property or field is a number, specifies how it should processed when serializing and deserializing. - /// Whether the property was annotated with . - /// The CLR name of the property or field. - /// The name to be used when processing the property or field, specified by . + /// Provides serialization metadata about the property or field. /// A instance intialized with the provided metadata. - public static JsonPropertyInfo CreatePropertyInfo( - JsonSerializerOptions options, - bool isProperty, - bool isPublic, - bool isVirtual, - Type declaringType, - JsonTypeInfo propertyTypeInfo, - JsonConverter? converter, - Func? getter, - Action? setter, - JsonIgnoreCondition? ignoreCondition, - bool hasJsonInclude, - JsonNumberHandling? numberHandling, - string propertyName, - string? jsonPropertyName) + public static JsonPropertyInfo CreatePropertyInfo(JsonSerializerOptions options, JsonPropertyInfoValues propertyInfo) { if (options == null) { throw new ArgumentNullException(nameof(options)); } + if (propertyInfo == null) + { + throw new ArgumentNullException(nameof(propertyInfo)); + } + + Type? declaringType = propertyInfo.DeclaringType; if (declaringType == null) { - throw new ArgumentNullException(nameof(declaringType)); + throw new ArgumentException(nameof(propertyInfo.DeclaringType)); } + JsonTypeInfo? propertyTypeInfo = propertyInfo.PropertyTypeInfo; if (propertyTypeInfo == null) { - throw new ArgumentNullException(nameof(propertyTypeInfo)); + throw new ArgumentException(nameof(propertyInfo.PropertyTypeInfo)); } + string? propertyName = propertyInfo.PropertyName; if (propertyName == null) { - throw new ArgumentNullException(nameof(propertyName)); + throw new ArgumentException(nameof(propertyInfo.PropertyName)); } + JsonConverter? converter = propertyInfo.Converter; if (converter == null) { converter = propertyTypeInfo.PropertyInfoForTypeInfo.ConverterBase as JsonConverter; @@ -76,27 +58,13 @@ public static JsonPropertyInfo CreatePropertyInfo( } } - if (!isProperty && isVirtual) + if (!propertyInfo.IsProperty && propertyInfo.IsVirtual) { - throw new InvalidOperationException(SR.Format(SR.FieldCannotBeVirtual, nameof(isProperty), nameof(isVirtual))); + throw new InvalidOperationException(SR.Format(SR.FieldCannotBeVirtual, nameof(propertyInfo.IsProperty), nameof(propertyInfo.IsVirtual))); } JsonPropertyInfo jsonPropertyInfo = new JsonPropertyInfo(); - jsonPropertyInfo.InitializeForSourceGen( - options, - isProperty, - isPublic, - declaringType, - propertyTypeInfo, - converter, - getter, - setter, - ignoreCondition, - hasJsonInclude, - numberHandling, - propertyName, - jsonPropertyName); - + jsonPropertyInfo.InitializeForSourceGen(options, propertyInfo); return jsonPropertyInfo; } @@ -120,7 +88,7 @@ public static JsonTypeInfo CreateObjectInfo(JsonSerializerOptions options, /// A instance representing the type. public static JsonTypeInfo CreateValueInfo(JsonSerializerOptions options, JsonConverter converter) { - JsonTypeInfo info = new JsonTypeInfoInternal(options, ConverterStrategy.Value); + JsonTypeInfo info = new JsonTypeInfoInternal(options); info.PropertyInfoForTypeInfo = CreateJsonPropertyInfoForClassInfo(typeof(T), info, converter, options); return info; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValues.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValuesOfT.cs similarity index 100% rename from src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValues.cs rename to src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValuesOfT.cs diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs index ae2768ae0f5343..8aee3b75f34415 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfo.cs @@ -18,8 +18,6 @@ internal abstract class JsonParameterInfo private protected bool MatchingPropertyCanBeNull { get; private set; } - internal abstract object? ClrDefaultValue { get; } - // The default value of the parameter. This is `DefaultValue` of the `ParameterInfo`, if specified, or the CLR `default` for the `ParameterType`. public object? DefaultValue { get; private protected set; } @@ -75,18 +73,49 @@ public virtual void Initialize(JsonParameterInfoValues parameterInfo, JsonProper MatchingPropertyCanBeNull = matchingProperty.PropertyTypeCanBeNull; } - // Create a parameter that is ignored at run time. It uses the same type (typeof(sbyte)) to help - // prevent issues with unsupported types and helps ensure we don't accidently (de)serialize it. - public static JsonParameterInfo CreateIgnoredParameterPlaceholder(JsonParameterInfoValues parameterInfo, JsonPropertyInfo matchingProperty) + /// + /// Create a parameter that is ignored at run time. It uses the same type (typeof(sbyte)) to help + /// prevent issues with unsupported types and helps ensure we don't accidently (de)serialize it. + /// + public static JsonParameterInfo CreateIgnoredParameterPlaceholder( + JsonParameterInfoValues parameterInfo, + JsonPropertyInfo matchingProperty, + bool sourceGenMode) { - JsonParameterInfo jsonParameterInfo = matchingProperty.ConverterBase.CreateJsonParameterInfo(); + JsonParameterInfo jsonParameterInfo = new JsonParameterInfo(); jsonParameterInfo.ClrInfo = parameterInfo; jsonParameterInfo.RuntimePropertyType = matchingProperty.RuntimePropertyType!; jsonParameterInfo.NameAsUtf8Bytes = matchingProperty.NameAsUtf8Bytes!; - jsonParameterInfo.InitializeDefaultValue(matchingProperty); + + // TODO: https://github.com/dotnet/runtime/issues/60082. + // Default value initialization for params mapping to ignored properties doesn't + // account for the default value of optional parameters. This should be fixed. + + if (sourceGenMode) + { + // The value in the matching JsonPropertyInfo instance matches the parameter type. + jsonParameterInfo.DefaultValue = matchingProperty.DefaultValue; + } + else + { + // The value in the created JsonPropertyInfo instance (sbyte) + // doesn't match the parameter type, use reflection to get the default value. + Type parameterType = parameterInfo.ParameterType; + + GenericMethodHolder holder; + if (matchingProperty.Options.TryGetClass(parameterType, out JsonTypeInfo? typeInfo)) + { + holder = typeInfo.GenericMethods; + } + else + { + holder = GenericMethodHolder.CreateHolder(parameterInfo.ParameterType); + } + + jsonParameterInfo.DefaultValue = holder.DefaultValue; + } + return jsonParameterInfo; } - - protected abstract void InitializeDefaultValue(JsonPropertyInfo matchingProperty); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs index 2195426a551edf..b275f01acd0952 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonParameterInfoOfT.cs @@ -11,8 +11,6 @@ namespace System.Text.Json.Serialization.Metadata /// internal sealed class JsonParameterInfo : JsonParameterInfo { - internal override object? ClrDefaultValue => default(T); - public T TypedDefaultValue { get; private set; } = default!; public override void Initialize(JsonParameterInfoValues parameterInfo, JsonPropertyInfo matchingProperty, JsonSerializerOptions options) @@ -21,7 +19,7 @@ public override void Initialize(JsonParameterInfoValues parameterInfo, JsonPrope InitializeDefaultValue(matchingProperty); } - protected override void InitializeDefaultValue(JsonPropertyInfo matchingProperty) + private void InitializeDefaultValue(JsonPropertyInfo matchingProperty) { Debug.Assert(ClrInfo.ParameterType == matchingProperty.DeclaredPropertyType); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs index 0ae3d8126d931c..5e2258ec6dde83 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs @@ -42,16 +42,14 @@ internal static JsonPropertyInfo GetPropertyPlaceholder() // Create a property that is ignored at run-time. internal static JsonPropertyInfo CreateIgnoredPropertyPlaceholder( - JsonConverter converter, MemberInfo memberInfo, Type memberType, bool isVirtual, JsonSerializerOptions options) { - JsonPropertyInfo jsonPropertyInfo = converter.CreateJsonPropertyInfo(); + JsonPropertyInfo jsonPropertyInfo = new JsonPropertyInfo(); jsonPropertyInfo.Options = options; - jsonPropertyInfo.ConverterBase = converter; jsonPropertyInfo.MemberInfo = memberInfo; jsonPropertyInfo.IsIgnored = true; jsonPropertyInfo.DeclaredPropertyType = memberType; @@ -503,6 +501,11 @@ internal JsonTypeInfo RuntimeTypeInfo /// internal bool SrcGen_HasJsonInclude { get; set; } + /// + /// Relevant to source generated metadata: did the property have the ? + /// + internal bool SrcGen_IsExtensionData { get; set; } + /// /// Relevant to source generated metadata: is the property public? /// @@ -520,5 +523,10 @@ internal JsonTypeInfo RuntimeTypeInfo internal string? ClrName { get; set; } internal bool IsVirtual { get; set; } + + /// + /// Default value used for parameterized ctor invocation. + /// + internal abstract object? DefaultValue { get; } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index 6111f46117c347..e98f08dd54cdcd 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -28,8 +28,11 @@ internal sealed class JsonPropertyInfo : JsonPropertyInfo private bool _propertyTypeEqualsTypeToConvert; internal Func? Get { get; set; } + internal Action? Set { get; set; } + internal override object? DefaultValue => default(T); + public JsonConverter Converter { get; internal set; } = null!; internal override void Initialize( @@ -116,28 +119,15 @@ internal override void Initialize( GetPolicies(ignoreCondition, parentTypeNumberHandling); } - internal void InitializeForSourceGen( - JsonSerializerOptions options, - bool isProperty, - bool isPublic, - Type declaringType, - JsonTypeInfo typeInfo, - JsonConverter converter, - Func? getter, - Action? setter, - JsonIgnoreCondition? ignoreCondition, - bool hasJsonInclude, - JsonNumberHandling? numberHandling, - string propertyName, - string? jsonPropertyName) + internal void InitializeForSourceGen(JsonSerializerOptions options, JsonPropertyInfoValues propertyInfo) { Options = options; - ClrName = propertyName; + ClrName = propertyInfo.PropertyName; // Property name settings. - if (jsonPropertyName != null) + if (propertyInfo.JsonPropertyName != null) { - NameAsString = jsonPropertyName; + NameAsString = propertyInfo.JsonPropertyName; } else if (options.PropertyNamingPolicy == null) { @@ -154,13 +144,27 @@ internal void InitializeForSourceGen( NameAsUtf8Bytes ??= Encoding.UTF8.GetBytes(NameAsString!); EscapedNameSection ??= JsonHelpers.GetEscapedPropertyNameSection(NameAsUtf8Bytes, Options.Encoder); - - SrcGen_IsPublic = isPublic; - SrcGen_HasJsonInclude = hasJsonInclude; + SrcGen_IsPublic = propertyInfo.IsPublic; + SrcGen_HasJsonInclude = propertyInfo.HasJsonInclude; + SrcGen_IsExtensionData = propertyInfo.IsExtensionData; DeclaredPropertyType = typeof(T); + + JsonTypeInfo propertyTypeInfo = propertyInfo.PropertyTypeInfo; + Type declaringType = propertyInfo.DeclaringType; + + JsonConverter? converter = propertyInfo.Converter; + if (converter == null) + { + converter = propertyTypeInfo.PropertyInfoForTypeInfo.ConverterBase as JsonConverter; + if (converter == null) + { + throw new InvalidOperationException(SR.Format(SR.ConverterForPropertyMustBeValid, declaringType, ClrName, typeof(T))); + } + } + ConverterBase = converter; - if (ignoreCondition == JsonIgnoreCondition.Always) + if (propertyInfo.IgnoreCondition == JsonIgnoreCondition.Always) { IsIgnored = true; Debug.Assert(!ShouldSerialize); @@ -168,23 +172,23 @@ internal void InitializeForSourceGen( } else { - Get = getter!; - Set = setter; + Get = propertyInfo.Getter!; + Set = propertyInfo.Setter; HasGetter = Get != null; HasSetter = Set != null; - RuntimeTypeInfo = typeInfo; + RuntimeTypeInfo = propertyTypeInfo; DeclaringType = declaringType; - IgnoreCondition = ignoreCondition; - MemberType = isProperty ? MemberTypes.Property : MemberTypes.Field; + IgnoreCondition = propertyInfo.IgnoreCondition; + MemberType = propertyInfo.IsProperty ? MemberTypes.Property : MemberTypes.Field; - _converterIsExternalAndPolymorphic = !converter.IsInternalConverter && DeclaredPropertyType != converter.TypeToConvert; + _converterIsExternalAndPolymorphic = !ConverterBase.IsInternalConverter && DeclaredPropertyType != ConverterBase.TypeToConvert; PropertyTypeCanBeNull = typeof(T).CanBeNull(); - _propertyTypeEqualsTypeToConvert = converter.TypeToConvert == typeof(T); + _propertyTypeEqualsTypeToConvert = ConverterBase.TypeToConvert == typeof(T); ConverterStrategy = Converter!.ConverterStrategy; RuntimePropertyType = DeclaredPropertyType; DetermineIgnoreCondition(IgnoreCondition); // TODO: this method needs to also take the number handling option for the declaring type. - DetermineNumberHandlingForProperty(numberHandling, declaringTypeNumberHandling: null); + DetermineNumberHandlingForProperty(propertyInfo.NumberHandling, declaringTypeNumberHandling: null); DetermineSerializationCapabilities(IgnoreCondition); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs new file mode 100644 index 00000000000000..ed7fffe7124c7b --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.Json.Serialization.Metadata +{ + /// + /// Provides serialization metadata about a property or field. + /// + /// The type to convert of the for the property. + public sealed class JsonPropertyInfoValues + { + /// + /// If , indicates that the member is a property, otherwise indicates the member is a field. + /// + public bool IsProperty { get; init; } + + /// + /// Whether the property or field is public. + /// + public bool IsPublic { get; init; } + + /// + /// Whether the property or field is a virtual property. + /// + public bool IsVirtual { get; init; } + + /// + /// The declaring type of the property or field. + /// + public Type DeclaringType { get; init; } = null!; + + /// + /// The info for the property or field's type. + /// + public JsonTypeInfo PropertyTypeInfo { get; init; } = null!; + + /// + /// A for the property or field, specified by . + /// + public JsonConverter? Converter { get; init; } + + /// + /// Provides a mechanism to get the property or field's value. + /// + public Func? Getter { get; init; } + + /// + /// Provides a mechanism to set the property or field's value. + /// + public Action? Setter { get; init; } + + /// + /// Specifies a condition for the member to be ignored. + /// + public JsonIgnoreCondition? IgnoreCondition { get; init; } + + /// + /// Whether the property was annotated with . + /// + public bool HasJsonInclude { get; init; } + + /// + /// Whether the property was annotated with . + /// + public bool IsExtensionData { get; init; } + + /// + /// If the property or field is a number, specifies how it should processed when serializing and deserializing. + /// + public JsonNumberHandling? NumberHandling { get; init; } + + /// + /// The name of the property or field. + /// + public string PropertyName { get; init; } = null!; + + /// + /// The name to be used when processing the property or field, specified by . + /// + public string? JsonPropertyName { get; init; } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs index 00911d756bdefb..f696cefe8f21cd 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.Cache.cs @@ -58,6 +58,12 @@ internal static JsonPropertyInfo AddProperty( JsonNumberHandling? parentTypeNumberHandling, JsonSerializerOptions options) { + JsonIgnoreCondition? ignoreCondition = JsonPropertyInfo.GetAttribute(memberInfo)?.Condition; + if (ignoreCondition == JsonIgnoreCondition.Always) + { + return JsonPropertyInfo.CreateIgnoredPropertyPlaceholder(memberInfo, memberType, isVirtual, options); + } + JsonConverter converter = GetConverter( memberType, parentClassType, @@ -65,12 +71,6 @@ internal static JsonPropertyInfo AddProperty( out Type runtimeType, options); - JsonIgnoreCondition? ignoreCondition = JsonPropertyInfo.GetAttribute(memberInfo)?.Condition; - if (ignoreCondition == JsonIgnoreCondition.Always) - { - return JsonPropertyInfo.CreateIgnoredPropertyPlaceholder(converter, memberInfo, memberType, isVirtual, options); - } - return CreateProperty( declaredPropertyType: memberType, runtimePropertyType: runtimeType, @@ -613,6 +613,16 @@ internal void InitializePropCache() continue; } + if (jsonPropertyInfo.SrcGen_IsExtensionData) + { + // Source generator compile-time type inspection has performed this validation for us. + Debug.Assert(DataExtensionProperty == null); + Debug.Assert(IsValidDataExtensionProperty(jsonPropertyInfo)); + + DataExtensionProperty = jsonPropertyInfo; + continue; + } + CacheMember(jsonPropertyInfo, propertyCache, ref ignoredMembers); } @@ -636,7 +646,7 @@ internal void InitializeParameterCache() return; } - InitializeConstructorParameters(array); + InitializeConstructorParameters(array, sourceGenMode: true); Debug.Assert(ParameterCache != null); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index 28fb27669139e6..b7e11501e60459 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -130,12 +130,7 @@ internal GenericMethodHolder GenericMethods { get { - if (_genericMethods == null) - { - Type runtimePropertyClass = typeof(GenericMethodHolder<>).MakeGenericType(new Type[] { Type })!; - _genericMethods = (GenericMethodHolder)Activator.CreateInstance(runtimePropertyClass)!; - } - + _genericMethods ??= GenericMethodHolder.CreateHolder(Type); return _genericMethods; } } @@ -147,7 +142,7 @@ internal JsonTypeInfo() Debug.Assert(false, "This constructor should not be called."); } - internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy) + internal JsonTypeInfo(Type type, JsonSerializerOptions options, bool dummy) { Type = type; Options = options ?? throw new ArgumentNullException(nameof(options)); @@ -451,7 +446,7 @@ public ParameterLookupValue(JsonPropertyInfo jsonPropertyInfo) public JsonPropertyInfo JsonPropertyInfo { get; } } - private void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters) + private void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParameters, bool sourceGenMode = false) { var parameterCache = new JsonPropertyDictionary(Options.PropertyNameCaseInsensitive, jsonParameters.Length); @@ -497,14 +492,14 @@ private void InitializeConstructorParameters(JsonParameterInfoValues[] jsonParam Debug.Assert(matchingEntry.JsonPropertyInfo != null); JsonPropertyInfo jsonPropertyInfo = matchingEntry.JsonPropertyInfo; - JsonParameterInfo jsonParameterInfo = CreateConstructorParameter(parameterInfo, jsonPropertyInfo, Options); + JsonParameterInfo jsonParameterInfo = CreateConstructorParameter(parameterInfo, jsonPropertyInfo, sourceGenMode, Options); parameterCache.Add(jsonPropertyInfo.NameAsString, jsonParameterInfo); } // It is invalid for the extension data property to bind with a constructor argument. else if (DataExtensionProperty != null && StringComparer.OrdinalIgnoreCase.Equals(paramToCheck.Name, DataExtensionProperty.NameAsString)) { - ThrowHelper.ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(DataExtensionProperty.MemberInfo!, Type); + ThrowHelper.ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(DataExtensionProperty); } } @@ -527,7 +522,7 @@ private static JsonParameterInfoValues[] GetParameterInfoArray(ParameterInfo[] p ParameterType = reflectionInfo.ParameterType, Position = reflectionInfo.Position, HasDefaultValue = reflectionInfo.HasDefaultValue, - DefaultValue = reflectionInfo.DefaultValue + DefaultValue = reflectionInfo.GetDefaultValue() }; jsonParameters[i] = jsonInfo; @@ -554,17 +549,7 @@ private static bool PropertyIsOverridenAndIgnored( private void ValidateAndAssignDataExtensionProperty(JsonPropertyInfo jsonPropertyInfo) { - Type memberType = jsonPropertyInfo.DeclaredPropertyType; - JsonConverter? converter = null; - if (typeof(IDictionary).IsAssignableFrom(memberType) || - typeof(IDictionary).IsAssignableFrom(memberType) || - // Avoid a reference to typeof(JsonNode) to support trimming. - (memberType.FullName == JsonObjectTypeName && ReferenceEquals(memberType.Assembly, GetType().Assembly))) - { - converter = Options.GetConverterInternal(memberType); - } - - if (converter == null) + if (!IsValidDataExtensionProperty(jsonPropertyInfo)) { ThrowHelper.ThrowInvalidOperationException_SerializationDataExtensionPropertyInvalid(Type, jsonPropertyInfo); } @@ -572,14 +557,27 @@ private void ValidateAndAssignDataExtensionProperty(JsonPropertyInfo jsonPropert DataExtensionProperty = jsonPropertyInfo; } + private bool IsValidDataExtensionProperty(JsonPropertyInfo jsonPropertyInfo) + { + Type memberType = jsonPropertyInfo.DeclaredPropertyType; + + bool typeIsValid = typeof(IDictionary).IsAssignableFrom(memberType) || + typeof(IDictionary).IsAssignableFrom(memberType) || + // Avoid a reference to typeof(JsonNode) to support trimming. + (memberType.FullName == JsonObjectTypeName && ReferenceEquals(memberType.Assembly, GetType().Assembly)); + + return typeIsValid && Options.GetConverterInternal(memberType) != null; + } + private static JsonParameterInfo CreateConstructorParameter( JsonParameterInfoValues parameterInfo, JsonPropertyInfo jsonPropertyInfo, + bool sourceGenMode, JsonSerializerOptions options) { if (jsonPropertyInfo.IsIgnored) { - return JsonParameterInfo.CreateIgnoredParameterPlaceholder(parameterInfo, jsonPropertyInfo); + return JsonParameterInfo.CreateIgnoredParameterPlaceholder(parameterInfo, jsonPropertyInfo, sourceGenMode); } JsonConverter converter = jsonPropertyInfo.ConverterBase; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs index e7e5dc7067bf52..552b49658dddd2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs @@ -1,7 +1,6 @@ // 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.Text.Json.Serialization.Converters; namespace System.Text.Json.Serialization.Metadata @@ -13,17 +12,17 @@ namespace System.Text.Json.Serialization.Metadata internal sealed class JsonTypeInfoInternal : JsonTypeInfo { /// - /// Creates serialization metadata given JsonSerializerOptions and a ConverterStrategy. + /// Creates serialization metadata for a type using a simple converter. /// - public JsonTypeInfoInternal(JsonSerializerOptions options, ConverterStrategy converterStrategy) - : base(typeof(T), options, converterStrategy) + public JsonTypeInfoInternal(JsonSerializerOptions options) + : base(typeof(T), options) { } /// /// Creates serialization metadata for an object. /// - public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues objectInfo) : base(typeof(T), options, ConverterStrategy.Object) + public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues objectInfo) : base(typeof(T), options) { #pragma warning disable CS8714 // The type cannot be used as type parameter in the generic type or method. @@ -46,66 +45,40 @@ public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues< #pragma warning restore CS8714 PropInitFunc = objectInfo.PropertyMetadataInitializer; - Serialize = objectInfo.SerializeHandler; + SerializeHandler = objectInfo.SerializeHandler; PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, Options); NumberHandling = objectInfo.NumberHandling; } /// - /// Creates serialization metadata for a . + /// Creates serialization metadata for a collection. /// public JsonTypeInfoInternal( JsonSerializerOptions options, - Func? createObjectFunc, + JsonCollectionInfoValues collectionInfo, Func> converterCreator, - JsonTypeInfo? elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, - Type elementType, object? createObjectWithArgs = null, object? addFunc = null) - : base(typeof(T), options, ConverterStrategy.Enumerable) + : base(typeof(T), options) { - JsonConverter converter = new JsonMetadataServicesConverter(converterCreator, ConverterStrategy.Enumerable); - - ElementType = converter.ElementType; - ElementTypeInfo = elementInfo ?? throw new ArgumentNullException(nameof(elementInfo)); - NumberHandling = numberHandling; - PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options); - Serialize = serializeFunc; - CreateObjectWithArgs = createObjectWithArgs; - AddMethodDelegate = addFunc; - SetCreateObjectFunc(createObjectFunc); - } + if (collectionInfo == null) + { + throw new ArgumentNullException(nameof(collectionInfo)); + } - /// - /// Creates serialization metadata for a . - /// - public JsonTypeInfoInternal( - JsonSerializerOptions options, - Func? createObjectFunc, - Func> converterCreator, - JsonTypeInfo? keyInfo, - JsonTypeInfo? valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, - Type keyType, - Type elementType, - object? createObjectWithArgs = null) - : base(typeof(T), options, ConverterStrategy.Dictionary) - { - JsonConverter converter = new JsonMetadataServicesConverter(converterCreator, ConverterStrategy.Dictionary); + ConverterStrategy strategy = collectionInfo.KeyInfo == null ? ConverterStrategy.Enumerable : ConverterStrategy.Dictionary; + JsonConverter converter = new JsonMetadataServicesConverter(converterCreator, strategy); KeyType = converter.KeyType; ElementType = converter.ElementType; - KeyTypeInfo = keyInfo ?? throw new ArgumentNullException(nameof(keyInfo)); - ElementType = converter.ElementType; - ElementTypeInfo = valueInfo ?? throw new ArgumentNullException(nameof(valueInfo)); - NumberHandling = numberHandling; + KeyTypeInfo = collectionInfo.KeyInfo; + ElementTypeInfo = collectionInfo.ElementInfo ?? throw new ArgumentNullException(nameof(collectionInfo.ElementInfo)); + NumberHandling = collectionInfo.NumberHandling; PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options); - Serialize = serializeFunc; + SerializeHandler = collectionInfo.SerializeHandler; CreateObjectWithArgs = createObjectWithArgs; - SetCreateObjectFunc(createObjectFunc); + AddMethodDelegate = addFunc; + SetCreateObjectFunc(collectionInfo.ObjectCreator); } private void SetCreateObjectFunc(Func? createObjectFunc) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs index 337fd7cf1a3ca9..e09f840c2c0f50 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs @@ -15,8 +15,8 @@ public abstract class JsonTypeInfo : JsonTypeInfo { private Action? _serialize; - internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy) : - base(type, options, converterStrategy) + internal JsonTypeInfo(Type type, JsonSerializerOptions options) : + base(type, options, dummy: false) { } internal JsonTypeInfo() @@ -25,10 +25,11 @@ internal JsonTypeInfo() } /// - /// A method that serializes an instance of using + /// Serializes an instance of using /// values specified at design time. /// - public Action? Serialize + /// The writer is not flushed after writing. + public Action? SerializeHandler { get { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs index 7312f6f07df499..479cbe4abcca6d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs @@ -40,6 +40,12 @@ internal struct WriteStack /// public CancellationToken CancellationToken; + /// + /// In the case of async serialization, used by resumable converters to signal that + /// the current buffer contents should not be flushed to the underlying stream. + /// + public bool SuppressFlush; + /// /// Stores a pending task that a resumable converter depends on to continue work. /// It must be awaited by the root context before serialization is resumed. @@ -341,7 +347,7 @@ public string PropertyPath() static void AppendStackFrame(StringBuilder sb, ref WriteStackFrame frame) { // Append the property name. - string? propertyName = frame.DeclaredJsonPropertyInfo?.MemberInfo?.Name; + string? propertyName = frame.DeclaredJsonPropertyInfo?.ClrName; if (propertyName == null) { // Attempt to get the JSON property name from the property name specified in re-entry. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index 9de23e8d011a9e..a75f5eaa484067 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -215,9 +215,9 @@ public static void ThrowInvalidOperationException_ConstructorParameterIncomplete [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(MemberInfo memberInfo, Type classType) + public static void ThrowInvalidOperationException_ExtensionDataCannotBindToCtorParam(JsonPropertyInfo jsonPropertyInfo) { - throw new InvalidOperationException(SR.Format(SR.ExtensionDataCannotBindToCtorParam, memberInfo, classType)); + throw new InvalidOperationException(SR.Format(SR.ExtensionDataCannotBindToCtorParam, jsonPropertyInfo.ClrName, jsonPropertyInfo.DeclaringType)); } [DoesNotReturn] diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs index f8a46a31468ca9..bf16e32e9f8d57 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Double.cs @@ -109,9 +109,7 @@ private static bool TryFormatDouble(double value, Span destination, out in #if BUILDING_INBOX_LIBRARY return Utf8Formatter.TryFormat(value, destination, out bytesWritten); #else - const string FormatString = "G17"; - - string utf16Text = value.ToString(FormatString, CultureInfo.InvariantCulture); + string utf16Text = value.ToString(JsonConstants.DoubleFormatString, CultureInfo.InvariantCulture); // Copy the value to the destination, if it's large enough. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs index 2f046d872f6972..067971e86b5af4 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Float.cs @@ -109,9 +109,7 @@ private static bool TryFormatSingle(float value, Span destination, out int #if BUILDING_INBOX_LIBRARY return Utf8Formatter.TryFormat(value, destination, out bytesWritten); #else - const string FormatString = "G9"; - - string utf16Text = value.ToString(FormatString, CultureInfo.InvariantCulture); + string utf16Text = value.ToString(JsonConstants.SingleFormatString, CultureInfo.InvariantCulture); // Copy the value to the destination, if it's large enough. diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs index ba855bd5f6bbf6..ac2999d72e3159 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs @@ -252,6 +252,24 @@ static async IAsyncEnumerable GetNumbersAsync() } } + [Fact] + public async Task RegressionTest_ExceptionOnFirstMoveNextShouldNotFlushBuffer() + { + // Regression test for https://github.com/dotnet/aspnetcore/issues/36977 + using var stream = new MemoryStream(); + await Assert.ThrowsAsync(async () => await JsonSerializer.SerializeAsync(stream, new { Data = GetFailingAsyncEnumerable() })); + Assert.Equal(0, stream.Length); + + static async IAsyncEnumerable GetFailingAsyncEnumerable() + { + await Task.Yield(); + throw new NotImplementedException(); +#pragma warning disable CS0162 // Unreachable code detected + yield break; +#pragma warning restore CS0162 // Unreachable code detected + } + } + public class MockedAsyncEnumerable : IAsyncEnumerable, IEnumerable { private readonly IEnumerable _source; diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs index 177b42fae56e6e..2c2ee556fbb991 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs @@ -665,23 +665,26 @@ static void ValidateException(NotSupportedException ex) public class CustomInt32ConverterSerializerContext : JsonSerializerContext { - public CustomInt32ConverterSerializerContext() : base(null, null) { } + public CustomInt32ConverterSerializerContext() : base(null) { } public override JsonTypeInfo? GetTypeInfo(Type _) => throw new NotImplementedException(); public JsonTypeInfo> DictionaryInt32String => _dictionaryInt32String ??= CreateDictionaryConverter(); private JsonTypeInfo>? _dictionaryInt32String; + protected override JsonSerializerOptions? GeneratedSerializerOptions => null; + private JsonTypeInfo> CreateDictionaryConverter() { JsonTypeInfo keyInfo = JsonMetadataServices.CreateValueInfo(Options, new ConverterForInt32()); JsonTypeInfo valueInfo = JsonMetadataServices.CreateValueInfo(Options, JsonMetadataServices.StringConverter); - return JsonMetadataServices.CreateDictionaryInfo, int, string>( - Options, - createObjectFunc: () => new(), - keyInfo, valueInfo, - numberHandling: default, - serializeFunc: null - ); + JsonCollectionInfoValues> info = new() + { + ObjectCreator = () => new(), + KeyInfo = keyInfo, + ElementInfo = valueInfo, + }; + + return JsonMetadataServices.CreateDictionaryInfo, int, string>(Options, info); } } diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs index e2275bc7ff7f8f..63c5398f901429 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs @@ -11,9 +11,6 @@ public abstract partial class ConstructorTests { [Fact] [OuterLoop] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task MultipleThreadsLooping() { const int Iterations = 100; @@ -25,13 +22,10 @@ public async Task MultipleThreadsLooping() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task MultipleThreads() { // Verify the test class has >32 properties since that is a threshold for using the fallback dictionary. - Assert.True(typeof(ClassWithConstructor_SimpleAndComplexParameters).GetProperties(BindingFlags.Instance | BindingFlags.Public).Length > 32); + Assert.True(typeof(ObjWCtorMixedParams).GetProperties(BindingFlags.Instance | BindingFlags.Public).Length > 32); async Task DeserializeObjectAsync(string json, Type type, JsonSerializerOptions options) { @@ -60,7 +54,7 @@ async Task DeserializeObjectNormalAsync(Type type, JsonSerializerOptions options async Task SerializeObject(Type type, JsonSerializerOptions options) { - var obj = ClassWithConstructor_SimpleAndComplexParameters.GetInstance(); + var obj = ObjWCtorMixedParams.GetInstance(); await JsonSerializerWrapperForString.SerializeWrapper(obj, options); }; @@ -87,7 +81,7 @@ async Task RunTestAsync(Type type) await Task.WhenAll(tasks); } - await RunTestAsync(typeof(ClassWithConstructor_SimpleAndComplexParameters)); + await RunTestAsync(typeof(ObjWCtorMixedParams)); await RunTestAsync(typeof(Person_Class)); await RunTestAsync(typeof(Parameterized_Class_With_ComplexTuple)); } @@ -99,13 +93,13 @@ public async Task PropertyCacheWithMinInputsFirst() var options = new JsonSerializerOptions(); string json = "{}"; - await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + await JsonSerializerWrapperForString.DeserializeWrapper(json, options); - ClassWithConstructor_SimpleAndComplexParameters testObj = ClassWithConstructor_SimpleAndComplexParameters.GetInstance(); + ObjWCtorMixedParams testObj = ObjWCtorMixedParams.GetInstance(); testObj.Verify(); json = await JsonSerializerWrapperForString.SerializeWrapper(testObj, options); - testObj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + testObj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); testObj.Verify(); } @@ -115,15 +109,15 @@ public async Task PropertyCacheWithMinInputsLast() // Use local options to avoid obtaining already cached metadata from the default options. var options = new JsonSerializerOptions(); - ClassWithConstructor_SimpleAndComplexParameters testObj = ClassWithConstructor_SimpleAndComplexParameters.GetInstance(); + ObjWCtorMixedParams testObj = ObjWCtorMixedParams.GetInstance(); testObj.Verify(); string json = await JsonSerializerWrapperForString.SerializeWrapper(testObj, options); - testObj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + testObj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); testObj.Verify(); json = "{}"; - await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + await JsonSerializerWrapperForString.DeserializeWrapper(json, options); } // Use a common options instance to encourage additional metadata collisions across types. Also since @@ -132,9 +126,6 @@ public async Task PropertyCacheWithMinInputsLast() [Fact] [SkipOnCoreClr("https://github.com/dotnet/runtime/issues/45464", RuntimeConfiguration.Checked)] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task MultipleTypes() { async Task Serialize(object[] args) diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs index f34687d65bd59c..679ddca2a04c80 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Exceptions.cs @@ -114,14 +114,11 @@ public async Task RandomReferenceMetadataNotSupported() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task ExtensionDataProperty_CannotBindTo_CtorParam() { InvalidOperationException ex = await Assert.ThrowsAsync(() => JsonSerializerWrapperForString.DeserializeWrapper("{}")); - string exStr = ex.ToString(); // System.InvalidOperationException: 'The extension data property 'System.Collections.Generic.Dictionary`2[System.String,System.Text.Json.JsonElement] ExtensionData' on type 'System.Text.Json.Serialization.Tests.ConstructorTests+Class_ExtData_CtorParam' cannot bind with a parameter in constructor 'Void .ctor(System.Collections.Generic.Dictionary`2[System.String,System.Text.Json.JsonElement])'.' - Assert.Contains("System.Collections.Generic.Dictionary`2[System.String,System.Text.Json.JsonElement] ExtensionData", exStr); + string exStr = ex.ToString(); // System.InvalidOperationException: 'The extension data property 'ExtensionData' on type 'System.Text.Json.Serialization.Tests.ConstructorTests+Class_ExtData_CtorParam' cannot bind with a parameter in the deserialization constructor.' + Assert.Contains("ExtensionData", exStr); Assert.Contains("System.Text.Json.Serialization.Tests.ConstructorTests+Class_ExtData_CtorParam", exStr); } @@ -204,6 +201,7 @@ public async Task PathForChildListFails() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/39055 (already fixed in main)")] public async Task PathForChildDictionaryFails() { JsonException e = await Assert.ThrowsAsync(() => JsonSerializerWrapperForString.DeserializeWrapper(@"{""Child"":{""MyDictionary"":{""Key"": bad]")); @@ -273,21 +271,21 @@ public async Task CaseInsensitiveFails() // Baseline (no exception) { - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""mydecimal"":1}", options); + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""mydecimal"":1}", options); Assert.Equal(1, obj.MyDecimal); } { - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MYDECIMAL"":1}", options); + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MYDECIMAL"":1}", options); Assert.Equal(1, obj.MyDecimal); } JsonException e; - e = await Assert.ThrowsAsync(() => JsonSerializerWrapperForString.DeserializeWrapper(@"{""mydecimal"":bad}", options)); + e = await Assert.ThrowsAsync(() => JsonSerializerWrapperForString.DeserializeWrapper(@"{""mydecimal"":bad}", options)); Assert.Equal("$.mydecimal", e.Path); - e = await Assert.ThrowsAsync(() => JsonSerializerWrapperForString.DeserializeWrapper(@"{""MYDECIMAL"":bad}", options)); + e = await Assert.ThrowsAsync(() => JsonSerializerWrapperForString.DeserializeWrapper(@"{""MYDECIMAL"":bad}", options)); Assert.Equal("$.MYDECIMAL", e.Path); } diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs index 5f2da8c2caa8cd..d56a64a3e65c89 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Threading.Tasks; using Xunit; @@ -291,9 +292,6 @@ public async Task Null_AsArgument_To_ParameterThat_CanNotBeNull() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task OtherPropertiesAreSet() { var personClass = await JsonSerializerWrapperForString.DeserializeWrapper(Person_Class.s_json); @@ -312,9 +310,6 @@ public async Task ExtraProperties_AreIgnored() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task ExtraProperties_GoInExtensionData_IfPresent() { Point_2D_With_ExtData point = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""X"":1,""y"":2,""b"":3}"); @@ -368,7 +363,7 @@ public async Task IgnoreNullValues_DontSetNull_ToConstructorArguments_ThatCantBe [Fact] public async Task NumerousSimpleAndComplexParameters() { - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(ClassWithConstructor_SimpleAndComplexParameters.s_json); + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(ObjWCtorMixedParams.s_json); obj.Verify(); } @@ -565,7 +560,7 @@ public async Task TupleDeserialization_DefaultValuesUsed_WhenJsonMissing() #endif public async Task TupleDeserializationWorks_ClassWithParameterizedCtor() { - string classJson = ClassWithConstructor_SimpleAndComplexParameters.s_json; + string classJson = ObjWCtorMixedParams.s_json; StringBuilder sb = new StringBuilder(); sb.Append("{"); @@ -579,13 +574,13 @@ public async Task TupleDeserializationWorks_ClassWithParameterizedCtor() string complexTupleJson = sb.ToString(); var complexTuple = await JsonSerializerWrapperForString.DeserializeWrapper>(complexTupleJson); + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams>>(complexTupleJson); complexTuple.Item1.Verify(); complexTuple.Item2.Verify(); @@ -793,9 +788,6 @@ public async Task LastParameterWins() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task LastParameterWins_DoesNotGoToExtensionData() { string json = @"{ @@ -823,9 +815,6 @@ public async Task BitVector32_UsesStructDefaultCtor_MultipleParameterizedCtor() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task HonorExtensionDataGeneric() { var obj1 = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""key"": ""value""}"); @@ -1228,5 +1217,248 @@ public class TypeWithUri public TypeWithUri(Uri myUri = default) => MyUri = myUri; } + + [Fact] + public async Task SmallObject_ClrDefaultParamValueUsed_WhenMatchingPropIgnored() + { + string json = @"{""Prop"":20}"; + var obj1 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj1.Prop); + + var obj2 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj2.Prop); + } + + public class SmallType_IgnoredProp_Bind_ParamWithDefaultValue + { + [JsonIgnore] + public int Prop { get; set; } + + public SmallType_IgnoredProp_Bind_ParamWithDefaultValue(int prop = 5) + => Prop = prop; + } + + public class SmallType_IgnoredProp_Bind_Param + { + [JsonIgnore] + public int Prop { get; set; } + + public SmallType_IgnoredProp_Bind_Param(int prop) + => Prop = prop; + } + + [Fact] + public async Task LargeObject_ClrDefaultParamValueUsed_WhenMatchingPropIgnored() + { + string json = @"{""Prop"":20}"; + var obj1 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj1.Prop); + + var obj2 = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(0, obj2.Prop); + } + + public class LargeType_IgnoredProp_Bind_ParamWithDefaultValue + { + public int W { get; set; } + + public int X { get; set; } + + public int Y { get; set; } + + public int Z { get; set; } + + [JsonIgnore] + public int Prop { get; set; } + + public LargeType_IgnoredProp_Bind_ParamWithDefaultValue(int w, int x, int y, int z, int prop = 5) + => Prop = prop; + } + + public class LargeType_IgnoredProp_Bind_Param + { + public int W { get; set; } + + public int X { get; set; } + + public int Y { get; set; } + + public int Z { get; set; } + + [JsonIgnore] + public int Prop { get; set; } + + public LargeType_IgnoredProp_Bind_Param(int w, int x, int y, int z, int prop) + => Prop = prop; + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/34779")] + public async Task BindingBetweenRefProps() + { + string json = @"{""NameRef"":""John""}"; + await JsonSerializerWrapperForString.DeserializeWrapper(json); + } + + public class TypeWith_RefStringProp_ParamCtor + { + private string _name; + + public ref string NameRef => ref _name; + + public TypeWith_RefStringProp_ParamCtor(ref string nameRef) => _name = nameRef; + } + + [Fact] + public async Task BindToIgnoredPropOfSameType() + { + string json = @"{""Prop"":{}}"; + Assert.NotNull(await JsonSerializerWrapperForString.DeserializeWrapper(json)); + } + + public class ClassWithIgnoredSameType + { + [JsonIgnore] + public ClassWithIgnoredSameType Prop { get; } + + public ClassWithIgnoredSameType(ClassWithIgnoredSameType prop) { } + } + + public async Task TestClassWithDefaultCtorParams() + { + ClassWithDefaultCtorParams obj = new ClassWithDefaultCtorParams( + new Point_2D_Struct_WithAttribute(1, 2), + DayOfWeek.Sunday, + (DayOfWeek)(-2), + (DayOfWeek)19, + BindingFlags.CreateInstance | BindingFlags.FlattenHierarchy, + SampleEnumUInt32.MinZero, + "Hello world!", + null, + "xzy", + 'c', + ' ', + 23, + 4, + -40, + double.Epsilon, + 23, + 4, + -40, + float.MinValue, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10); + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + JsonTestHelper.AssertJsonEqual(json, await JsonSerializerWrapperForString.SerializeWrapper(obj)); + } + + public class ClassWithDefaultCtorParams + { + public Point_2D_Struct_WithAttribute Struct { get; } + public DayOfWeek Enum1 { get; } + public DayOfWeek Enum2 { get; } + public DayOfWeek Enum3 { get; } + public BindingFlags Enum4 { get; } + public SampleEnumUInt32 Enum5 { get; } + public string Str1 { get; } + public string Str2 { get; } + public string Str3 { get; } + public char Char1 { get; } + public char Char2 { get; } + public double Double1 { get; } + public double Double2 { get; } + public double Double3 { get; } + public double Double4 { get; } + public double Double5 { get; } + public float Float1 { get; } + public float Float2 { get; } + public float Float3 { get; } + public float Float4 { get; } + public float Float5 { get; } + public byte Byte { get; } + public decimal Decimal1 { get; } + public decimal Decimal2 { get; } + public short Short { get; } + public sbyte Sbyte { get; } + public int Int { get; } + public long Long { get; } + public ushort UShort { get; } + public uint UInt { get; } + public ulong ULong { get; } + + public ClassWithDefaultCtorParams( + Point_2D_Struct_WithAttribute @struct = default, + DayOfWeek enum1 = default, + DayOfWeek enum2 = DayOfWeek.Sunday, + DayOfWeek enum3 = DayOfWeek.Sunday | DayOfWeek.Monday, + BindingFlags enum4 = BindingFlags.CreateInstance | BindingFlags.ExactBinding, + SampleEnumUInt32 enum5 = SampleEnumUInt32.MinZero, + string str1 = "abc", + string str2 = "", + string str3 = "\n\r⁉️\'\"\u200D\f\t\v\0\a\b\\\'\"", + char char1 = 'a', + char char2 = '\u200D', + double double1 = double.NegativeInfinity, + double double2 = double.PositiveInfinity, + double double3 = double.NaN, + double double4 = double.MaxValue, + double double5 = double.Epsilon, + float float1 = float.NegativeInfinity, + float float2 = float.PositiveInfinity, + float float3 = float.NaN, + float float4 = float.MinValue, + float float5 = float.Epsilon, + byte @byte = byte.MinValue, + decimal @decimal1 = decimal.MinValue, + decimal @decimal2 = decimal.MaxValue, + short @short = short.MinValue, + sbyte @sbyte = sbyte.MaxValue, + int @int = int.MinValue, + long @long = long.MaxValue, + ushort @ushort = ushort.MinValue, + uint @uint = uint.MaxValue, + ulong @ulong = ulong.MinValue) + { + Struct = @struct; + Enum1 = enum1; + Enum2 = enum2; + Enum3 = enum3; + Enum4 = enum4; + Enum5 = enum5; + Str1 = str1; + Str2 = str2; + Str3 = str3; + Char1 = char1; + Char2 = char2; + Double1 = double1; + Double2 = double2; + Double3 = double3; + Double4 = double4; + Float1 = float1; + Float2 = float2; + Float3 = float3; + Float4 = float4; + Byte = @byte; + Decimal1 = @decimal1; + Decimal2 = @decimal2; + Short = @short; + Sbyte = @sbyte; + Int = @int; + Long = @long; + UShort = @ushort; + UInt = @uint; + ULong = @ulong; + } + } } } diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Stream.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Stream.cs index ac5cd60933bf9f..92b3b480506df0 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Stream.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Stream.cs @@ -12,9 +12,6 @@ public abstract partial class ConstructorTests { [Fact] [SkipOnCoreClr("https://github.com/dotnet/runtime/issues/45464", RuntimeConfiguration.Checked)] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task ReadSimpleObjectAsync() { async Task RunTestAsync(byte[] testData) @@ -37,7 +34,7 @@ async Task RunTestAsync(byte[] testData) // Simple models can be deserialized. tasks[0] = Task.Run(async () => await RunTestAsync(Parameterized_IndexViewModel_Immutable.s_data)); // Complex models can be deserialized. - tasks[1] = Task.Run(async () => await RunTestAsync(ClassWithConstructor_SimpleAndComplexParameters.s_data)); + tasks[1] = Task.Run(async () => await RunTestAsync(ObjWCtorMixedParams.s_data)); tasks[2] = Task.Run(async () => await RunTestAsync(Parameterized_Class_With_ComplexTuple.s_data)); // JSON that doesn't bind to ctor args are matched with properties or ignored (as appropriate). tasks[3] = Task.Run(async () => await RunTestAsync(Person_Class.s_data)); @@ -62,9 +59,6 @@ async Task RunTestAsync(byte[] testData) } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task ReadSimpleObjectWithTrailingTriviaAsync() { async Task RunTestAsync(string testData) @@ -89,7 +83,7 @@ async Task RunTestAsync(string testData) // Simple models can be deserialized. tasks[0] = Task.Run(async () => await RunTestAsync(Parameterized_IndexViewModel_Immutable.s_json)); // Complex models can be deserialized. - tasks[1] = Task.Run(async () => await RunTestAsync(ClassWithConstructor_SimpleAndComplexParameters.s_json)); + tasks[1] = Task.Run(async () => await RunTestAsync(ObjWCtorMixedParams.s_json)); tasks[2] = Task.Run(async () => await RunTestAsync(Parameterized_Class_With_ComplexTuple.s_json)); // JSON that doesn't bind to ctor args are matched with properties or ignored (as appropriate). tasks[3] = Task.Run(async () => await RunTestAsync(Person_Class.s_json)); @@ -157,9 +151,6 @@ async Task RunTestAsync() } [Fact] -#if BUILDING_SOURCE_GENERATOR_TESTS - [ActiveIssue("Needs JsonExtensionData support.")] -#endif public async Task ExerciseStreamCodePaths() { static string GetPropertyName(int index) => diff --git a/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs new file mode 100644 index 00000000000000..efa6bfb7e121ff --- /dev/null +++ b/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs @@ -0,0 +1,1466 @@ +// 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.Collections.Immutable; +using System.Linq; +using System.Reflection; +using System.Text.Encodings.Web; +using System.Text.Json.Nodes; +using System.Threading.Tasks; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public abstract class ExtensionDataTests : SerializerTests + { + public ExtensionDataTests(JsonSerializerWrapperForString serializerWrapper) : base(serializerWrapper, null) { } + + [Fact] + public async Task EmptyPropertyName_WinsOver_ExtensionDataEmptyPropertyName() + { + string json = @"{"""":1}"; + + ClassWithEmptyPropertyNameAndExtensionProperty obj; + + // Create a new options instances to re-set any caches. + JsonSerializerOptions options = new JsonSerializerOptions(); + + // Verify the real property wins over the extension data property. + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal(1, obj.MyInt1); + Assert.Null(obj.MyOverflow); + } + + [Fact] + public async Task EmptyPropertyNameInExtensionData() + { + { + string json = @"{"""":42}"; + EmptyClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(42, obj.MyOverflow[""].GetInt32()); + } + + { + // Verify that last-in wins. + string json = @"{"""":42, """":43}"; + EmptyClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(43, obj.MyOverflow[""].GetInt32()); + } + } + + [Fact] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("Needs SimpleTestClass support.")] +#endif + public async Task ExtensionPropertyNotUsed() + { + string json = @"{""MyNestedClass"":" + SimpleTestClass.s_json + "}"; + ClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Null(obj.MyOverflow); + } + + [Fact] + public async Task ExtensionPropertyRoundTrip() + { + ClassWithExtensionProperty obj; + + { + string json = @"{""MyIntMissing"":2, ""MyInt"":1, ""MyNestedClassMissing"":" + SimpleTestClass.s_json + "}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + } + + // Round-trip the json. + { + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + + // The json should not contain the dictionary name. + Assert.DoesNotContain(nameof(ClassWithExtensionProperty.MyOverflow), json); + } + + void Verify() + { + Assert.NotNull(obj.MyOverflow); + Assert.Equal(1, obj.MyInt); + Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); + + JsonProperty[] properties = obj.MyOverflow["MyNestedClassMissing"].EnumerateObject().ToArray(); + + // Verify a couple properties + Assert.Equal(1, properties.Where(prop => prop.Name == "MyInt16").First().Value.GetInt32()); + Assert.True(properties.Where(prop => prop.Name == "MyBooleanTrue").First().Value.GetBoolean()); + } + } + + [Fact] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("Needs SimpleTestClass support.")] +#endif + public async Task ExtensionFieldNotUsed() + { + string json = @"{""MyNestedClass"":" + SimpleTestClass.s_json + "}"; + ClassWithExtensionField obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Null(obj.MyOverflow); + } + + [Fact] + public async Task ExtensionFieldRoundTrip() + { + ClassWithExtensionField obj; + + { + string json = @"{""MyIntMissing"":2, ""MyInt"":1, ""MyNestedClassMissing"":" + SimpleTestClass.s_json + "}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + } + + // Round-trip the json. + { + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + + // The json should not contain the dictionary name. + Assert.DoesNotContain(nameof(ClassWithExtensionField.MyOverflow), json); + } + + void Verify() + { + Assert.NotNull(obj.MyOverflow); + Assert.Equal(1, obj.MyInt); + Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); + + JsonProperty[] properties = obj.MyOverflow["MyNestedClassMissing"].EnumerateObject().ToArray(); + + // Verify a couple properties + Assert.Equal(1, properties.Where(prop => prop.Name == "MyInt16").First().Value.GetInt32()); + Assert.True(properties.Where(prop => prop.Name == "MyBooleanTrue").First().Value.GetBoolean()); + } + } + + [Fact] + public async Task ExtensionPropertyIgnoredWhenWritingDefault() + { + string expected = @"{}"; + string actual = await JsonSerializerWrapperForString.SerializeWrapper(new ClassWithExtensionPropertyAsObject()); + Assert.Equal(expected, actual); + } + + [Fact] + public async Task MultipleExtensionPropertyIgnoredWhenWritingDefault() + { + var obj = new ClassWithMultipleDictionaries(); + string actual = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal("{\"ActualDictionary\":null}", actual); + + obj = new ClassWithMultipleDictionaries + { + ActualDictionary = new Dictionary() + }; + actual = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal("{\"ActualDictionary\":{}}", actual); + + obj = new ClassWithMultipleDictionaries + { + MyOverflow = new Dictionary + { + { "test", "value" } + } + }; + actual = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal("{\"ActualDictionary\":null,\"test\":\"value\"}", actual); + + obj = new ClassWithMultipleDictionaries + { + ActualDictionary = new Dictionary(), + MyOverflow = new Dictionary + { + { "test", "value" } + } + }; + actual = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal("{\"ActualDictionary\":{},\"test\":\"value\"}", actual); + } + + [Fact] + public async Task ExtensionPropertyInvalidJsonFail() + { + const string BadJson = @"{""Good"":""OK"",""Bad"":!}"; + + JsonException jsonException = await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(BadJson)); + Assert.Contains("Path: $.Bad | LineNumber: 0 | BytePositionInLine: 19.", jsonException.ToString()); + Assert.NotNull(jsonException.InnerException); + Assert.IsAssignableFrom(jsonException.InnerException); + Assert.Contains("!", jsonException.InnerException.ToString()); + } + + [Fact] + public async Task ExtensionPropertyAlreadyInstantiated() + { + Assert.NotNull(new ClassWithExtensionPropertyAlreadyInstantiated().MyOverflow); + + string json = @"{""MyIntMissing"":2}"; + + ClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); + } + + [Fact] + public async Task ExtensionPropertyAsObject() + { + string json = @"{""MyIntMissing"":2}"; + + ClassWithExtensionPropertyAsObject obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.IsType(obj.MyOverflow["MyIntMissing"]); + Assert.Equal(2, ((JsonElement)obj.MyOverflow["MyIntMissing"]).GetInt32()); + } + + [Fact] + public async Task ExtensionPropertyCamelCasing() + { + // Currently we apply no naming policy. If we do (such as a ExtensionPropertyNamingPolicy), we'd also have to add functionality to the JsonDocument. + + ClassWithExtensionProperty obj; + const string jsonWithProperty = @"{""MyIntMissing"":1}"; + const string jsonWithPropertyCamelCased = @"{""myIntMissing"":1}"; + + { + // Baseline Pascal-cased json + no casing option. + obj = await JsonSerializerWrapperForString.DeserializeWrapper(jsonWithProperty); + Assert.Equal(1, obj.MyOverflow["MyIntMissing"].GetInt32()); + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""MyIntMissing"":1", json); + } + + { + // Pascal-cased json + camel casing option. + JsonSerializerOptions options = new JsonSerializerOptions(); + options.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(jsonWithProperty, options); + Assert.Equal(1, obj.MyOverflow["MyIntMissing"].GetInt32()); + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Contains(@"""MyIntMissing"":1", json); + } + + { + // Baseline camel-cased json + no casing option. + obj = await JsonSerializerWrapperForString.DeserializeWrapper(jsonWithPropertyCamelCased); + Assert.Equal(1, obj.MyOverflow["myIntMissing"].GetInt32()); + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""myIntMissing"":1", json); + } + + { + // Baseline camel-cased json + camel casing option. + JsonSerializerOptions options = new JsonSerializerOptions(); + options.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(jsonWithPropertyCamelCased, options); + Assert.Equal(1, obj.MyOverflow["myIntMissing"].GetInt32()); + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Contains(@"""myIntMissing"":1", json); + } + } + + [Fact] + public async Task NullValuesIgnored() + { + const string json = @"{""MyNestedClass"":null}"; + const string jsonMissing = @"{""MyNestedClassMissing"":null}"; + + { + // Baseline with no missing. + ClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Null(obj.MyOverflow); + + string outJson = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""MyNestedClass"":null", outJson); + } + + { + // Baseline with missing. + ClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(jsonMissing); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(JsonValueKind.Null, obj.MyOverflow["MyNestedClassMissing"].ValueKind); + } + + { + JsonSerializerOptions options = new JsonSerializerOptions(); + options.IgnoreNullValues = true; + + ClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(jsonMissing, options); + + // Currently we do not ignore nulls in the extension data. The JsonDocument would also need to support this mode + // for any lower-level nulls. + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(JsonValueKind.Null, obj.MyOverflow["MyNestedClassMissing"].ValueKind); + } + } + + public class ClassWithInvalidExtensionProperty + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public class ClassWithTwoExtensionProperties + { + [JsonExtensionData] + public Dictionary MyOverflow1 { get; set; } + + [JsonExtensionData] + public Dictionary MyOverflow2 { get; set; } + } + + [Fact] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("https://github.com/dotnet/runtime/issues/58945")] +#endif + public async Task InvalidExtensionPropertyFail() + { + // Baseline + await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(@"{}")); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(@"{}")); + } + + public class ClassWithIgnoredData + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + + [JsonIgnore] + public int MyInt { get; set; } + } + + [Fact] + public async Task IgnoredDataShouldNotBeExtensionData() + { + ClassWithIgnoredData obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MyInt"":1}"); + + Assert.Equal(0, obj.MyInt); + Assert.Null(obj.MyOverflow); + } + + public class ClassWithExtensionData + { + [JsonExtensionData] + public T Overflow { get; set; } + } + + public class CustomOverflowDictionary : Dictionary + { + } + + public class DictionaryOverflowConverter : JsonConverter> + { + public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) + { + writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); + } + } + + public class JsonElementOverflowConverter : JsonConverter> + { + public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) + { + writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); + } + } + + public class JsonObjectOverflowConverter : JsonConverter + { + public override JsonObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, JsonObject value, JsonSerializerOptions options) + { + writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); + } + } + + public class CustomObjectDictionaryOverflowConverter : JsonConverter> + { + public override CustomOverflowDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, CustomOverflowDictionary value, JsonSerializerOptions options) + { + writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); + } + } + + public class CustomJsonElementDictionaryOverflowConverter : JsonConverter> + { + public override CustomOverflowDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + throw new NotImplementedException(); + } + + public override void Write(Utf8JsonWriter writer, CustomOverflowDictionary value, JsonSerializerOptions options) + { + writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); + } + } + + [Theory] + [InlineData(typeof(Dictionary), typeof(DictionaryOverflowConverter))] + [InlineData(typeof(Dictionary), typeof(JsonElementOverflowConverter))] + [InlineData(typeof(CustomOverflowDictionary), typeof(CustomObjectDictionaryOverflowConverter))] + [InlineData(typeof(CustomOverflowDictionary), typeof(CustomJsonElementDictionaryOverflowConverter))] + public void ExtensionProperty_SupportsWritingToCustomSerializerWithOptions(Type overflowType, Type converterType) + { + typeof(ExtensionDataTests) + .GetMethod(nameof(ExtensionProperty_SupportsWritingToCustomSerializerWithOptionsInternal), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod(overflowType, converterType) + .Invoke(null, null); + } + + private static void ExtensionProperty_SupportsWritingToCustomSerializerWithOptionsInternal() + where TDictionary : new() + where TConverter : JsonConverter, new() + { + var root = new ClassWithExtensionData() + { + Overflow = new TDictionary() + }; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new TConverter()); + + string json = JsonSerializer.Serialize(root, options); + Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); + } + + private interface IClassWithOverflow + { + public T Overflow { get; set; } + } + + public class ClassWithExtensionDataWithAttributedConverter : IClassWithOverflow> + { + [JsonExtensionData] + [JsonConverter(typeof(DictionaryOverflowConverter))] + public Dictionary Overflow { get; set; } + } + + public class ClassWithJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow> + { + [JsonExtensionData] + [JsonConverter(typeof(JsonElementOverflowConverter))] + public Dictionary Overflow { get; set; } + } + + public class ClassWithCustomElementExtensionDataWithAttributedConverter : IClassWithOverflow> + { + [JsonExtensionData] + [JsonConverter(typeof(CustomObjectDictionaryOverflowConverter))] + public CustomOverflowDictionary Overflow { get; set; } + } + + public class ClassWithCustomJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow> + { + [JsonExtensionData] + [JsonConverter(typeof(CustomJsonElementDictionaryOverflowConverter))] + public CustomOverflowDictionary Overflow { get; set; } + } + + [Theory] + [InlineData(typeof(ClassWithExtensionDataWithAttributedConverter), typeof(Dictionary))] + [InlineData(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter), typeof(Dictionary))] + [InlineData(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary))] + [InlineData(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary))] + public void ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverter(Type attributedType, Type dictionaryType) + { + typeof(ExtensionDataTests) + .GetMethod(nameof(ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverterInternal), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod(attributedType, dictionaryType) + .Invoke(null, null); + } + + private static void ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverterInternal() + where TRoot : IClassWithOverflow, new() + where TDictionary : new() + { + var root = new TRoot() + { + Overflow = new TDictionary() + }; + + string json = JsonSerializer.Serialize(root); + Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); + } + + [Theory] + [InlineData(typeof(Dictionary), typeof(DictionaryOverflowConverter), typeof(object))] + [InlineData(typeof(Dictionary), typeof(JsonElementOverflowConverter), typeof(JsonElement))] + [InlineData(typeof(CustomOverflowDictionary), typeof(CustomObjectDictionaryOverflowConverter), typeof(object))] + [InlineData(typeof(CustomOverflowDictionary), typeof(CustomJsonElementDictionaryOverflowConverter), typeof(JsonElement))] + public void ExtensionProperty_IgnoresCustomSerializerWithOptions(Type overflowType, Type converterType, Type elementType) + { + typeof(ExtensionDataTests) + .GetMethod(nameof(ExtensionProperty_IgnoresCustomSerializerWithOptionsInternal), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod(overflowType, elementType, converterType) + .Invoke(null, null); + } + + [Fact] + public async Task ExtensionProperty_IgnoresCustomSerializerWithOptions_JsonObject() + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonObjectOverflowConverter()); + + // A custom converter for JsonObject is not allowed on an extension property. + InvalidOperationException ex = await Assert.ThrowsAsync(async () => + await JsonSerializerWrapperForString.DeserializeWrapper>(@"{""TestKey"":""TestValue""}", options)); + + Assert.Contains("JsonObject", ex.ToString()); + } + + private static void ExtensionProperty_IgnoresCustomSerializerWithOptionsInternal() + where TConverter : JsonConverter, new() + where TDictionary : IDictionary + { + var options = new JsonSerializerOptions(); + options.Converters.Add(new TConverter()); + + ClassWithExtensionData obj + = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}", options); + + Assert.Equal("TestValue", ((JsonElement)(object)obj.Overflow["TestKey"]).GetString()); + } + + [Theory] + [InlineData(typeof(ClassWithExtensionDataWithAttributedConverter), typeof(Dictionary), typeof(object))] + [InlineData(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter), typeof(Dictionary), typeof(JsonElement))] + [InlineData(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary), typeof(object))] + [InlineData(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary), typeof(JsonElement))] + public void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverter(Type attributedType, Type dictionaryType, Type elementType) + { + typeof(ExtensionDataTests) + .GetMethod(nameof(ExtensionProperty_IgnoresCustomSerializerWithExplicitConverterInternal), BindingFlags.Static | BindingFlags.NonPublic) + .MakeGenericMethod(attributedType, dictionaryType, elementType) + .Invoke(null, null); + } + + [Fact] + public async Task ExtensionProperty_IgnoresCustomSerializerWithExplicitConverter_JsonObject() + { + ClassWithExtensionData obj + = await JsonSerializerWrapperForString.DeserializeWrapper>(@"{""TestKey"":""TestValue""}"); + + Assert.Equal("TestValue", obj.Overflow["TestKey"].GetValue()); + } + + private static void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverterInternal() + where TRoot : IClassWithOverflow, new() + where TDictionary : IDictionary + { + ClassWithExtensionData obj + = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}"); + + Assert.Equal("TestValue", ((JsonElement)(object)obj.Overflow["TestKey"]).GetString()); + } + + [Fact] + public async Task ExtensionPropertyObjectValue_Empty() + { + ClassWithExtensionPropertyAlreadyInstantiated obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + Assert.Equal(@"{}", await JsonSerializerWrapperForString.SerializeWrapper(obj)); + } + + [Fact] + public async Task ExtensionPropertyObjectValue_SameAsExtensionPropertyName() + { + const string json = @"{""MyOverflow"":{""Key1"":""V""}}"; + + // Deserializing directly into the overflow is not supported by design. + ClassWithExtensionPropertyAsObject obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + + // The JSON is treated as normal overflow. + Assert.NotNull(obj.MyOverflow["MyOverflow"]); + Assert.Equal(json, await JsonSerializerWrapperForString.SerializeWrapper(obj)); + } + + public class ClassWithExtensionPropertyAsObjectAndNameProperty + { + public string Name { get; set; } + + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public static IEnumerable JsonSerializerOptions() + { + yield return new object[] { null }; + yield return new object[] { new JsonSerializerOptions() }; + yield return new object[] { new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.JsonElement } }; + yield return new object[] { new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode } }; + } + + [Theory] + [MemberData(nameof(JsonSerializerOptions))] + public async Task ExtensionPropertyDuplicateNames(JsonSerializerOptions options) + { + var obj = new ClassWithExtensionPropertyAsObjectAndNameProperty(); + obj.Name = "Name1"; + + obj.MyOverflow = new Dictionary(); + obj.MyOverflow["Name"] = "Name2"; + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Equal(@"{""Name"":""Name1"",""Name"":""Name2""}", json); + + // The overflow value comes last in the JSON so it overwrites the original value. + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal("Name2", obj.Name); + + // Since there was no overflow, this should be null. + Assert.Null(obj.MyOverflow); + } + + [Theory] + [MemberData(nameof(JsonSerializerOptions))] + public async Task Null_SystemObject(JsonSerializerOptions options) + { + const string json = @"{""MissingProperty"":null}"; + + { + ClassWithExtensionPropertyAsObject obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + + // A null value maps to , so the value is null. + object elem = obj.MyOverflow["MissingProperty"]; + Assert.Null(elem); + } + + { + ClassWithExtensionPropertyAsJsonObject obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + + JsonObject jObject = obj.MyOverflow; + JsonNode jNode = jObject["MissingProperty"]; + // Since JsonNode is a reference type the value is null. + Assert.Null(jNode); + } + } + + [Fact] + public async Task Null_JsonElement() + { + const string json = @"{""MissingProperty"":null}"; + + ClassWithExtensionPropertyAsJsonElement obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + object elem = obj.MyOverflow["MissingProperty"]; + // Since JsonElement is a struct, it treats null as JsonValueKind.Null. + Assert.IsType(elem); + Assert.Equal(JsonValueKind.Null, ((JsonElement)elem).ValueKind); + } + + [Fact] + public async Task Null_JsonObject() + { + const string json = @"{""MissingProperty"":null}"; + + ClassWithExtensionPropertyAsJsonObject obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + object elem = obj.MyOverflow["MissingProperty"]; + // Since JsonNode is a reference type the value is null. + Assert.Null(elem); + } + + [Fact] + public async Task ExtensionPropertyObjectValue() + { + // Baseline + ClassWithExtensionPropertyAlreadyInstantiated obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + obj.MyOverflow.Add("test", new object()); + obj.MyOverflow.Add("test1", 1); + + Assert.Equal(@"{""test"":{},""test1"":1}", await JsonSerializerWrapperForString.SerializeWrapper(obj)); + } + + public class DummyObj + { + public string Prop { get; set; } + } + + public struct DummyStruct + { + public string Prop { get; set; } + } + + [Theory] + [MemberData(nameof(JsonSerializerOptions))] + public async Task ExtensionPropertyObjectValue_RoundTrip(JsonSerializerOptions options) + { + // Baseline + ClassWithExtensionPropertyAlreadyInstantiated obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{}", options); + obj.MyOverflow.Add("test", new object()); + obj.MyOverflow.Add("test1", 1); + obj.MyOverflow.Add("test2", "text"); + obj.MyOverflow.Add("test3", new DummyObj() { Prop = "ObjectProp" }); + obj.MyOverflow.Add("test4", new DummyStruct() { Prop = "StructProp" }); + obj.MyOverflow.Add("test5", new Dictionary() { { "Key", "Value" }, { "Key1", "Value1" }, }); + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + ClassWithExtensionPropertyAlreadyInstantiated roundTripObj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + + Assert.Equal(6, roundTripObj.MyOverflow.Count); + + if (options?.UnknownTypeHandling == JsonUnknownTypeHandling.JsonNode) + { + Assert.IsAssignableFrom(roundTripObj.MyOverflow["test"]); + Assert.IsAssignableFrom(roundTripObj.MyOverflow["test1"]); + Assert.IsAssignableFrom(roundTripObj.MyOverflow["test2"]); + Assert.IsAssignableFrom(roundTripObj.MyOverflow["test3"]); + + Assert.IsType(roundTripObj.MyOverflow["test"]); + + Assert.IsAssignableFrom(roundTripObj.MyOverflow["test1"]); + Assert.Equal(1, ((JsonValue)roundTripObj.MyOverflow["test1"]).GetValue()); + Assert.Equal(1, ((JsonValue)roundTripObj.MyOverflow["test1"]).GetValue()); + + Assert.IsAssignableFrom(roundTripObj.MyOverflow["test2"]); + Assert.Equal("text", ((JsonValue)roundTripObj.MyOverflow["test2"]).GetValue()); + + Assert.IsType(roundTripObj.MyOverflow["test3"]); + Assert.Equal("ObjectProp", ((JsonObject)roundTripObj.MyOverflow["test3"])["Prop"].GetValue()); + + Assert.IsType(roundTripObj.MyOverflow["test4"]); + Assert.Equal("StructProp", ((JsonObject)roundTripObj.MyOverflow["test4"])["Prop"].GetValue()); + + Assert.IsType(roundTripObj.MyOverflow["test5"]); + Assert.Equal("Value", ((JsonObject)roundTripObj.MyOverflow["test5"])["Key"].GetValue()); + Assert.Equal("Value1", ((JsonObject)roundTripObj.MyOverflow["test5"])["Key1"].GetValue()); + } + else + { + Assert.IsType(roundTripObj.MyOverflow["test"]); + Assert.IsType(roundTripObj.MyOverflow["test1"]); + Assert.IsType(roundTripObj.MyOverflow["test2"]); + Assert.IsType(roundTripObj.MyOverflow["test3"]); + + Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test"]).ValueKind); + + Assert.Equal(JsonValueKind.Number, ((JsonElement)roundTripObj.MyOverflow["test1"]).ValueKind); + Assert.Equal(1, ((JsonElement)roundTripObj.MyOverflow["test1"]).GetInt32()); + Assert.Equal(1, ((JsonElement)roundTripObj.MyOverflow["test1"]).GetInt64()); + + Assert.Equal(JsonValueKind.String, ((JsonElement)roundTripObj.MyOverflow["test2"]).ValueKind); + Assert.Equal("text", ((JsonElement)roundTripObj.MyOverflow["test2"]).GetString()); + + Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test3"]).ValueKind); + Assert.Equal("ObjectProp", ((JsonElement)roundTripObj.MyOverflow["test3"]).GetProperty("Prop").GetString()); + + Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test4"]).ValueKind); + Assert.Equal("StructProp", ((JsonElement)roundTripObj.MyOverflow["test4"]).GetProperty("Prop").GetString()); + + Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test5"]).ValueKind); + Assert.Equal("Value", ((JsonElement)roundTripObj.MyOverflow["test5"]).GetProperty("Key").GetString()); + Assert.Equal("Value1", ((JsonElement)roundTripObj.MyOverflow["test5"]).GetProperty("Key1").GetString()); + } + } + + [Fact] + public async Task DeserializeIntoJsonObjectProperty() + { + string json = @"{""MyDict"":{""Property1"":1}}"; + ClassWithExtensionPropertyAsJsonObject obj = + await JsonSerializerWrapperForString.DeserializeWrapper(json); + + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(1, obj.MyOverflow["MyDict"]["Property1"].GetValue()); + } + + [Fact] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("https://github.com/dotnet/runtime/issues/58945")] +#endif + + public async Task DeserializeIntoSystemObjectProperty() + { + string json = @"{""MyDict"":{""Property1"":1}}"; + + await Assert.ThrowsAsync(async () => + await JsonSerializerWrapperForString.DeserializeWrapper(json)); + + // Cannot deserialize into System.Object overflow even if UnknownTypeHandling is set to use JsonNode. + var options = new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode }; + await Assert.ThrowsAsync(async () => + await JsonSerializerWrapperForString.DeserializeWrapper(json)); + } + + public class ClassWithReference + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + + public ClassWithExtensionProperty MyReference { get; set; } + } + + [Theory] + [InlineData(@"{""MyIntMissing"":2,""MyReference"":{""MyIntMissingChild"":3}}")] + [InlineData(@"{""MyReference"":{""MyIntMissingChild"":3},""MyIntMissing"":2}")] + [InlineData(@"{""MyReference"":{""MyNestedClass"":null,""MyInt"":0,""MyIntMissingChild"":3},""MyIntMissing"":2}")] + public async Task NestedClass(string json) + { + ClassWithReference obj; + + void Verify() + { + Assert.IsType(obj.MyOverflow["MyIntMissing"]); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); + + ClassWithExtensionProperty child = obj.MyReference; + + Assert.IsType(child.MyOverflow["MyIntMissingChild"]); + Assert.IsType(child.MyOverflow["MyIntMissingChild"]); + Assert.Equal(1, child.MyOverflow.Count); + Assert.Equal(3, child.MyOverflow["MyIntMissingChild"].GetInt32()); + Assert.Null(child.MyNestedClass); + Assert.Equal(0, child.MyInt); + } + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + + // Round-trip the json and verify. + json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + } + + public class ParentClassWithObject + { + public string Text { get; set; } + public ChildClassWithObject Child { get; set; } + + [JsonExtensionData] + public Dictionary ExtensionData { get; set; } = new Dictionary(); + } + + public class ChildClassWithObject + { + public int Number { get; set; } + + [JsonExtensionData] + public Dictionary ExtensionData { get; set; } = new Dictionary(); + } + + [Fact] + public async Task NestedClassWithObjectExtensionDataProperty() + { + var child = new ChildClassWithObject { Number = 2 }; + child.ExtensionData.Add("SpecialInformation", "I am child class"); + + var parent = new ParentClassWithObject { Text = "Hello World" }; + parent.ExtensionData.Add("SpecialInformation", "I am parent class"); + parent.Child = child; + + // The extension data is based on the raw strings added above and not JsonElement. + Assert.Equal("Hello World", parent.Text); + Assert.IsType(parent.ExtensionData["SpecialInformation"]); + Assert.Equal("I am parent class", (string)parent.ExtensionData["SpecialInformation"]); + Assert.Equal(2, parent.Child.Number); + Assert.IsType(parent.Child.ExtensionData["SpecialInformation"]); + Assert.Equal("I am child class", (string)parent.Child.ExtensionData["SpecialInformation"]); + + // Round-trip and verify. Extension data is now based on JsonElement. + string json = await JsonSerializerWrapperForString.SerializeWrapper(parent); + parent = await JsonSerializerWrapperForString.DeserializeWrapper(json); + + Assert.Equal("Hello World", parent.Text); + Assert.IsType(parent.ExtensionData["SpecialInformation"]); + Assert.Equal("I am parent class", ((JsonElement)parent.ExtensionData["SpecialInformation"]).GetString()); + Assert.Equal(2, parent.Child.Number); + Assert.IsType(parent.Child.ExtensionData["SpecialInformation"]); + Assert.Equal("I am child class", ((JsonElement)parent.Child.ExtensionData["SpecialInformation"]).GetString()); + } + + public class ParentClassWithJsonElement + { + public string Text { get; set; } + + public List Children { get; set; } = new List(); + + [JsonExtensionData] + // Use SortedDictionary as verification of supporting derived dictionaries. + public SortedDictionary ExtensionData { get; set; } = new SortedDictionary(); + } + + public class ChildClassWithJsonElement + { + public int Number { get; set; } + + [JsonExtensionData] + public Dictionary ExtensionData { get; set; } = new Dictionary(); + } + + [Fact] + public async Task NestedClassWithJsonElementExtensionDataProperty() + { + var child = new ChildClassWithJsonElement { Number = 4 }; + child.ExtensionData.Add("SpecialInformation", JsonDocument.Parse(await JsonSerializerWrapperForString.SerializeWrapper("I am child class")).RootElement); + + var parent = new ParentClassWithJsonElement { Text = "Hello World" }; + parent.ExtensionData.Add("SpecialInformation", JsonDocument.Parse(await JsonSerializerWrapperForString.SerializeWrapper("I am parent class")).RootElement); + parent.Children.Add(child); + + Verify(); + + // Round-trip and verify. + string json = await JsonSerializerWrapperForString.SerializeWrapper(parent); + parent = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Verify(); + + void Verify() + { + Assert.Equal("Hello World", parent.Text); + Assert.Equal("I am parent class", parent.ExtensionData["SpecialInformation"].GetString()); + Assert.Equal(1, parent.Children.Count); + Assert.Equal(4, parent.Children[0].Number); + Assert.Equal("I am child class", parent.Children[0].ExtensionData["SpecialInformation"].GetString()); + } + } + + [Fact] + public async Task DeserializeIntoObjectProperty() + { + ClassWithExtensionPropertyAsObject obj; + string json; + + // Baseline dictionary. + json = @"{""MyDict"":{""Property1"":1}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(1, ((JsonElement)obj.MyOverflow["MyDict"]).EnumerateObject().First().Value.GetInt32()); + + // Attempt to deserialize directly into the overflow property; this is just added as a normal missing property like MyDict above. + json = @"{""MyOverflow"":{""Property1"":1}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(1, ((JsonElement)obj.MyOverflow["MyOverflow"]).EnumerateObject().First().Value.GetInt32()); + + // Attempt to deserialize null into the overflow property. This is also treated as a missing property. + json = @"{""MyOverflow"":null}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Null(obj.MyOverflow["MyOverflow"]); + + // Attempt to deserialize object into the overflow property. This is also treated as a missing property. + json = @"{""MyOverflow"":{}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(JsonValueKind.Object, ((JsonElement)obj.MyOverflow["MyOverflow"]).ValueKind); + } + + [Fact] + public async Task DeserializeIntoMultipleDictionaries() + { + ClassWithMultipleDictionaries obj; + string json; + + // Baseline dictionary. + json = @"{""ActualDictionary"":{""Key"": {""Property0"":-1}},""MyDict"":{""Property1"":1}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(1, ((JsonElement)obj.MyOverflow["MyDict"]).EnumerateObject().First().Value.GetInt32()); + Assert.Equal(1, obj.ActualDictionary.Count); + Assert.Equal(-1, ((JsonElement)obj.ActualDictionary["Key"]).EnumerateObject().First().Value.GetInt32()); + + // Attempt to deserialize null into the dictionary and overflow property. This is also treated as a missing property. + json = @"{""ActualDictionary"":null,""MyOverflow"":null}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Null(obj.MyOverflow["MyOverflow"]); + Assert.Null(obj.ActualDictionary); + + // Attempt to deserialize object into the dictionary and overflow property. This is also treated as a missing property. + json = @"{""ActualDictionary"":{},""MyOverflow"":{}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(JsonValueKind.Object, ((JsonElement)obj.MyOverflow["MyOverflow"]).ValueKind); + Assert.Equal(0, obj.ActualDictionary.Count); + } + + [Fact] + public async Task DeserializeIntoJsonElementProperty() + { + ClassWithExtensionPropertyAsJsonElement obj; + string json; + + // Baseline dictionary. + json = @"{""MyDict"":{""Property1"":1}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(1, obj.MyOverflow["MyDict"].EnumerateObject().First().Value.GetInt32()); + + // Attempt to deserialize directly into the overflow property; this is just added as a normal missing property like MyDict above. + json = @"{""MyOverflow"":{""Property1"":1}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(1, obj.MyOverflow["MyOverflow"].EnumerateObject().First().Value.GetInt32()); + + // Attempt to deserialize null into the overflow property. This is also treated as a missing property. + json = @"{""MyOverflow"":null}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(JsonValueKind.Null, obj.MyOverflow["MyOverflow"].ValueKind); + + // Attempt to deserialize object into the overflow property. This is also treated as a missing property. + json = @"{""MyOverflow"":{}}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(JsonValueKind.Object, obj.MyOverflow["MyOverflow"].ValueKind); + } + + [Fact] + public async Task SerializerOutputRoundtripsWhenEscaping() + { + string jsonString = "{\"\u6C49\u5B57\":\"abc\",\"Class\":{\"\u6F22\u5B57\":\"xyz\"},\"\u62DC\u6258\":{\"\u62DC\u6258\u62DC\u6258\":1}}"; + + ClassWithEscapedProperty input = await JsonSerializerWrapperForString.DeserializeWrapper(jsonString); + + Assert.Equal("abc", input.\u6C49\u5B57); + Assert.Equal("xyz", input.Class.\u6F22\u5B57); + + string normalizedString = await JsonSerializerWrapperForString.SerializeWrapper(input); + + Assert.Equal(normalizedString, await JsonSerializerWrapperForString.SerializeWrapper(await JsonSerializerWrapperForString.DeserializeWrapper(normalizedString))); + } + + public class ClassWithEscapedProperty + { + public string \u6C49\u5B57 { get; set; } + public NestedClassWithEscapedProperty Class { get; set; } + + [JsonExtensionData] + public Dictionary Overflow { get; set; } + } + + public class NestedClassWithEscapedProperty + { + public string \u6F22\u5B57 { get; set; } + } + + public class ClassWithInvalidExtensionPropertyStringString + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public class ClassWithInvalidExtensionPropertyObjectString + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public class ClassWithInvalidExtensionPropertyStringJsonNode + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + [Fact] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("https://github.com/dotnet/runtime/issues/58945")] +#endif + public async Task ExtensionProperty_InvalidDictionary() + { + var obj1 = new ClassWithInvalidExtensionPropertyStringString(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj1)); + + var obj2 = new ClassWithInvalidExtensionPropertyObjectString(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj2)); + + var obj3 = new ClassWithInvalidExtensionPropertyStringJsonNode(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj3)); + } + + public class ClassWithExtensionPropertyAlreadyInstantiated + { + public ClassWithExtensionPropertyAlreadyInstantiated() + { + MyOverflow = new Dictionary(); + } + + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyAsObject + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyAsJsonElement + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyAsJsonObject + { + [JsonExtensionData] + public JsonObject MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyAsSystemObject + { + [JsonExtensionData] + public object MyOverflow { get; set; } + } + + public class ClassWithMultipleDictionaries + { + [JsonExtensionData] + public Dictionary MyOverflow { get; set; } + + public Dictionary ActualDictionary { get; set; } + } + + [Fact] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("https://github.com/dotnet/runtime/issues/58945")] +#endif + public async Task DeserializeIntoImmutableDictionaryProperty() + { + // baseline + await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + await JsonSerializerWrapperForString.DeserializeWrapper(@"{}"); + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}")); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}")); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}")); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}")); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}")); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}")); + } + + [Fact] + public async Task SerializeIntoImmutableDictionaryProperty() + { + // attempt to serialize a null immutable dictionary + string expectedJson = "{}"; + var obj = new ClassWithExtensionPropertyAsImmutable(); + var json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(expectedJson, json); + + // attempt to serialize an empty immutable dictionary + expectedJson = "{}"; + obj = new ClassWithExtensionPropertyAsImmutable(); + obj.MyOverflow = ImmutableDictionary.Empty; + json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(expectedJson, json); + + // attempt to serialize a populated immutable dictionary + expectedJson = "{\"hello\":\"world\"}"; + obj = new ClassWithExtensionPropertyAsImmutable(); + var dictionaryStringObject = new Dictionary { { "hello", "world" } }; + obj.MyOverflow = ImmutableDictionary.CreateRange(dictionaryStringObject); + json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(expectedJson, json); + } + + public class ClassWithExtensionPropertyAsImmutable + { + [JsonExtensionData] + public ImmutableDictionary MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyAsImmutableJsonElement + { + [JsonExtensionData] + public ImmutableDictionary MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyPrivateConstructor + { + [JsonExtensionData] + public GenericIDictionaryWrapperPrivateConstructor MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyPrivateConstructorJsonElement + { + [JsonExtensionData] + public GenericIDictionaryWrapperPrivateConstructor MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyCustomIImmutable + { + [JsonExtensionData] + public GenericIImmutableDictionaryWrapper MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyCustomIImmutableJsonElement + { + [JsonExtensionData] + public GenericIImmutableDictionaryWrapper MyOverflow { get; set; } + } + + [Theory] + [InlineData(typeof(ClassWithExtensionPropertyNoGenericParameters))] + [InlineData(typeof(ClassWithExtensionPropertyOneGenericParameter))] + [InlineData(typeof(ClassWithExtensionPropertyThreeGenericParameters))] + public async Task DeserializeIntoGenericDictionaryParameterCount(Type type) + { + object obj = await JsonSerializerWrapperForString.DeserializeWrapper("{\"hello\":\"world\"}", type); + + IDictionary extData = (IDictionary)type.GetProperty("MyOverflow").GetValue(obj)!; + Assert.Equal("world", ((JsonElement)extData["hello"]).GetString()); + } + + public class ClassWithExtensionPropertyNoGenericParameters + { + [JsonExtensionData] + public StringToObjectIDictionaryWrapper MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyOneGenericParameter + { + [JsonExtensionData] + public StringToGenericIDictionaryWrapper MyOverflow { get; set; } + } + + public class ClassWithExtensionPropertyThreeGenericParameters + { + [JsonExtensionData] + public GenericIDictonaryWrapperThreeGenericParameters MyOverflow { get; set; } + } + + [Fact] + public async Task CustomObjectConverterInExtensionProperty() + { + const string Json = "{\"hello\": \"world\"}"; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new ObjectConverter()); + + ClassWithExtensionPropertyAsObject obj = await JsonSerializerWrapperForString.DeserializeWrapper(Json, options); + object overflowProp = obj.MyOverflow["hello"]; + Assert.IsType(overflowProp); + Assert.Equal("world!!!", ((string)overflowProp)); + + string newJson = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Equal("{\"hello\":\"world!!!\"}", newJson); + } + + public class ObjectConverter : JsonConverter + { + public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.GetString() + "!!!"; + } + + public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) + { + // Since we are in a user-provided (not internal to S.T.Json) object converter, + // this converter will be called, not the internal string converter. + writer.WriteStringValue((string)value); + } + } + + [Fact] + public async Task CustomJsonElementConverterInExtensionProperty() + { + const string Json = "{\"hello\": \"world\"}"; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonElementConverter()); + + ClassWithExtensionPropertyAsJsonElement obj = await JsonSerializerWrapperForString.DeserializeWrapper(Json, options); + JsonElement overflowProp = obj.MyOverflow["hello"]; + Assert.Equal(JsonValueKind.Undefined, overflowProp.ValueKind); + + string newJson = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Equal("{\"hello\":{\"Hi\":\"There\"}}", newJson); + } + + public class JsonElementConverter : JsonConverter + { + public override JsonElement Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // Just return an empty JsonElement. + reader.Skip(); + return new JsonElement(); + } + + public override void Write(Utf8JsonWriter writer, JsonElement value, JsonSerializerOptions options) + { + // Write a string we can test against easily. + writer.WriteStartObject(); + writer.WriteString("Hi", "There"); + writer.WriteEndObject(); + } + } + + [Fact] + public async Task CustomJsonObjectConverterInExtensionProperty() + { + const string Json = "{\"hello\": \"world\"}"; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new JsonObjectConverter()); + + // A custom converter for JsonObject is not allowed on an extension property. + InvalidOperationException ex = await Assert.ThrowsAsync(async () => + await JsonSerializerWrapperForString.DeserializeWrapper(Json, options)); + + Assert.Contains("JsonObject", ex.ToString()); + } + + public class JsonObjectConverter : JsonConverter + { + public override JsonObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // Just return an empty JsonElement. + reader.Skip(); + return new JsonObject(); + } + + public override void Write(Utf8JsonWriter writer, JsonObject value, JsonSerializerOptions options) + { + // Write a string we can test against easily. + writer.WriteStartObject(); + writer.WriteString("Hi", "There"); + writer.WriteEndObject(); + } + } + + [Fact] + public async Task EmptyPropertyAndExtensionData_PropertyFirst() + { + // Verify any caching treats real property (with empty name) differently than a missing property. + + ClassWithEmptyPropertyNameAndExtensionProperty obj; + + // Create a new options instances to re-set any caches. + JsonSerializerOptions options = new JsonSerializerOptions(); + + // First use an empty property. + string json = @"{"""":43}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal(43, obj.MyInt1); + Assert.Null(obj.MyOverflow); + + // Then populate cache with a missing property name. + json = @"{""DoesNotExist"":42}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal(0, obj.MyInt1); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(42, obj.MyOverflow["DoesNotExist"].GetInt32()); + } + + [Fact] + public async Task EmptyPropertyNameAndExtensionData_ExtDataFirst() + { + // Verify any caching treats real property (with empty name) differently than a missing property. + + ClassWithEmptyPropertyNameAndExtensionProperty obj; + + // Create a new options instances to re-set any caches. + JsonSerializerOptions options = new JsonSerializerOptions(); + + // First populate cache with a missing property name. + string json = @"{""DoesNotExist"":42}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal(0, obj.MyInt1); + Assert.Equal(1, obj.MyOverflow.Count); + Assert.Equal(42, obj.MyOverflow["DoesNotExist"].GetInt32()); + + // Then use an empty property. + json = @"{"""":43}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal(43, obj.MyInt1); + Assert.Null(obj.MyOverflow); + } + + [Fact] + public async Task ExtensionDataDictionarySerialize_DoesNotHonor() + { + var options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + EmptyClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Key1"": 1}", options); + + // Ignore naming policy for extension data properties by default. + Assert.False(obj.MyOverflow.ContainsKey("key1")); + Assert.Equal(1, obj.MyOverflow["Key1"].GetInt32()); + } + + [Theory] + [InlineData(0x1, 'v')] + [InlineData(0x1, '\u0467')] + [InlineData(0x10, 'v')] + [InlineData(0x10, '\u0467')] + [InlineData(0x100, 'v')] + [InlineData(0x100, '\u0467')] + [InlineData(0x1000, 'v')] + [InlineData(0x1000, '\u0467')] + [InlineData(0x10000, 'v')] + [InlineData(0x10000, '\u0467')] + public async Task LongPropertyNames(int propertyLength, char ch) + { + // Although the CLR may limit member length to 1023 bytes, the serializer doesn't have a hard limit. + + string val = new string(ch, propertyLength); + string json = @"{""" + val + @""":1}"; + + EmptyClassWithExtensionProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + + Assert.True(obj.MyOverflow.ContainsKey(val)); + + var options = new JsonSerializerOptions + { + // Avoid escaping '\u0467'. + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + + string jsonRoundTripped = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Equal(json, jsonRoundTripped); + } + + public class EmptyClassWithExtensionProperty + { + [JsonExtensionData] + public IDictionary MyOverflow { get; set; } + } + + public class ClassWithEmptyPropertyNameAndExtensionProperty + { + [JsonPropertyName("")] + public int MyInt1 { get; set; } + + [JsonExtensionData] + public IDictionary MyOverflow { get; set; } + } + } +} diff --git a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs index 528ac2903e4057..1f1c05c9a8aece 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Text.Json.Serialization.Tests; +using System.Text.Json.Serialization.Tests.Schemas.OrderPayload; using System.Text.RegularExpressions; using System.Threading.Tasks; using Xunit; @@ -84,5 +86,187 @@ public static async Task> ToListAsync(this IAsyncEnumerable source public static string StripWhitespace(this string value) => s_stripWhitespace.Replace(value, string.Empty); + + internal static List PopulateLargeObject(int size) + { + List orders = new List(size); + for (int i = 0; i < size; i++) + { + Order order = new Order + { + OrderNumber = i, + Customer = new User + { + UserId = "222ffbbb888kkk", + Name = "John Doe", + Username = "johndoe", + CreatedAt = new DateTime(), + ImageId = string.Empty, + UserType = UserType.Customer, + UpdatedAt = new DateTime(), + TwitterId = string.Empty, + FacebookId = "9988998877662222111", + SubscriptionType = 2, + IsNew = true, + IsEmployee = false + }, + ShippingInfo = new List + { + new ShippingInfo() + { + OrderNumber = i, + Employee = new User + { + UserId = "222ffbbb888" + i, + Name = "Shipping Coordinator", + Username = "coordinator" + i, + CreatedAt = new DateTime(), + ImageId = string.Empty, + UserType = UserType.Employee, + UpdatedAt = new DateTime(), + TwitterId = string.Empty, + SubscriptionType = 0, + IsEmployee = true + }, + CarrierId = "TTT123999MMM", + ShippingType = "Ground", + EstimatedDelivery = new DateTime(), + Tracking = new Uri("http://TestShipCompany.test/track/123" + i), + CarrierName = "TestShipCompany", + HandlingInstruction = "Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats", + CurrentStatus = "Out for delivery", + IsDangerous = false + } + }, + OneTime = true, + Cancelled = false, + IsGift = i % 2 == 0, + IsGPickUp = i % 5 == 0, + ShippingAddress = new Address() + { + City = "Redmond" + }, + PickupAddress = new Address + { + City = "Bellevue" + }, + Coupon = SampleEnumInt64.Max, + UserInteractions = new List + { + new Comment + { + Id = 200 + i, + OrderNumber = i, + Customer = new User + { + UserId = "222ffbbb888kkk", + Name = "John Doe", + Username = "johndoe", + CreatedAt = new DateTime(), + ImageId = string.Empty, + UserType = UserType.Customer, + UpdatedAt = new DateTime(), + TwitterId = "twitterId" + i, + FacebookId = "9988998877662222111", + SubscriptionType = 2, + IsNew = true, + IsEmployee = false + }, + Title = "Green Field", + Message = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to", + Responses = new List() + } + }, + Created = new DateTime(2019, 11, 10), + Confirmed = new DateTime(2019, 11, 11), + ShippingDate = new DateTime(2019, 11, 12), + EstimatedDelivery = new DateTime(2019, 11, 15), + ReviewedBy = new User() + { + UserId = "222ffbbb888" + i, + Name = "Shipping Coordinator", + Username = "coordinator" + i, + CreatedAt = new DateTime(), + ImageId = string.Empty, + UserType = UserType.Employee, + UpdatedAt = new DateTime(), + TwitterId = string.Empty, + SubscriptionType = 0, + IsEmployee = true + } + }; + List products = new List(); + for (int j = 0; j < i % 4; j++) + { + Product product = new Product() + { + ProductId = Guid.NewGuid(), + Name = "Surface Pro", + SKU = "LL123" + j, + Brand = new TestClassWithInitializedProperties(), + ProductCategory = new SimpleTestClassWithNonGenericCollectionWrappers(), + Description = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to", + Created = new DateTime(2000, 10, 12), + Title = "Surface Pro 6 for Business - 512GB", + Price = new Price(), + BestChoice = true, + AverageStars = 4.8f, + Featured = true, + ProductRestrictions = new TestClassWithInitializedProperties(), + SalesInfo = new SimpleTestClassWithGenericCollectionWrappers(), + Origin = SampleEnum.One, + Manufacturer = new BasicCompany(), + Fragile = true, + DetailsUrl = new Uri("http://dotnet.test/link/entries/entry/1"), + NetWeight = 2.7m, + GrossWeight = 3.3m, + Length = i, + Height = i + 1, + Width = i + 2, + FeaturedImage = new FeaturedImage(), + PreviewImage = new PreviewImage(), + KeyWords = new List { "surface", "pro", "laptop" }, + RelatedImages = new List(), + RelatedVideo = new Uri("http://dotnet.test/link/entries/entry/2"), + GuaranteeStartsAt = new DateTime(), + GuaranteeEndsAt = new DateTime(), + IsActive = true, + RelatedProducts = new List() + }; + product.SalesInfo.Initialize(); + List reviews = new List(); + for (int k = 0; k < i % 3; k++) + { + + Review review = new Review + { + Customer = new User + { + UserId = "333344445555", + Name = "Customer" + i + k, + Username = "cust" + i + k, + CreatedAt = new DateTime(), + ImageId = string.Empty, + UserType = UserType.Customer, + SubscriptionType = k + }, + ProductSku = product.SKU, + CustomerName = "Customer" + i + k, + Stars = j + k, + Title = $"Title {i}{j}{k}", + Comment = "", + Images = new List { new Uri($"http://dotnet.test/link/images/image/{k}"), new Uri($"http://dotnet.test/link/images/image/{j}") }, + ReviewId = i + j + k + }; + reviews.Add(review); + } + product.Reviews = reviews; + products.Add(product); + } + order.Products = products; + orders.Add(order); + } + return orders; + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs b/src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs similarity index 65% rename from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs rename to src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs index 2d325eac994f1d..20562ef04fbc10 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs @@ -2,20 +2,24 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Text.Json.Nodes; using System.Text.Json.Serialization.Tests.Schemas.OrderPayload; +using System.Threading.Tasks; using Xunit; -namespace System.Text.Json.Nodes.Tests +namespace System.Text.Json.Serialization.Tests { - public static class SerializerInteropTests + public abstract class NodeInteropTests : SerializerTests { + public NodeInteropTests(JsonSerializerWrapperForString serializerWrapper) : base(serializerWrapper) { } + [Fact] - public static void CompareResultsAgainstSerializer() + public async Task CompareResultsAgainstSerializer() { - List obj = Serialization.Tests.StreamTests.PopulateLargeObject(2); - string expected = JsonSerializer.Serialize(obj); + List obj = JsonTestHelper.PopulateLargeObject(2); + string expected = await JsonSerializerWrapperForString.SerializeWrapper(obj); - JsonArray jArray = JsonSerializer.Deserialize(expected); + JsonArray jArray = await JsonSerializerWrapperForString.DeserializeWrapper(expected); string actual = jArray.ToJsonString(); Assert.Equal(expected, actual); @@ -24,7 +28,7 @@ public static void CompareResultsAgainstSerializer() Assert.Equal(expected, actual); } - private class Poco + public class Poco { public string MyString { get; set; } public JsonNode Node { get; set; } @@ -35,7 +39,7 @@ private class Poco } [Fact] - public static void NodesAsPocoProperties() + public async Task NodesAsPocoProperties() { const string Expected = "{\"MyString\":null,\"Node\":42,\"Array\":[43],\"Value\":44,\"IntValue\":45,\"Object\":{\"Property\":46}}"; @@ -51,10 +55,10 @@ public static void NodesAsPocoProperties() } }; - string json = JsonSerializer.Serialize(poco); + string json = await JsonSerializerWrapperForString.SerializeWrapper(poco); Assert.Equal(Expected, json); - poco = JsonSerializer.Deserialize(json); + poco = await JsonSerializerWrapperForString.DeserializeWrapper(json); Assert.Equal(42, (int)poco.Node); Assert.Equal(43, (int)poco.Array[0]); Assert.Equal(44, (int)poco.Value); diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyNameTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyNameTests.cs new file mode 100644 index 00000000000000..fe1c4b5f73ce3b --- /dev/null +++ b/src/libraries/System.Text.Json/tests/Common/PropertyNameTests.cs @@ -0,0 +1,484 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// This file is saved as Unicode in order to test inline (not escaped) unicode characters. + +using System.Collections.Generic; +using System.Text.Encodings.Web; +using System.Threading.Tasks; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public abstract partial class PropertyNameTests : SerializerTests + { + public PropertyNameTests(JsonSerializerWrapperForString serializerWrapper) : base(serializerWrapper) { } + + [Fact] + public async Task CamelCaseDeserializeNoMatch() + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MyInt16"":1}", options); + + // This is 0 (default value) because the data does not match the property "MyInt16" that is assuming camel-casing of "myInt16". + Assert.Equal(0, obj.MyInt16); + } + + [Fact] + public async Task CamelCaseDeserializeMatch() + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""myInt16"":1}", options); + + // This is 1 because the data matches the property "MyInt16" that is assuming camel-casing of "myInt16". + Assert.Equal(1, obj.MyInt16); + } + + [Fact] + public async Task CamelCaseSerialize() + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{}", options); + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Contains(@"""myInt16"":0", json); + Assert.Contains(@"""myInt32"":0", json); + } + + [Fact] + public async Task CustomNamePolicy() + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = new UppercaseNamingPolicy(); + + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MYINT16"":1}", options); + + // This is 1 because the data matches the property "MYINT16" that is uppercase of "myInt16". + Assert.Equal(1, obj.MyInt16); + } + + [Fact] + public async Task NullNamePolicy() + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = new NullNamingPolicy(); + + // A policy that returns null is not allowed. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(@"{}", options)); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new SimpleTestClass(), options)); + } + + [Fact] + public async Task IgnoreCase() + { + { + // A non-match scenario with no options (case-sensitive by default). + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""myint16"":1}"); + Assert.Equal(0, obj.MyInt16); + } + + { + // A non-match scenario with default options (case-sensitive by default). + var options = new JsonSerializerOptions(); + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""myint16"":1}", options); + Assert.Equal(0, obj.MyInt16); + } + + { + var options = new JsonSerializerOptions(); + options.PropertyNameCaseInsensitive = true; + SimpleTestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""myint16"":1}", options); + Assert.Equal(1, obj.MyInt16); + } + } + + [Fact] + public async Task JsonPropertyNameAttribute() + { + { + OverridePropertyNameDesignTime_TestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Blah"":1}"); + Assert.Equal(1, obj.myInt); + + obj.myObject = 2; + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""Blah"":1", json); + Assert.Contains(@"""BlahObject"":2", json); + } + + // The JsonPropertyNameAttribute should be unaffected by JsonNamingPolicy and PropertyNameCaseInsensitive. + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + options.PropertyNameCaseInsensitive = true; + + OverridePropertyNameDesignTime_TestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Blah"":1}", options); + Assert.Equal(1, obj.myInt); + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""Blah"":1", json); + } + } + + [Fact] + public async Task JsonNameAttributeDuplicateDesignTimeFail() + { + { + var options = new JsonSerializerOptions(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}", options)); + } + + { + var options = new JsonSerializerOptions(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new DuplicatePropertyNameDesignTime_TestClass(), options)); + } + } + + [Fact] + public async Task JsonNameConflictOnCamelCasingFail() + { + { + // Baseline comparison - no options set. + IntPropertyNamesDifferentByCaseOnly_TestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper("{}"); + await JsonSerializerWrapperForString.SerializeWrapper(obj); + } + + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}", options)); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new IntPropertyNamesDifferentByCaseOnly_TestClass(), options)); + } + + { + // Baseline comparison - no options set. + ObjectPropertyNamesDifferentByCaseOnly_TestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper("{}"); + await JsonSerializerWrapperForString.SerializeWrapper(obj); + } + + { + var options = new JsonSerializerOptions(); + options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}", options)); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new ObjectPropertyNamesDifferentByCaseOnly_TestClass(), options)); + } + } + + [Fact] + public async Task JsonOutputNotAffectedByCasingPolicy() + { + { + // Baseline. + string json = await JsonSerializerWrapperForString.SerializeWrapper(new SimpleTestClass()); + Assert.Contains(@"""MyInt16"":0", json); + } + + // The JSON output should be unaffected by PropertyNameCaseInsensitive. + { + var options = new JsonSerializerOptions(); + options.PropertyNameCaseInsensitive = true; + + string json = await JsonSerializerWrapperForString.SerializeWrapper(new SimpleTestClass(), options); + Assert.Contains(@"""MyInt16"":0", json); + } + } + + [Fact] + public async Task EmptyPropertyName() + { + string json = @"{"""":1}"; + + { + var obj = new EmptyPropertyName_TestClass(); + obj.MyInt1 = 1; + + string jsonOut = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(json, jsonOut); + } + + { + EmptyPropertyName_TestClass obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.MyInt1); + } + } + + [Fact] + public async Task UnicodePropertyNames() + { + ClassWithUnicodeProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper("{\"A\u0467\":1}"); + Assert.Equal(1, obj.A\u0467); + + // Specifying encoder on options does not impact deserialize. + var options = new JsonSerializerOptions(); + options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; + + obj = await JsonSerializerWrapperForString.DeserializeWrapper("{\"A\u0467\":1}", options); + Assert.Equal(1, obj.A\u0467); + + string json; + + // Verify the name is escaped after serialize. + json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""A\u0467"":1", json); + + // With custom escaper + json = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Contains("\"A\u0467\":1", json); + + // Verify the name is unescaped after deserialize. + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.A\u0467); + + // With custom escaper + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); + Assert.Equal(1, obj.A\u0467); + } + + [Fact] + public async Task UnicodePropertyNamesWithPooledAlloc() + { + // We want to go over StackallocByteThreshold=256 to force a pooled allocation, so this property is 400 chars and 401 bytes. + ClassWithUnicodeProperty obj = await JsonSerializerWrapperForString.DeserializeWrapper("{\"A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\":1}"); + Assert.Equal(1, obj.A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890); + + // Verify the name is escaped after serialize. + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Contains(@"""A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"":1", json); + + // Verify the name is unescaped after deserialize. + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890); + } + + public class ClassWithPropertyNamePermutations + { + public int a { get; set; } + public int aa { get; set; } + public int aaa { get; set; } + public int aaaa { get; set; } + public int aaaaa { get; set; } + public int aaaaaa { get; set; } + + // 7 characters - caching code only keys up to 7. + public int aaaaaaa { get; set; } + public int aaaaaab { get; set; } + + // 8 characters. + public int aaaaaaaa { get; set; } + public int aaaaaaab { get; set; } + + // 9 characters. + public int aaaaaaaaa { get; set; } + public int aaaaaaaab { get; set; } + + public int \u0467 { get; set; } + public int \u0467\u0467 { get; set; } + public int \u0467\u0467a { get; set; } + public int \u0467\u0467b { get; set; } + public int \u0467\u0467\u0467 { get; set; } + public int \u0467\u0467\u0467a { get; set; } + public int \u0467\u0467\u0467b { get; set; } + public int \u0467\u0467\u0467\u0467 { get; set; } + public int \u0467\u0467\u0467\u0467a { get; set; } + public int \u0467\u0467\u0467\u0467b { get; set; } + } + + [Fact] + public async Task CachingKeys() + { + ClassWithPropertyNamePermutations obj; + + void Verify() + { + Assert.Equal(1, obj.a); + Assert.Equal(2, obj.aa); + Assert.Equal(3, obj.aaa); + Assert.Equal(4, obj.aaaa); + Assert.Equal(5, obj.aaaaa); + Assert.Equal(6, obj.aaaaaa); + Assert.Equal(7, obj.aaaaaaa); + Assert.Equal(7, obj.aaaaaab); + Assert.Equal(8, obj.aaaaaaaa); + Assert.Equal(8, obj.aaaaaaab); + Assert.Equal(9, obj.aaaaaaaaa); + Assert.Equal(9, obj.aaaaaaaab); + + Assert.Equal(2, obj.\u0467); + Assert.Equal(4, obj.\u0467\u0467); + Assert.Equal(5, obj.\u0467\u0467a); + Assert.Equal(5, obj.\u0467\u0467b); + Assert.Equal(6, obj.\u0467\u0467\u0467); + Assert.Equal(7, obj.\u0467\u0467\u0467a); + Assert.Equal(7, obj.\u0467\u0467\u0467b); + Assert.Equal(8, obj.\u0467\u0467\u0467\u0467); + Assert.Equal(9, obj.\u0467\u0467\u0467\u0467a); + Assert.Equal(9, obj.\u0467\u0467\u0467\u0467b); + } + + obj = new ClassWithPropertyNamePermutations + { + a = 1, + aa = 2, + aaa = 3, + aaaa = 4, + aaaaa = 5, + aaaaaa = 6, + aaaaaaa = 7, + aaaaaab = 7, + aaaaaaaa = 8, + aaaaaaab = 8, + aaaaaaaaa = 9, + aaaaaaaab = 9, + \u0467 = 2, + \u0467\u0467 = 4, + \u0467\u0467a = 5, + \u0467\u0467b = 5, + \u0467\u0467\u0467 = 6, + \u0467\u0467\u0467a = 7, + \u0467\u0467\u0467b = 7, + \u0467\u0467\u0467\u0467 = 8, + \u0467\u0467\u0467\u0467a = 9, + \u0467\u0467\u0467\u0467b = 9, + }; + + // Verify baseline. + Verify(); + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + + // Verify the length is consistent with a verified value. + Assert.Equal(354, json.Length); + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + + // Verify round-tripped object. + Verify(); + } + + [Fact] + public async Task BadNamingPolicy_ThrowsInvalidOperation() + { + var options = new JsonSerializerOptions { DictionaryKeyPolicy = new NullNamingPolicy() }; + + var inputPrimitive = new Dictionary + { + { "validKey", 1 } + }; + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(inputPrimitive, options)); + + var inputClass = new Dictionary + { + { "validKey", new OverridePropertyNameDesignTime_TestClass() } + }; + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(inputClass, options)); + } + + public class OverridePropertyNameDesignTime_TestClass + { + [JsonPropertyName("Blah")] + public int myInt { get; set; } + + [JsonPropertyName("BlahObject")] + public object myObject { get; set; } + } + + public class DuplicatePropertyNameDesignTime_TestClass + { + [JsonPropertyName("Blah")] + public int MyInt1 { get; set; } + + [JsonPropertyName("Blah")] + public int MyInt2 { get; set; } + } + + public class EmptyPropertyName_TestClass + { + [JsonPropertyName("")] + public int MyInt1 { get; set; } + } + + public class NullPropertyName_TestClass + { + [JsonPropertyName(null)] + public int MyInt1 { get; set; } + } + + public class IntPropertyNamesDifferentByCaseOnly_TestClass + { + public int myInt { get; set; } + public int MyInt { get; set; } + } + + public class ObjectPropertyNamesDifferentByCaseOnly_TestClass + { + public int myObject { get; set; } + public int MyObject { get; set; } + } + + [Fact] + public async Task SpecialCharacters() + { + ClassWithSpecialCharacters obj = new() + { + Baseline = 1, + Schema = 2, + SmtpId = 3, + Emojies = 4, + ꀀ = 5, + YiIt_2 = 6 + }; + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal( + "{\"Baseline\":1," + + "\"$schema\":2," + + "\"smtp-id\":3," + + "\"\\uD83D\\uDE00\\uD83D\\uDE01\":4," + + "\"\\uA000\":5," + + "\"\\uA000_2\":6}", json); + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(1, obj.Baseline); + Assert.Equal(2, obj.Schema); + Assert.Equal(3, obj.SmtpId); + Assert.Equal(4, obj.Emojies); + Assert.Equal(5, obj.ꀀ); + Assert.Equal(6, obj.YiIt_2); + } + + public class ClassWithSpecialCharacters + { + [JsonPropertyOrder(1)] + public int Baseline { get; set; } + + [JsonPropertyOrder(2)] + [JsonPropertyName("$schema")] // Invalid C# property name. + public int Schema { get; set; } + + [JsonPropertyOrder(3)] + [JsonPropertyName("smtp-id")] // Invalid C# property name. + public int SmtpId { get; set; } + + [JsonPropertyOrder(4)] + [JsonPropertyName("😀😁")] // Invalid C# property name. Unicode:\uD83D\uDE00\uD83D\uDE01 + public int Emojies { get; set; } + + [JsonPropertyOrder(5)] + public int ꀀ { get; set; } // Valid C# property name. Unicode:\uA000 + + [JsonPropertyOrder(6)] + [JsonPropertyName("\uA000_2")] // Valid C# property name: ꀀ_2 + public int YiIt_2 { get; set; } + } + } +} diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.NonPublicAccessors.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.NonPublicAccessors.cs index 0c8dc6a941c38f..af5159c0552e36 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.NonPublicAccessors.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.NonPublicAccessors.cs @@ -216,31 +216,46 @@ public async Task HonorNamingPolicy() } [Fact] - public virtual async Task HonorJsonPropertyName() + public virtual async Task HonorJsonPropertyName_PrivateGetter() { - string json = @"{""prop1"":1,""prop2"":2}"; + string json = @"{""prop1"":1}"; - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); - Assert.Equal(MySmallEnum.AnotherValue, obj.GetMyEnum); - Assert.Equal(2, obj.MyInt); + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(MySmallEnum.AnotherValue, obj.GetProxy()); json = await JsonSerializerWrapperForString.SerializeWrapper(obj); Assert.Contains(@"""prop1"":1", json); + } + + [Fact] + public virtual async Task HonorJsonPropertyName_PrivateSetter() + { + string json = @"{""prop2"":2}"; + + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(2, obj.MyInt); + + json = await JsonSerializerWrapperForString.SerializeWrapper(obj); Assert.Contains(@"""prop2"":2", json); } - public struct StructWithPropertiesWithJsonPropertyName + public struct StructWithPropertiesWithJsonPropertyName_PrivateGetter { [JsonInclude] [JsonPropertyName("prop1")] public MySmallEnum MyEnum { private get; set; } + // For test validation. + internal MySmallEnum GetProxy() => MyEnum; + } + + public struct StructWithPropertiesWithJsonPropertyName_PrivateSetter + { [JsonInclude] [JsonPropertyName("prop2")] public int MyInt { get; private set; } - // For test validation. - internal MySmallEnum GetMyEnum => MyEnum; + internal void SetProxy(int myInt) => MyInt = myInt; } [Fact] diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index 32f19eb120c39c..8c0f57b422a55d 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -241,6 +241,24 @@ public async Task Ignore_BasePublicPropertyIgnored_ConflictWithDerivedPrivate() Assert.Equal("NewDefaultValue", ((ClassWithIgnoredPublicPropertyAndNewSlotPrivate)obj).MyString); } + [Fact] + public async Task Ignore_VerifyNoReferenceToGetterAndSetter() + { + // Serialize + var obj = new ClassWithObsoleteAndIgnoredProperty(); + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + + Assert.Equal(@"{}", json); + + // Deserialize + json = @"{""MyString_Obsolete"":""NewValue""}"; + obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + +#pragma warning disable CS0618 // Type or member is obsolete + Assert.Equal("DefaultValue", obj.MyString_Obsolete); +#pragma warning restore CS0618 // Type or member is obsolete + } + [Fact] public async Task Ignore_PublicProperty_ConflictWithPrivateDueAttributes() { @@ -782,6 +800,13 @@ public class ClassWithIgnoredPublicProperty public string MyString { get; set; } = "DefaultValue"; } + public class ClassWithObsoleteAndIgnoredProperty + { + [Obsolete("Src gen should not generate reference to getter or setter")] + [JsonIgnore] + public string MyString_Obsolete { get; set; } = "DefaultValue"; + } + public class ClassWithIgnoredPublicPropertyAndNewSlotPrivate : ClassWithIgnoredPublicProperty { internal new string MyString { get; set; } = "NewDefaultValue"; @@ -2628,5 +2653,201 @@ public async Task JsonIgnoreCondition_WhenWritingDefault_OnInterface() json = await JsonSerializerWrapperForString.SerializeWrapper(obj); Assert.Equal("{\"MyProp\":{}}", json); } + + public class ConcreteDerivedClass : AbstractBaseClass + { + // Ignored including on base class: + [JsonIgnore] public override int Abstract_Ignored_Property { get; set; } + [JsonIgnore] public override int Virtual_Ignored_Property { get; set; } + + // Ignored but not specified on base class: + [JsonIgnore] public override int Abstract_IgnoredOnConcrete_Property { get; set; } + [JsonIgnore] public override int Virtual_IgnoredOnConcrete_Property { get; set; } + + // Ignored specified on base class: + [JsonPropertyOrder(1)] public override int Abstract_IgnoredOnBase_Property { get; set; } + [JsonPropertyOrder(2)] public override int Virtual_IgnoredOnBase_Property { get; set; } + + // Standard overrides (not ignored): + [JsonPropertyOrder(3)] public override int Abstract_Property { get; set; } + [JsonPropertyOrder(4)] public override int Virtual_Property { get; set; } + } + + public abstract class AbstractBaseClass + { + [JsonIgnore] public abstract int Abstract_Ignored_Property { get; set; } + [JsonIgnore] public virtual int Virtual_Ignored_Property { get; set; } + + public abstract int Abstract_IgnoredOnConcrete_Property { get; set; } + public virtual int Virtual_IgnoredOnConcrete_Property { get; set; } + + [JsonIgnore] public abstract int Abstract_IgnoredOnBase_Property { get; set; } + [JsonIgnore] public virtual int Virtual_IgnoredOnBase_Property { get; set; } + + public abstract int Abstract_Property { get; set; } + public virtual int Virtual_Property { get; set; } + } + + [Fact] + public async Task JsonIgnoreCondition_Polymorphic() + { + ConcreteDerivedClass obj = new() + { + Abstract_Ignored_Property = -1, + Virtual_Ignored_Property = -1, + Abstract_IgnoredOnConcrete_Property = -1, + Virtual_IgnoredOnConcrete_Property = -1, + Abstract_IgnoredOnBase_Property = 1, + Virtual_IgnoredOnBase_Property = 2, + Abstract_Property = 3, + Virtual_Property = 4, + }; + + // Verify properties work as expected. + Assert.Equal(-1, obj.Abstract_Ignored_Property); + Assert.Equal(-1, obj.Virtual_Ignored_Property); + Assert.Equal(-1, obj.Abstract_IgnoredOnConcrete_Property); + Assert.Equal(-1, obj.Virtual_IgnoredOnConcrete_Property); + Assert.Equal(1, obj.Abstract_IgnoredOnBase_Property); + Assert.Equal(2, obj.Virtual_IgnoredOnBase_Property); + Assert.Equal(3, obj.Abstract_Property); + Assert.Equal(4, obj.Virtual_Property); + + const string ExpectedJson = "{" + + "\"Abstract_IgnoredOnBase_Property\":1," + + "\"Virtual_IgnoredOnBase_Property\":2," + + "\"Abstract_Property\":3," + + "\"Virtual_Property\":4}"; + + string json = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(ExpectedJson, json); + + const string Json = "{" + + "\"Abstract_Ignored_Property\":-1," + + "\"Virtual_Ignored_Property\":-1," + + "\"Abstract_IgnoredOnConcrete_Property\":-1," + + "\"Virtual_IgnoredOnConcrete_Property\":-1," + + "\"Abstract_IgnoredOnBase_Property\":1," + + "\"Virtual_IgnoredOnBase_Property\":2," + + "\"Abstract_Property\":3," + + "\"Virtual_Property\":4}"; + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(Json); + Assert.Equal(0, obj.Abstract_Ignored_Property); + Assert.Equal(0, obj.Virtual_Ignored_Property); + Assert.Equal(0, obj.Abstract_IgnoredOnConcrete_Property); + Assert.Equal(0, obj.Virtual_IgnoredOnConcrete_Property); + Assert.Equal(1, obj.Abstract_IgnoredOnBase_Property); + Assert.Equal(2, obj.Virtual_IgnoredOnBase_Property); + Assert.Equal(3, obj.Abstract_Property); + Assert.Equal(4, obj.Virtual_Property); + } + + [Fact] + public async Task SerializationMetadataNotComputedWhenMemberIgnored() + { + string janePayload = @"{""Name"":""Jane Doe""}"; + +#if !BUILDING_SOURCE_GENERATOR_TESTS + // Without [JsonIgnore], serializer throws exceptions due to runtime-reflection-based property metadata inspection. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_RefStringProp())); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}")); + + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_PropWith_BadConverter())); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper("{}")); +#else + // Ref returns supported in source-gen mode + string expected = @"{""NameRef"":""John Doe"",""Name"":""John Doe""}"; + JsonTestHelper.AssertJsonEqual(expected, await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_RefStringProp())); + + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(janePayload); + Assert.Equal("Jane Doe", obj.Name); + Assert.Equal("Jane Doe", obj.NameRef); + + var obj2 = new TypeWith_PropWith_BadConverter(); + obj2.Property = "Hello"; + + // Invalid converter specified, fallback to built-in converter. This should be corrected. + // https://github.com/dotnet/runtime/issues/60020. + + Assert.Equal(@"{""Property"":""Hello""}", await JsonSerializerWrapperForString.SerializeWrapper(obj2)); + + obj2 = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Property"":""World""}"); + Assert.Equal("World", obj2.Property); +#endif + + // With [JsonIgnore], serializer skips property metadata inspection + Assert.Equal(@"{""Name"":""John Doe""}", await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_IgnoredRefStringProp())); + Assert.Equal("Jane Doe", (await JsonSerializerWrapperForString.DeserializeWrapper(janePayload)).Name); + + Assert.Equal("{}", await JsonSerializerWrapperForString.SerializeWrapper(new TypeWith_IgnoredPropWith_BadConverter())); + Assert.Null((await JsonSerializerWrapperForString.DeserializeWrapper("{}")).Property); + } + + internal class TypeWith_RefStringProp + { + public ref string NameRef => ref Name; + + [JsonInclude] // This is a field. + public string Name = "John Doe"; + } + + internal class TypeWith_IgnoredRefStringProp + { + [JsonIgnore] + public ref string NameRef => ref Name; + + [JsonInclude] // This is a field. + public string Name = "John Doe"; + } + + public class TypeWith_PropWith_BadConverter + { + [JsonConverter(typeof(BadConverter))] + public string? Property { get; set; } + } + + public class TypeWith_IgnoredPropWith_BadConverter + { + [JsonIgnore] + [JsonConverter(typeof(BadConverter))] + public string? Property { get; set; } + } + + public class BadConverter + { + } + + [Fact] + public async Task TestClassWithIgnoredCallbacks() + { + Assert.Equal("{}", await JsonSerializerWrapperForString.SerializeWrapper(new ClassWithIgnoredCallbacks())); + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Func"":"""",""Action"":""""}"); + Assert.False(obj.Func("")); + Assert.Null(obj.Action); + } + + [Fact] + public async Task TestClassWithCallbacks() + { + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new ClassWithCallbacks())); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(@"{""Func"":{},""Action"":{}")); + } + + public class ClassWithIgnoredCallbacks + { + [JsonIgnore] + public Func Func { get; set; } = (val) => false; + + [JsonIgnore] + public Action Action { get; set; } + } + + public class ClassWithCallbacks + { + public Func Func { get; set; } + + public Action Action { get; set; } = (val) => Console.WriteLine(); + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/SampleTestData.OrderPayload.cs b/src/libraries/System.Text.Json/tests/Common/SampleTestData.OrderPayload.cs similarity index 100% rename from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/SampleTestData.OrderPayload.cs rename to src/libraries/System.Text.Json/tests/Common/SampleTestData.OrderPayload.cs diff --git a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs index 0d2749c7b13ca6..890d61f97245d1 100644 --- a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs @@ -923,7 +923,7 @@ public class NullArgTester_Mutable public int Int { get; set; } } - public class ClassWithConstructor_SimpleAndComplexParameters : ITestClassWithParameterizedCtor + public class ObjWCtorMixedParams : ITestClassWithParameterizedCtor { public byte MyByte { get; } public sbyte MySByte { get; set; } @@ -961,7 +961,7 @@ public class ClassWithConstructor_SimpleAndComplexParameters : ITestClassWithPar public ImmutableSortedSet MyStringImmutableSortedSetT { get; } public List MyListOfNullString { get; } - public ClassWithConstructor_SimpleAndComplexParameters( + public ObjWCtorMixedParams( byte myByte, char myChar, string myString, @@ -1011,8 +1011,8 @@ public ClassWithConstructor_SimpleAndComplexParameters( MyListOfNullString = myListOfNullString; } - public static ClassWithConstructor_SimpleAndComplexParameters GetInstance() => - JsonSerializer.Deserialize(s_json); + public static ObjWCtorMixedParams GetInstance() => + JsonSerializer.Deserialize(s_json); public static string s_json => $"{{{s_partialJson1},{s_partialJson2}}}"; @@ -1849,23 +1849,23 @@ public class CampaignSummaryViewModel public class Parameterized_Class_With_ComplexTuple : ITestClassWithParameterizedCtor { public Tuple< - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters> MyTuple { get; } + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams> MyTuple { get; } public Parameterized_Class_With_ComplexTuple( Tuple< - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters, - ClassWithConstructor_SimpleAndComplexParameters> myTuple) => MyTuple = myTuple; + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams, + ObjWCtorMixedParams> myTuple) => MyTuple = myTuple; private const string s_inner_json = @" { diff --git a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs new file mode 100644 index 00000000000000..35359cafd159bd --- /dev/null +++ b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs @@ -0,0 +1,272 @@ +// 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.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.Text.Json.Serialization.Tests +{ + public abstract class UnsupportedTypesTests : SerializerTests + { + private bool SupportsJsonPathOnSerialize { get; init; } + + public UnsupportedTypesTests( + JsonSerializerWrapperForString serializerWrapper, + bool supportsJsonPathOnSerialize) : base(serializerWrapper) + { + SupportsJsonPathOnSerialize = supportsJsonPathOnSerialize; + } + + [Fact] + public async Task DeserializeUnsupportedType() + { + // Any test payload is fine. + string json = @"""Some string"""; + + await RunTest(json); + await RunTest(json); + await RunTest(json); + await RunTest(json); // One nullable variation. + await RunTest(json); +#if NETCOREAPP + await RunTest(json); + await RunTest(json); +#endif +#if BUILDING_SOURCE_GENERATOR_TESTS + await RunTest>(json); + await RunTest(json); +#endif + + async Task RunTest(string json) + { + Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); + string fullName = type.FullName; + + NotSupportedException ex = await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json)); + string exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + Assert.Contains("$", exAsStr); + + json = $@"{{""Prop"":{json}}}"; + + ex = await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper>(json)); + exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + Assert.Contains("$.Prop", exAsStr); + + // Verify Nullable<> semantics. NSE is not thrown because the serializer handles null. + if (isNullableOfT) + { + Assert.Null(JsonSerializer.Deserialize("null")); + + json = $@"{{""Prop"":null}}"; + ClassWithType obj = await JsonSerializerWrapperForString.DeserializeWrapper>(json); + Assert.Null(obj.Prop); + } + } + } + + [Fact] + public async Task SerializeUnsupportedType() + { + await RunTest(typeof(int)); + await RunTest(new SerializationInfo(typeof(Type), new FormatterConverter())); + await RunTest((IntPtr)123); + await RunTest(new IntPtr(123)); // One nullable variation. + await RunTest((UIntPtr)123); +#if NETCOREAPP + await RunTest(DateOnly.MaxValue); + await RunTest(TimeOnly.MinValue); +#endif +#if BUILDING_SOURCE_GENERATOR_TESTS + await RunTest(new ClassThatImplementsIAsyncEnumerable()); +#endif + + async Task RunTest(T value) + { + Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); + string fullName = type.FullName; + + NotSupportedException ex = await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(value)); + string exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + Assert.Contains("$", exAsStr); + + ClassWithType obj = new ClassWithType { Prop = value }; + + ex = await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj)); + exAsStr = ex.ToString(); + Assert.Contains(fullName, exAsStr); + + if (SupportsJsonPathOnSerialize) + { + Assert.Contains("$.Prop", exAsStr); + } + else + { + Assert.Contains("$.", exAsStr); + Assert.DoesNotContain("$.Prop", exAsStr); + } + + // Verify null semantics. NSE is not thrown because the serializer handles null. + if (!type.IsValueType || isNullableOfT) + { + string serialized = await JsonSerializerWrapperForString.SerializeWrapper((T)(object)null); + Assert.Equal("null", serialized); + + obj.Prop = (T)(object)null; + serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(@"{""Prop"":null}", serialized); + + serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj, new JsonSerializerOptions { IgnoreNullValues = true }); + Assert.Equal(@"{}", serialized); + } + } + } + + public class ClassWithIntPtr + { + public IntPtr MyIntPtr { get; set; } + } + + public class ClassWithIntPtrConverter + { + [JsonConverter(typeof(IntPtrConverter))] + public IntPtr MyIntPtr { get; set; } + } + + public class IntPtrConverter : JsonConverter + { + public override IntPtr Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + int value = reader.GetInt32(); + return new IntPtr(value); + } + + public override void Write(Utf8JsonWriter writer, IntPtr value, JsonSerializerOptions options) + { + writer.WriteNumberValue(value.ToInt32()); + } + } + + [Fact] + public async Task RuntimeConverterIsSupported_IntPtr() + { + const string Json = "{\"MyIntPtr\":42}"; + string serialized; + JsonSerializerOptions options = new(); + options.Converters.Add(new IntPtrConverter()); + + serialized = await JsonSerializerWrapperForString.SerializeWrapper(new IntPtr(42), options); + Assert.Equal("42", serialized); + + IntPtr intPtr = await JsonSerializerWrapperForString.DeserializeWrapper("42", options); + Assert.Equal(42, intPtr.ToInt32()); + + ClassWithIntPtr obj = new() { MyIntPtr = new IntPtr(42) }; + serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Equal(Json, serialized); + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(Json, options); + Assert.Equal(42, obj.MyIntPtr.ToInt32()); + } + + [Fact] + public async Task CompileTimeConverterIsSupported_IntPtr() + { + const string Json = "{\"MyIntPtr\":42}"; + + ClassWithIntPtrConverter obj = new() { MyIntPtr = new IntPtr(42) }; + string serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(Json, serialized); + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(Json); + Assert.Equal(42, obj.MyIntPtr.ToInt32()); + } + + public class ClassWithAsyncEnumerableConverter + { + [JsonConverter(typeof(AsyncEnumerableConverter))] + public ClassThatImplementsIAsyncEnumerable MyAsyncEnumerable { get; set; } + } + + public class ClassThatImplementsIAsyncEnumerable : IAsyncEnumerable + { + public string Status { get; set; } = "Created"; + + // Should not be called. + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) => throw new NotImplementedException(); + } + + public class AsyncEnumerableConverter : JsonConverter + { + public override ClassThatImplementsIAsyncEnumerable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Assert.Equal(JsonTokenType.StartArray, reader.TokenType); + reader.Read(); + Assert.Equal(JsonTokenType.EndArray, reader.TokenType); + return new ClassThatImplementsIAsyncEnumerable { Status = "Read" }; + } + + public override void Write(Utf8JsonWriter writer, ClassThatImplementsIAsyncEnumerable value, JsonSerializerOptions options) + { + writer.WriteStartArray(); + writer.WriteEndArray(); + value.Status = "Write"; + } + } + + [Fact] + public async Task RuntimeConverterIsSupported_AsyncEnumerable() + { + const string Json = "{\"MyAsyncEnumerable\":[]}"; + + string serialized; + JsonSerializerOptions options = new(); + options.Converters.Add(new AsyncEnumerableConverter()); + + ClassThatImplementsIAsyncEnumerable obj = new(); + Assert.Equal("Created", obj.Status); + serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj, options); + Assert.Equal("[]", serialized); + Assert.Equal("Write", obj.Status); + obj = await JsonSerializerWrapperForString.DeserializeWrapper("[]", options); + Assert.Equal("Read", obj.Status); + + ClassWithAsyncEnumerableConverter poco = new(); + poco.MyAsyncEnumerable = new(); + Assert.Equal("Created", poco.MyAsyncEnumerable.Status); + serialized = await JsonSerializerWrapperForString.SerializeWrapper(poco, options); + Assert.Equal(Json, serialized); + Assert.Equal("Write", poco.MyAsyncEnumerable.Status); + poco = await JsonSerializerWrapperForString.DeserializeWrapper(Json, options); + Assert.Equal("Read", poco.MyAsyncEnumerable.Status); + } + + [Fact] + public async Task CompileTimeConverterIsSupported_AsyncEnumerable() + { + const string Json = "{\"MyAsyncEnumerable\":[]}"; + + ClassWithAsyncEnumerableConverter obj = new(); + obj.MyAsyncEnumerable = new(); + Assert.Equal("Created", obj.MyAsyncEnumerable.Status); + + string serialized = await JsonSerializerWrapperForString.SerializeWrapper(obj); + Assert.Equal(Json, serialized); + Assert.Equal("Write", obj.MyAsyncEnumerable.Status); + + obj = await JsonSerializerWrapperForString.DeserializeWrapper(Json); + Assert.Equal("Read", obj.MyAsyncEnumerable.Status); + } + + public static Type GetNullableOfTUnderlyingType(Type type, out bool isNullableOfT) + { + isNullableOfT = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); + return isNullableOfT ? type.GetGenericArguments()[0] : type; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn3.11.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn3.11.csproj new file mode 100644 index 00000000000000..367b28d96d3717 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn3.11.csproj @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.0.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.0.csproj new file mode 100644 index 00000000000000..138741ea7741a8 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.Roslyn4.0.csproj @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.targets new file mode 100644 index 00000000000000..bf1d9e18c74a03 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/System.Text.Json.TestLibrary.targets @@ -0,0 +1,17 @@ + + + netstandard2.0 + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs new file mode 100644 index 00000000000000..a0eebf2e4fd383 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs @@ -0,0 +1,17 @@ +// 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.Json.Serialization; + +namespace System.Text.Json.SourceGeneration.Tests.NETStandard +{ + public class MyPoco + { + public string Value { get; set; } + } + + [JsonSerializable(typeof(MyPoco))] + public partial class NETStandardSerializerContext : JsonSerializerContext + { + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs index 72af4d22fe3faa..d7a76e4817b668 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Reflection; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; @@ -9,6 +10,9 @@ namespace System.Text.Json.SourceGeneration.Tests { public interface ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode { get; } + public bool IsIncludeFieldsEnabled => GetType().GetCustomAttribute()?.IncludeFields ?? false; + public JsonTypeInfo Location { get; } public JsonTypeInfo NumberTypes { get; } public JsonTypeInfo RepeatedLocation { get; } @@ -27,8 +31,21 @@ public interface ITestContext public JsonTypeInfo MyNestedClass { get; } public JsonTypeInfo MyNestedNestedClass { get; } public JsonTypeInfo ObjectArray { get; } + public JsonTypeInfo ByteArray { get; } public JsonTypeInfo String { get; } + public JsonTypeInfo<(string Label1, int Label2, bool)> ValueTupleStringInt32Boolean { get; } public JsonTypeInfo ClassWithEnumAndNullable { get; } + public JsonTypeInfo ClassWithNullableProperties { get; } + public JsonTypeInfo ClassWithCustomConverter { get; } + public JsonTypeInfo StructWithCustomConverter { get; } + public JsonTypeInfo ClassWithCustomConverterFactory { get; } + public JsonTypeInfo StructWithCustomConverterFactory { get; } + public JsonTypeInfo ClassWithCustomConverterProperty { get; } + public JsonTypeInfo StructWithCustomConverterProperty { get; } + public JsonTypeInfo ClassWithCustomConverterFactoryProperty { get; } + public JsonTypeInfo StructWithCustomConverterFactoryProperty { get; } + public JsonTypeInfo ClassWithBadCustomConverter { get; } + public JsonTypeInfo StructWithBadCustomConverter { get; } } internal partial class JsonContext : JsonSerializerContext @@ -42,14 +59,16 @@ internal partial class JsonContext : JsonSerializerContext private static JsonContext s_defaultContext; public static JsonContext Default => s_defaultContext ??= new JsonContext(new JsonSerializerOptions(s_defaultOptions)); - public JsonContext() : base(null, s_defaultOptions) + public JsonContext() : base(null) { } - public JsonContext(JsonSerializerOptions options) : base(options, s_defaultOptions) + public JsonContext(JsonSerializerOptions options) : base(options) { } + protected override JsonSerializerOptions? GeneratedSerializerOptions => s_defaultOptions; + public override JsonTypeInfo GetTypeInfo(global::System.Type type) { if (type == typeof(JsonMessage)) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs index 49deae9acadd78..7bc91507d9ad53 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.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.Collections.Generic; using System.Reflection; using System.Text.Json.Serialization; using Microsoft.DotNet.RemoteExecutor; @@ -89,5 +90,44 @@ internal record Person(string FirstName, string LastName); internal partial class PersonJsonContext : JsonSerializerContext { } + + // Regression test for https://github.com/dotnet/runtime/issues/62079 + [Fact] + public static void SupportsPropertiesWithCustomConverterFactory() + { + var value = new ClassWithCustomConverterFactoryProperty { MyEnum = Serialization.Tests.SampleEnum.MinZero }; + string json = JsonSerializer.Serialize(value, SingleClassWithCustomConverterFactoryPropertyContext.Default.ClassWithCustomConverterFactoryProperty); + Assert.Equal(@"{""MyEnum"":""MinZero""}", json); + } + + public class ParentClass + { + public ClassWithCustomConverterFactoryProperty? Child { get; set; } + } + + [JsonSerializable(typeof(ParentClass))] + internal partial class SingleClassWithCustomConverterFactoryPropertyContext : JsonSerializerContext + { + } + + // Regression test for https://github.com/dotnet/runtime/issues/61860 + [Fact] + public static void SupportsGenericParameterWithCustomConverterFactory() + { + var value = new List { TestEnum.Cee }; + string json = JsonSerializer.Serialize(value, GenericParameterWithCustomConverterFactoryContext.Default.ListTestEnum); + Assert.Equal(@"[""Cee""]", json); + } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum TestEnum + { + Aye, Bee, Cee + } + + [JsonSerializable(typeof(List))] + internal partial class GenericParameterWithCustomConverterFactoryContext : JsonSerializerContext + { + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs index c924e5af8ccf37..2c7d518e87a7bd 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs @@ -22,13 +22,27 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(MyTypeWithPropertyOrdering))] [JsonSerializable(typeof(MyIntermediateType))] [JsonSerializable(typeof(HighLowTempsImmutable))] + [JsonSerializable(typeof(byte[]))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))] [JsonSerializable(typeof(object[]))] [JsonSerializable(typeof(string))] + [JsonSerializable(typeof((string Label1, int Label2, bool)))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] + [JsonSerializable(typeof(ClassWithCustomConverter))] + [JsonSerializable(typeof(StructWithCustomConverter))] + [JsonSerializable(typeof(ClassWithCustomConverterFactory))] + [JsonSerializable(typeof(StructWithCustomConverterFactory))] + [JsonSerializable(typeof(ClassWithCustomConverterProperty))] + [JsonSerializable(typeof(StructWithCustomConverterProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(ClassWithBadCustomConverter))] + [JsonSerializable(typeof(StructWithBadCustomConverter))] internal partial class MetadataAndSerializationContext : JsonSerializerContext, ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Default; } public sealed class MetadataAndSerializationContextTests : RealWorldContextTests @@ -38,26 +52,39 @@ public sealed class MetadataAndSerializationContextTests : RealWorldContextTests [Fact] public override void EnsureFastPathGeneratedAsExpected() { - Assert.NotNull(MetadataAndSerializationContext.Default.Location.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.NumberTypes.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.RepeatedLocation.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.ActiveOrUpcomingEvent.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.CampaignSummaryViewModel.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.IndexViewModel.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.WeatherForecastWithPOCOs.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.EmptyPoco.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTemps.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyType.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyType2.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithCallbacks.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithPropertyOrdering.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyIntermediateType.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTempsImmutable.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedClass.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedNestedClass.Serialize); - Assert.Null(MetadataAndSerializationContext.Default.ObjectArray.Serialize); - Assert.Null(MetadataAndSerializationContext.Default.String.Serialize); - Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithEnumAndNullable.Serialize); + Assert.NotNull(MetadataAndSerializationContext.Default.Location.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.NumberTypes.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.RepeatedLocation.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.ActiveOrUpcomingEvent.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.CampaignSummaryViewModel.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.IndexViewModel.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.WeatherForecastWithPOCOs.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.EmptyPoco.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTemps.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyType.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyType2.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithCallbacks.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithPropertyOrdering.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyIntermediateType.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTempsImmutable.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedClass.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedNestedClass.SerializeHandler); + Assert.Null(MetadataAndSerializationContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MetadataAndSerializationContext.Default.SampleEnum.SerializeHandler); + Assert.Null(MetadataAndSerializationContext.Default.String.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithEnumAndNullable.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithNullableProperties.SerializeHandler); + Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverter); + Assert.NotNull(MetadataAndSerializationContext.Default.StructWithCustomConverter); + Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverterFactory); + Assert.NotNull(MetadataAndSerializationContext.Default.StructWithCustomConverterFactory); + Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverterProperty); + Assert.NotNull(MetadataAndSerializationContext.Default.StructWithCustomConverterProperty); + Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverterFactoryProperty); + Assert.NotNull(MetadataAndSerializationContext.Default.StructWithCustomConverterFactoryProperty); + Assert.Throws(() => MetadataAndSerializationContext.Default.ClassWithBadCustomConverter); + Assert.Throws(() => MetadataAndSerializationContext.Default.StructWithBadCustomConverter); } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs index e6d1fd754f10aa..4d3323cb7f9b3c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs @@ -24,10 +24,24 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(StructWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] internal partial class MetadataWithPerTypeAttributeContext : JsonSerializerContext, ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Metadata; } public sealed class MetadataWithPerTypeAttributeContextTests : RealWorldContextTests @@ -37,28 +51,42 @@ public sealed class MetadataWithPerTypeAttributeContextTests : RealWorldContextT [Fact] public override void EnsureFastPathGeneratedAsExpected() { - Assert.Null(MetadataWithPerTypeAttributeContext.Default.Location.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.RepeatedLocation.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.NumberTypes.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.IndexViewModel.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.EmptyPoco.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTemps.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType2.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyIntermediateType.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTempsImmutable.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedClass.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedNestedClass.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.ObjectArray.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.String.Serialize); - Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.Location.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.RepeatedLocation.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.NumberTypes.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.IndexViewModel.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.EmptyPoco.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTemps.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType2.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyIntermediateType.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTempsImmutable.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedClass.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedNestedClass.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ByteArray.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.SampleEnum.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.String.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithNullableProperties.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverter.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverter.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactory.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterFactory.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterProperty.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterProperty.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Throws(() => MetadataWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => MetadataWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler); } } - [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata, IncludeFields = true)] [JsonSerializable(typeof(Location))] [JsonSerializable(typeof(RepeatedTypes.Location), TypeInfoPropertyName = "RepeatedLocation")] [JsonSerializable(typeof(NumberTypes))] @@ -77,9 +105,44 @@ public override void EnsureFastPathGeneratedAsExpected() [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))] [JsonSerializable(typeof(object[]))] + [JsonSerializable(typeof(byte[]))] [JsonSerializable(typeof(string))] + [JsonSerializable(typeof((string Label1, int Label2, bool)))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] + [JsonSerializable(typeof(ClassWithCustomConverter))] + [JsonSerializable(typeof(StructWithCustomConverter))] + [JsonSerializable(typeof(ClassWithCustomConverterFactory))] + [JsonSerializable(typeof(StructWithCustomConverterFactory))] + [JsonSerializable(typeof(ClassWithCustomConverterProperty))] + [JsonSerializable(typeof(StructWithCustomConverterProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(ClassWithBadCustomConverter))] + [JsonSerializable(typeof(StructWithBadCustomConverter))] internal partial class MetadataContext : JsonSerializerContext, ITestContext + { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Metadata; + } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum EnumWrittenAsString + { + A = 1 + } + + [JsonSerializable(typeof(EnumWrittenAsString))] + public partial class ContextWithExplicitStringEnum : JsonSerializerContext + { + } + + public class PocoWithEnum + { + public EnumWrittenAsString MyEnum { get; set; } + } + + [JsonSerializable(typeof(PocoWithEnum))] + public partial class ContextWithImplicitStringEnum : JsonSerializerContext { } @@ -90,26 +153,77 @@ public sealed class MetadataContextTests : RealWorldContextTests [Fact] public override void EnsureFastPathGeneratedAsExpected() { - Assert.Null(MetadataContext.Default.Location.Serialize); - Assert.Null(MetadataContext.Default.RepeatedLocation.Serialize); - Assert.Null(MetadataContext.Default.NumberTypes.Serialize); - Assert.Null(MetadataContext.Default.ActiveOrUpcomingEvent.Serialize); - Assert.Null(MetadataContext.Default.CampaignSummaryViewModel.Serialize); - Assert.Null(MetadataContext.Default.IndexViewModel.Serialize); - Assert.Null(MetadataContext.Default.WeatherForecastWithPOCOs.Serialize); - Assert.Null(MetadataContext.Default.EmptyPoco.Serialize); - Assert.Null(MetadataContext.Default.HighLowTemps.Serialize); - Assert.Null(MetadataContext.Default.MyType.Serialize); - Assert.Null(MetadataContext.Default.MyType2.Serialize); - Assert.Null(MetadataContext.Default.MyTypeWithCallbacks.Serialize); - Assert.Null(MetadataContext.Default.MyTypeWithPropertyOrdering.Serialize); - Assert.Null(MetadataContext.Default.MyIntermediateType.Serialize); - Assert.Null(MetadataContext.Default.HighLowTempsImmutable.Serialize); - Assert.Null(MetadataContext.Default.MyNestedClass.Serialize); - Assert.Null(MetadataContext.Default.MyNestedNestedClass.Serialize); - Assert.Null(MetadataContext.Default.ObjectArray.Serialize); - Assert.Null(MetadataContext.Default.String.Serialize); - Assert.Null(MetadataContext.Default.ClassWithEnumAndNullable.Serialize); + Assert.Null(MetadataContext.Default.Location.SerializeHandler); + Assert.Null(MetadataContext.Default.RepeatedLocation.SerializeHandler); + Assert.Null(MetadataContext.Default.NumberTypes.SerializeHandler); + Assert.Null(MetadataContext.Default.ActiveOrUpcomingEvent.SerializeHandler); + Assert.Null(MetadataContext.Default.CampaignSummaryViewModel.SerializeHandler); + Assert.Null(MetadataContext.Default.IndexViewModel.SerializeHandler); + Assert.Null(MetadataContext.Default.WeatherForecastWithPOCOs.SerializeHandler); + Assert.Null(MetadataContext.Default.EmptyPoco.SerializeHandler); + Assert.Null(MetadataContext.Default.HighLowTemps.SerializeHandler); + Assert.Null(MetadataContext.Default.MyType.SerializeHandler); + Assert.Null(MetadataContext.Default.MyType2.SerializeHandler); + Assert.Null(MetadataContext.Default.MyTypeWithCallbacks.SerializeHandler); + Assert.Null(MetadataContext.Default.MyTypeWithPropertyOrdering.SerializeHandler); + Assert.Null(MetadataContext.Default.MyIntermediateType.SerializeHandler); + Assert.Null(MetadataContext.Default.HighLowTempsImmutable.SerializeHandler); + Assert.Null(MetadataContext.Default.MyNestedClass.SerializeHandler); + Assert.Null(MetadataContext.Default.MyNestedNestedClass.SerializeHandler); + Assert.Null(MetadataContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MetadataContext.Default.ByteArray.SerializeHandler); + Assert.Null(MetadataContext.Default.SampleEnum.SerializeHandler); + Assert.Null(MetadataContext.Default.String.SerializeHandler); + Assert.Null(MetadataContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); + Assert.Null(MetadataContext.Default.ClassWithEnumAndNullable.SerializeHandler); + Assert.Null(MetadataContext.Default.ClassWithNullableProperties.SerializeHandler); + Assert.Null(MetadataContext.Default.ClassWithCustomConverter.SerializeHandler); + Assert.Null(MetadataContext.Default.StructWithCustomConverter.SerializeHandler); + Assert.Null(MetadataContext.Default.ClassWithCustomConverterFactory.SerializeHandler); + Assert.Null(MetadataContext.Default.StructWithCustomConverterFactory.SerializeHandler); + Assert.Null(MetadataContext.Default.ClassWithCustomConverterProperty.SerializeHandler); + Assert.Null(MetadataContext.Default.StructWithCustomConverterProperty.SerializeHandler); + Assert.Null(MetadataContext.Default.ClassWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Null(MetadataContext.Default.StructWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Throws(() => MetadataContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => MetadataContext.Default.StructWithBadCustomConverter.SerializeHandler); + } + + [Fact] + public void EnsureHelperMethodGenerated_TypeFactory() + { + // There are 2 helper methods generated for obtaining a converter from a factory: + // - JsonConverter version that is property-based (that calls the one below) + // - JsonConverter version that is Type-based + // and this test verifies the latter one is generated. Other tests also have property-level + // factories and thus verify both are created. + + const string Json = "\"A\""; + + EnumWrittenAsString obj = EnumWrittenAsString.A; + + string json = JsonSerializer.Serialize(obj, ContextWithExplicitStringEnum.Default.EnumWrittenAsString); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, ContextWithExplicitStringEnum.Default.EnumWrittenAsString); + Assert.Equal(EnumWrittenAsString.A, obj); + } + + [Fact] + public void EnsureHelperMethodGenerated_ImplicitPropertyFactory() + { + // ContextWithImplicitStringEnum does not have an entry for EnumWrittenAsString since it is + // implictly added by PocoWithEnum. Verify helper methods are still being created properly. + + const string Json = "{\"MyEnum\":\"A\"}"; + + PocoWithEnum obj = new() { MyEnum = EnumWrittenAsString.A }; + + string json = JsonSerializer.Serialize(obj, ContextWithImplicitStringEnum.Default.PocoWithEnum); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, ContextWithImplicitStringEnum.Default.PocoWithEnum); + Assert.Equal(EnumWrittenAsString.A, obj.MyEnum); } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs index 64371e837de2ab..afdb3f93184193 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs @@ -6,6 +6,7 @@ namespace System.Text.Json.SourceGeneration.Tests { + [JsonSourceGenerationOptions(IncludeFields = true)] [JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(RepeatedTypes.Location), TypeInfoPropertyName = "RepeatedLocation", GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(NumberTypes), GenerationMode = JsonSourceGenerationMode.Metadata)] @@ -24,10 +25,24 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] internal partial class MixedModeContext : JsonSerializerContext, ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization; } public sealed class MixedModeContextTests : RealWorldContextTests @@ -37,25 +52,39 @@ public sealed class MixedModeContextTests : RealWorldContextTests [Fact] public override void EnsureFastPathGeneratedAsExpected() { - Assert.Null(MixedModeContext.Default.Location.Serialize); - Assert.NotNull(MixedModeContext.Default.RepeatedLocation.Serialize); - Assert.Null(MixedModeContext.Default.NumberTypes.Serialize); - Assert.NotNull(MixedModeContext.Default.CampaignSummaryViewModel.Serialize); - Assert.Null(MixedModeContext.Default.IndexViewModel.Serialize); - Assert.Null(MixedModeContext.Default.WeatherForecastWithPOCOs.Serialize); - Assert.NotNull(MixedModeContext.Default.EmptyPoco.Serialize); - Assert.NotNull(MixedModeContext.Default.HighLowTemps.Serialize); - Assert.NotNull(MixedModeContext.Default.MyType.Serialize); - Assert.NotNull(MixedModeContext.Default.MyType2.Serialize); - Assert.NotNull(MixedModeContext.Default.MyTypeWithCallbacks.Serialize); - Assert.NotNull(MixedModeContext.Default.MyTypeWithPropertyOrdering.Serialize); - Assert.NotNull(MixedModeContext.Default.MyIntermediateType.Serialize); - Assert.Null(MixedModeContext.Default.HighLowTempsImmutable.Serialize); - Assert.NotNull(MixedModeContext.Default.MyNestedClass.Serialize); - Assert.NotNull(MixedModeContext.Default.MyNestedNestedClass.Serialize); - Assert.Null(MixedModeContext.Default.ObjectArray.Serialize); - Assert.Null(MixedModeContext.Default.String.Serialize); - Assert.NotNull(MixedModeContext.Default.ClassWithEnumAndNullable.Serialize); + Assert.Null(MixedModeContext.Default.Location.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.RepeatedLocation.SerializeHandler); + Assert.Null(MixedModeContext.Default.NumberTypes.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.CampaignSummaryViewModel.SerializeHandler); + Assert.Null(MixedModeContext.Default.IndexViewModel.SerializeHandler); + Assert.Null(MixedModeContext.Default.WeatherForecastWithPOCOs.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.EmptyPoco.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.HighLowTemps.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyType.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyType2.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyTypeWithCallbacks.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyTypeWithPropertyOrdering.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyIntermediateType.SerializeHandler); + Assert.Null(MixedModeContext.Default.HighLowTempsImmutable.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyNestedClass.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.MyNestedNestedClass.SerializeHandler); + Assert.Null(MixedModeContext.Default.ObjectArray.SerializeHandler); + Assert.Null(MixedModeContext.Default.ByteArray.SerializeHandler); + Assert.Null(MixedModeContext.Default.SampleEnum.SerializeHandler); + Assert.Null(MixedModeContext.Default.String.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.ClassWithEnumAndNullable.SerializeHandler); + Assert.NotNull(MixedModeContext.Default.ClassWithNullableProperties.SerializeHandler); + Assert.Null(MixedModeContext.Default.ClassWithCustomConverter.SerializeHandler); + Assert.Null(MixedModeContext.Default.StructWithCustomConverter.SerializeHandler); + Assert.Null(MixedModeContext.Default.ClassWithCustomConverterFactory.SerializeHandler); + Assert.Null(MixedModeContext.Default.StructWithCustomConverterFactory.SerializeHandler); + Assert.Null(MixedModeContext.Default.ClassWithCustomConverterProperty.SerializeHandler); + Assert.Null(MixedModeContext.Default.StructWithCustomConverterProperty.SerializeHandler); + Assert.Null(MixedModeContext.Default.ClassWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Null(MixedModeContext.Default.StructWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Throws(() => MixedModeContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => MixedModeContext.Default.StructWithBadCustomConverter.SerializeHandler); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/NETStandardContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/NETStandardContextTests.cs new file mode 100644 index 00000000000000..557473b603b7de --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/NETStandardContextTests.cs @@ -0,0 +1,31 @@ +// 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.IO; +using System.Linq; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; +using Xunit; + +namespace System.Text.Json.SourceGeneration.Tests.NETStandard +{ + public class NETStandardContextTests + { + /// + /// Tests that we can serialize and deserialize a type defined in a NETStandard assembly. + /// This tests an issue where we were emitting source-gen logic that caused the compiler + /// to emit a reference to an internal definition of IsExternalInit that was missing + /// on later versions of .NET (since it was defined by the framework). + /// + [Fact] + public void RoundTripNETStandardDefinedSourceGenType() + { + MyPoco expected = new MyPoco() { Value = "Hello from NETStandard type."}; + + string json = JsonSerializer.Serialize(expected, NETStandardSerializerContext.Default.MyPoco); + MyPoco actual = JsonSerializer.Deserialize(json, NETStandardSerializerContext.Default.MyPoco); + Assert.Equal(expected.Value, actual.Value); + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs index ca941bea915903..1e2a9e5fe6be45 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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; @@ -6,6 +6,7 @@ using System.Linq; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; +using System.Text.Json.Serialization.Tests; using Xunit; namespace System.Text.Json.SourceGeneration.Tests @@ -110,6 +111,222 @@ public virtual void RoundTripTypeNameClash() VerifyRepeatedLocation(expected, obj); } + [Fact] + public virtual void RoundTripValueTuple() + { + bool isIncludeFieldsEnabled = DefaultContext.IsIncludeFieldsEnabled; + + var tuple = (Label1: "string", Label2: 42, true); + string expectedJson = isIncludeFieldsEnabled + ? "{\"Item1\":\"string\",\"Item2\":42,\"Item3\":true}" + : "{}"; + + string json = JsonSerializer.Serialize(tuple, DefaultContext.ValueTupleStringInt32Boolean); + Assert.Equal(expectedJson, json); + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + // Deserialization not supported in fast path serialization only mode + Assert.Throws(() => JsonSerializer.Deserialize(json, DefaultContext.ValueTupleStringInt32Boolean)); + } + else + { + var deserializedTuple = JsonSerializer.Deserialize(json, DefaultContext.ValueTupleStringInt32Boolean); + Assert.Equal(isIncludeFieldsEnabled ? tuple : default, deserializedTuple); + } + } + + [Fact] + public virtual void RoundTripWithCustomConverter_Class() + { + const string Json = "{\"MyInt\":142}"; + + ClassWithCustomConverter obj = new ClassWithCustomConverter() + { + MyInt = 42 + }; + + string json = JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverter); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, DefaultContext.ClassWithCustomConverter); + Assert.Equal(42, obj.MyInt); + } + + [Fact] + public virtual void RoundTripWithCustomConverterFactory_Class() + { + const string Json = "{\"MyInt\":142}"; + + ClassWithCustomConverterFactory obj = new() + { + MyInt = 42 + }; + + string json = JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterFactory); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, DefaultContext.ClassWithCustomConverterFactory); + Assert.Equal(42, obj.MyInt); + } + + [Fact] + public virtual void RoundTripWithCustomConverter_Struct() + { + const string Json = "{\"MyInt\":142}"; + + StructWithCustomConverter obj = new StructWithCustomConverter() + { + MyInt = 42 + }; + + string json = JsonSerializer.Serialize(obj, DefaultContext.StructWithCustomConverter); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, DefaultContext.StructWithCustomConverter); + Assert.Equal(42, obj.MyInt); + } + + [Fact] + public virtual void RoundtripWithCustomConverterProperty_Class() + { + const string ExpectedJson = "{\"Property\":42}"; + + ClassWithCustomConverterProperty obj = new() + { + Property = new ClassWithCustomConverterProperty.NestedPoco { Value = 42 } + }; + + // Types with properties in custom converters do not support fast path serialization. + Assert.True(DefaultContext.ClassWithCustomConverterProperty.SerializeHandler is null); + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterProperty)); + } + else + { + string json = JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterProperty); + Assert.Equal(ExpectedJson, json); + } + + obj = JsonSerializer.Deserialize(ExpectedJson); + Assert.Equal(42, obj.Property.Value); + } + + [Fact] + public virtual void RoundtripWithCustomConverterProperty_Struct() + { + const string ExpectedJson = "{\"Property\":42}"; + + StructWithCustomConverterProperty obj = new() + { + Property = new ClassWithCustomConverterProperty.NestedPoco { Value = 42 } + }; + + // Types with properties in custom converters do not support fast path serialization. + Assert.True(DefaultContext.StructWithCustomConverterProperty.SerializeHandler is null); + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.StructWithCustomConverterProperty)); + } + else + { + string json = JsonSerializer.Serialize(obj, DefaultContext.StructWithCustomConverterProperty); + Assert.Equal(ExpectedJson, json); + } + + obj = JsonSerializer.Deserialize(ExpectedJson); + Assert.Equal(42, obj.Property.Value); + } + + [Fact] + public virtual void RoundTripWithCustomPropertyConverterFactory_Class() + { + const string Json = "{\"MyEnum\":\"One\"}"; + + ClassWithCustomConverterFactoryProperty obj = new() + { + MyEnum = SampleEnum.One + }; + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterFactoryProperty)); + } + else + { + string json = JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterFactoryProperty); + Assert.Equal(Json, json); + } + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterFactoryProperty)); + } + else + { + obj = JsonSerializer.Deserialize(Json, DefaultContext.ClassWithCustomConverterFactoryProperty); + Assert.Equal(SampleEnum.One, obj.MyEnum); + } + } + + [Fact] + public virtual void RoundTripWithCustomPropertyConverterFactory_Struct() + { + const string Json = "{\"MyEnum\":\"One\"}"; + + StructWithCustomConverterFactoryProperty obj = new() + { + MyEnum = SampleEnum.One + }; + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.StructWithCustomConverterFactoryProperty)); + } + else + { + string json = JsonSerializer.Serialize(obj, DefaultContext.StructWithCustomConverterFactoryProperty); + Assert.Equal(Json, json); + } + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.StructWithCustomConverterFactoryProperty)); + } + else + { + obj = JsonSerializer.Deserialize(Json, DefaultContext.StructWithCustomConverterFactoryProperty); + Assert.Equal(SampleEnum.One, obj.MyEnum); + } + } + + [Fact] + public virtual void BadCustomConverter_Class() + { + const string Json = "{\"MyInt\":142}"; + + Assert.Throws(() => + JsonSerializer.Serialize(new ClassWithBadCustomConverter(), DefaultContext.ClassWithBadCustomConverter)); + + Assert.Throws(() => + JsonSerializer.Deserialize(Json, DefaultContext.ClassWithBadCustomConverter)); + } + + [Fact] + public virtual void BadCustomConverter_Struct() + { + const string Json = "{\"MyInt\":142}"; + + Assert.Throws(() => + JsonSerializer.Serialize(new StructWithBadCustomConverter(), DefaultContext.StructWithBadCustomConverter)); + + Assert.Throws(() => + JsonSerializer.Deserialize(Json, DefaultContext.StructWithBadCustomConverter)); + } + protected static Location CreateLocation() { return new Location @@ -182,7 +399,8 @@ protected static ActiveOrUpcomingEvent CreateActiveOrUpcomingEvent() EndDate = DateTime.UtcNow.AddYears(1), Name = "Just a name", ImageUrl = "https://www.dotnetfoundation.org/theme/img/carousel/foundation-diagram-content.png", - StartDate = DateTime.UtcNow + StartDate = DateTime.UtcNow, + Offset = TimeSpan.FromHours(2) }; } @@ -196,6 +414,7 @@ protected static void VerifyActiveOrUpcomingEvent(ActiveOrUpcomingEvent expected Assert.Equal(expected.ImageUrl, obj.ImageUrl); Assert.Equal(expected.Name, obj.Name); Assert.Equal(expected.StartDate, obj.StartDate); + Assert.Equal(expected.Offset, obj.Offset); } protected static CampaignSummaryViewModel CreateCampaignSummaryViewModel() @@ -422,6 +641,19 @@ public virtual void SerializeObjectArray_SimpleTypes_WithCustomOptions() Assert.Equal("\"World\"", world.GetRawText()); } + [Fact] + public virtual void SerializeByteArray() + { + byte[] value = new byte[] { 1, 2, 3 }; + const string expectedJson = "\"AQID\""; + + string actualJson = JsonSerializer.Serialize(value, DefaultContext.ByteArray); + Assert.Equal(expectedJson, actualJson); + + byte[] arr = JsonSerializer.Deserialize(actualJson, DefaultContext.ByteArray); + Assert.Equal(value, arr); + } + [Fact] public virtual void HandlesNestedTypes() { @@ -517,6 +749,62 @@ public class ClassWithEnumAndNullable public DayOfWeek? NullableDay { get; set; } } + [Fact] + public virtual void ClassWithNullableProperties_Roundtrip() + { + RunTest(new ClassWithNullableProperties + { + Uri = new Uri("http://contoso.com"), + Array = new int[] { 42 }, + Poco = new ClassWithNullableProperties.MyPoco(), + + NullableUri = new Uri("http://contoso.com"), + NullableArray = new int[] { 42 }, + NullablePoco = new ClassWithNullableProperties.MyPoco() + }); + + RunTest(new ClassWithNullableProperties()); + + void RunTest(ClassWithNullableProperties expected) + { + string json = JsonSerializer.Serialize(expected, DefaultContext.ClassWithNullableProperties); + ClassWithNullableProperties actual = JsonSerializer.Deserialize(json, DefaultContext.ClassWithNullableProperties); + + Assert.Equal(expected.Uri, actual.Uri); + Assert.Equal(expected.Array, actual.Array); + Assert.Equal(expected.Poco, actual.Poco); + + Assert.Equal(expected.NullableUri, actual.NullableUri); + Assert.Equal(expected.NullableArray, actual.NullableArray); + Assert.Equal(expected.NullablePoco, actual.NullablePoco); + + Assert.Equal(expected.NullableUriParameter, actual.NullableUriParameter); + Assert.Equal(expected.NullableArrayParameter, actual.NullableArrayParameter); + Assert.Equal(expected.NullablePocoParameter, actual.NullablePocoParameter); + } + } + + public class ClassWithNullableProperties + { + public Uri Uri { get; set; } + public int[] Array { get; set; } + public MyPoco Poco { get; set; } + + public Uri? NullableUri { get; set; } + public int[]? NullableArray { get; set; } + public MyPoco? NullablePoco { get; set; } + + // struct types containing nullable reference types as generic parameters + public GenericStruct NullableUriParameter { get; set; } + public GenericStruct NullableArrayParameter { get; set; } + public GenericStruct NullablePocoParameter { get; set; } + + public (string? x, int y)? NullableArgumentOfNullableStruct { get; set; } + + public record MyPoco { } + public struct GenericStruct { } + } + private const string ExceptionMessageFromCustomContext = "Exception thrown from custom context."; [Fact] @@ -540,13 +828,15 @@ public void GetTypeInfoCalledDuringPolymorphicSerialization() internal class CustomContext : JsonSerializerContext { - public CustomContext(JsonSerializerOptions options) : base(options, null) { } + public CustomContext(JsonSerializerOptions options) : base(options) { } private JsonTypeInfo _object; public JsonTypeInfo Object => _object ??= JsonMetadataServices.CreateValueInfo(Options, JsonMetadataServices.ObjectConverter); private JsonTypeInfo _objectArray; - public JsonTypeInfo ObjectArray => _objectArray ??= JsonMetadataServices.CreateArrayInfo(Options, Object, default, serializeFunc: null); + public JsonTypeInfo ObjectArray => _objectArray ??= JsonMetadataServices.CreateArrayInfo(Options, new JsonCollectionInfoValues { ElementInfo = Object }); + + protected override JsonSerializerOptions? GeneratedSerializerOptions => null; public override JsonTypeInfo GetTypeInfo(Type type) { @@ -563,7 +853,7 @@ protected static void AssertFastPathLogicCorrect(string expectedJson, T value { using MemoryStream ms = new(); using Utf8JsonWriter writer = new(ms); - typeInfo.Serialize!(writer, value); + typeInfo.SerializeHandler!(writer, value); writer.Flush(); JsonTestHelper.AssertJsonEqual(expectedJson, Encoding.UTF8.GetString(ms.ToArray())); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs index 01a7e4d0e39f96..3f65e034f6768e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs @@ -49,7 +49,7 @@ protected ConstructorTests_Metadata(JsonSerializerWrapperForString stringWrapper [JsonSerializable(typeof(Parameterized_WrapperForICollection))] [JsonSerializable(typeof(Point_2D_Struct))] [JsonSerializable(typeof(Point_2D_Struct_WithAttribute))] - [JsonSerializable(typeof(ClassWithConstructor_SimpleAndComplexParameters))] + [JsonSerializable(typeof(ObjWCtorMixedParams))] [JsonSerializable(typeof(Person_Class))] [JsonSerializable(typeof(Point_2D))] [JsonSerializable(typeof(Point_MultipleMembers_BindTo_OneConstructorParameter))] @@ -123,6 +123,14 @@ protected ConstructorTests_Metadata(JsonSerializerWrapperForString stringWrapper [JsonSerializable(typeof(MyRecord))] [JsonSerializable(typeof(AgeRecord))] [JsonSerializable(typeof(JsonElement))] + [JsonSerializable(typeof(Parameterized_Class_With_ComplexTuple))] + [JsonSerializable(typeof(Parameterized_Person_Simple))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(ClassWithIgnoredSameType))] + [JsonSerializable(typeof(ClassWithDefaultCtorParams))] internal sealed partial class ConstructorTestsContext_Metadata : JsonSerializerContext { } @@ -163,7 +171,7 @@ public ConstructorTests_Default() [JsonSerializable(typeof(Parameterized_WrapperForICollection))] [JsonSerializable(typeof(Point_2D_Struct))] [JsonSerializable(typeof(Point_2D_Struct_WithAttribute))] - [JsonSerializable(typeof(ClassWithConstructor_SimpleAndComplexParameters))] + [JsonSerializable(typeof(ObjWCtorMixedParams))] [JsonSerializable(typeof(Person_Class))] [JsonSerializable(typeof(Point_2D))] [JsonSerializable(typeof(Point_MultipleMembers_BindTo_OneConstructorParameter))] @@ -237,6 +245,14 @@ public ConstructorTests_Default() [JsonSerializable(typeof(MyRecord))] [JsonSerializable(typeof(AgeRecord))] [JsonSerializable(typeof(JsonElement))] + [JsonSerializable(typeof(Parameterized_Class_With_ComplexTuple))] + [JsonSerializable(typeof(Parameterized_Person_Simple))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(SmallType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_ParamWithDefaultValue))] + [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))] + [JsonSerializable(typeof(ClassWithIgnoredSameType))] + [JsonSerializable(typeof(ClassWithDefaultCtorParams))] internal sealed partial class ConstructorTestsContext_Default : JsonSerializerContext { } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs new file mode 100644 index 00000000000000..22b67e71fe800a --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs @@ -0,0 +1,131 @@ +//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.Text.Json.Nodes; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Tests; + +namespace System.Text.Json.SourceGeneration.Tests +{ + public sealed partial class ExtensionDataTests_Metadata : ExtensionDataTests + { + public ExtensionDataTests_Metadata() + : base(new StringSerializerWrapper(ExtensionDataTestsContext_Metadata.Default, (options) => new ExtensionDataTestsContext_Metadata(options))) + { + } + + [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithEmptyPropertyNameAndExtensionProperty))] + [JsonSerializable(typeof(EmptyClassWithExtensionProperty))] + [JsonSerializable(typeof(ClassWithExtensionProperty))] + [JsonSerializable(typeof(ClassWithExtensionField))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsObject))] + [JsonSerializable(typeof(ClassWithIgnoredData))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(ExtensionDataTests))] + [JsonSerializable(typeof(DictionaryOverflowConverter))] + [JsonSerializable(typeof(JsonElementOverflowConverter))] + [JsonSerializable(typeof(CustomObjectDictionaryOverflowConverter))] + [JsonSerializable(typeof(CustomJsonElementDictionaryOverflowConverter))] + [JsonSerializable(typeof(ClassWithExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(ClassWithExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAlreadyInstantiated))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsObjectAndNameProperty))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsJsonObject))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsJsonElement))] + [JsonSerializable(typeof(ClassWithReference))] + [JsonSerializable(typeof(ParentClassWithObject))] + [JsonSerializable(typeof(ParentClassWithJsonElement))] + [JsonSerializable(typeof(ClassWithMultipleDictionaries))] + [JsonSerializable(typeof(ClassWithEscapedProperty))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsImmutable))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsImmutableJsonElement))] + [JsonSerializable(typeof(ClassWithExtensionPropertyPrivateConstructor))] + [JsonSerializable(typeof(ClassWithExtensionPropertyPrivateConstructorJsonElement))] + [JsonSerializable(typeof(ClassWithExtensionPropertyNoGenericParameters))] + [JsonSerializable(typeof(ClassWithExtensionPropertyOneGenericParameter))] + [JsonSerializable(typeof(ClassWithExtensionPropertyThreeGenericParameters))] + [JsonSerializable(typeof(JsonElement))] + [JsonSerializable(typeof(ClassWithExtensionData))] + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(DummyObj))] + [JsonSerializable(typeof(DummyStruct))] + internal sealed partial class ExtensionDataTestsContext_Metadata : JsonSerializerContext + { + } + } + + public sealed partial class ExtensionDataTests_Default : ExtensionDataTests + { + public ExtensionDataTests_Default() + : base(new StringSerializerWrapper(ExtensionDataTestsContext_Default.Default, (options) => new ExtensionDataTestsContext_Default(options))) + { + } + + [JsonSerializable(typeof(ClassWithEmptyPropertyNameAndExtensionProperty))] + [JsonSerializable(typeof(EmptyClassWithExtensionProperty))] + [JsonSerializable(typeof(ClassWithExtensionProperty))] + [JsonSerializable(typeof(ClassWithExtensionField))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsObject))] + [JsonSerializable(typeof(ClassWithIgnoredData))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(ExtensionDataTests))] + [JsonSerializable(typeof(DictionaryOverflowConverter))] + [JsonSerializable(typeof(JsonElementOverflowConverter))] + [JsonSerializable(typeof(CustomObjectDictionaryOverflowConverter))] + [JsonSerializable(typeof(CustomJsonElementDictionaryOverflowConverter))] + [JsonSerializable(typeof(ClassWithExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(CustomOverflowDictionary))] + [JsonSerializable(typeof(ClassWithExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAlreadyInstantiated))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsObjectAndNameProperty))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsJsonObject))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsJsonElement))] + [JsonSerializable(typeof(ClassWithReference))] + [JsonSerializable(typeof(ParentClassWithObject))] + [JsonSerializable(typeof(ParentClassWithJsonElement))] + [JsonSerializable(typeof(ClassWithMultipleDictionaries))] + [JsonSerializable(typeof(ClassWithEscapedProperty))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsImmutable))] + [JsonSerializable(typeof(ClassWithExtensionPropertyAsImmutableJsonElement))] + [JsonSerializable(typeof(ClassWithExtensionPropertyPrivateConstructor))] + [JsonSerializable(typeof(ClassWithExtensionPropertyPrivateConstructorJsonElement))] + [JsonSerializable(typeof(ClassWithExtensionPropertyNoGenericParameters))] + [JsonSerializable(typeof(ClassWithExtensionPropertyOneGenericParameter))] + [JsonSerializable(typeof(ClassWithExtensionPropertyThreeGenericParameters))] + [JsonSerializable(typeof(JsonElement))] + [JsonSerializable(typeof(ClassWithExtensionData))] + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(DummyObj))] + [JsonSerializable(typeof(DummyStruct))] + internal sealed partial class ExtensionDataTestsContext_Default : JsonSerializerContext + { + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs new file mode 100644 index 00000000000000..4a27daaf2ebc5b --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs @@ -0,0 +1,44 @@ +// 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.Text.Json.Nodes; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Tests; +using System.Text.Json.Serialization.Tests.Schemas.OrderPayload; + +namespace System.Text.Json.SourceGeneration.Tests +{ + public sealed partial class NodeInteropTests_Metadata : NodeInteropTests + { + public NodeInteropTests_Metadata() + : base(new StringSerializerWrapper(NodeInteropTestsContext_Metadata.Default, (options) => new NodeInteropTestsContext_Metadata(options))) + { + } + + [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(List))] + [JsonSerializable(typeof(JsonArray))] + [JsonSerializable(typeof(Poco))] + [JsonSerializable(typeof(string))] + internal sealed partial class NodeInteropTestsContext_Metadata : JsonSerializerContext + { + } + } + + public sealed partial class NodeInteropTests_Default : NodeInteropTests + { + public NodeInteropTests_Default() + : base(new StringSerializerWrapper(NodeInteropTestsContext_Default.Default, (options) => new NodeInteropTestsContext_Default(options))) + { + } + + [JsonSerializable(typeof(List))] + [JsonSerializable(typeof(JsonArray))] + [JsonSerializable(typeof(Poco))] + [JsonSerializable(typeof(string))] + internal sealed partial class NodeInteropTestsContext_Default : JsonSerializerContext + { + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyNameTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyNameTests.cs new file mode 100644 index 00000000000000..1beb220396a416 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyNameTests.cs @@ -0,0 +1,60 @@ +// 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.Text.Json.Serialization; +using System.Text.Json.Serialization.Tests; + +namespace System.Text.Json.SourceGeneration.Tests +{ + public sealed partial class PropertyNameTests_Metadata : PropertyNameTests + { + public PropertyNameTests_Metadata() + : base(new StringSerializerWrapper(PropertyNameTestsContext_Metadata.Default, (options) => new PropertyNameTestsContext_Metadata(options))) + { + } + + [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(ClassWithSpecialCharacters))] + [JsonSerializable(typeof(ClassWithPropertyNamePermutations))] + [JsonSerializable(typeof(ClassWithUnicodeProperty))] + [JsonSerializable(typeof(DuplicatePropertyNameDesignTime_TestClass))] + [JsonSerializable(typeof(EmptyPropertyName_TestClass))] + [JsonSerializable(typeof(IntPropertyNamesDifferentByCaseOnly_TestClass))] + [JsonSerializable(typeof(NullPropertyName_TestClass))] + [JsonSerializable(typeof(ObjectPropertyNamesDifferentByCaseOnly_TestClass))] + [JsonSerializable(typeof(OverridePropertyNameDesignTime_TestClass))] + [JsonSerializable(typeof(SimpleTestClass))] + internal sealed partial class PropertyNameTestsContext_Metadata : JsonSerializerContext + { + } + } + + public sealed partial class PropertyNameTests_Default : PropertyNameTests + { + public PropertyNameTests_Default() + : base(new StringSerializerWrapper(PropertyNameTestsContext_Default.Default, (options) => new PropertyNameTestsContext_Default(options))) + { + } + + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(Dictionary))] + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(ClassWithSpecialCharacters))] + [JsonSerializable(typeof(ClassWithPropertyNamePermutations))] + [JsonSerializable(typeof(ClassWithUnicodeProperty))] + [JsonSerializable(typeof(DuplicatePropertyNameDesignTime_TestClass))] + [JsonSerializable(typeof(EmptyPropertyName_TestClass))] + [JsonSerializable(typeof(IntPropertyNamesDifferentByCaseOnly_TestClass))] + [JsonSerializable(typeof(NullPropertyName_TestClass))] + [JsonSerializable(typeof(ObjectPropertyNamesDifferentByCaseOnly_TestClass))] + [JsonSerializable(typeof(OverridePropertyNameDesignTime_TestClass))] + [JsonSerializable(typeof(SimpleTestClass))] + internal sealed partial class PropertyNameTestsContext_Default : JsonSerializerContext + { + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs index cc9b3d617107cc..a698165e3f9677 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Reflection; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Tests; using System.Threading.Tasks; @@ -46,17 +47,10 @@ public override async Task Honor_JsonSerializablePropertyAttribute_OnProperties( ""MyUri"":""https://microsoft.com"" }"; - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); - Assert.Equal(0, obj.MyInt); // Source gen can't use private setter - Assert.Equal("Hello", obj.MyString); - Assert.Equal(2f, obj.GetMyFloat); - Assert.Equal(new Uri("https://microsoft.com"), obj.MyUri); - - json = await JsonSerializerWrapperForString.SerializeWrapper(obj); - Assert.Contains(@"""MyInt"":0", json); - Assert.Contains(@"""MyString"":""Hello""", json); - Assert.DoesNotContain(@"""MyFloat"":", json); // Source gen can't use private setter - Assert.Contains(@"""MyUri"":""https://microsoft.com""", json); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json)); + + var obj = new MyClass_WithNonPublicAccessors_WithPropertyAttributes(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj)); } [Theory] @@ -64,12 +58,15 @@ public override async Task Honor_JsonSerializablePropertyAttribute_OnProperties( [InlineData(typeof(StructWithInitOnlyProperty))] public override async Task InitOnlyProperties(Type type) { - // Init-only setters cannot be referenced as get/set helpers in generated code. - object obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MyInt"":1}", type); - Assert.Equal(0, (int)type.GetProperty("MyInt").GetValue(obj)); + PropertyInfo property = type.GetProperty("MyInt"); // Init-only properties can be serialized. - Assert.Equal(@"{""MyInt"":0}", await JsonSerializerWrapperForString.SerializeWrapper(obj, type)); + object obj = Activator.CreateInstance(type); + property.SetValue(obj, 1); + Assert.Equal(@"{""MyInt"":1}", await JsonSerializerWrapperForString.SerializeWrapper(obj, type)); + + // Deserializing init-only properties is not supported. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MyInt"":1}", type)); } [Theory] @@ -78,12 +75,15 @@ public override async Task InitOnlyProperties(Type type) [InlineData(typeof(Class_PropertyWith_ProtectedInitOnlySetter_WithAttribute))] public override async Task NonPublicInitOnlySetter_With_JsonInclude(Type type) { - // Init-only setters cannot be referenced as get/set helpers in generated code. - object obj = await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MyInt"":1}", type); - Assert.Equal(0, (int)type.GetProperty("MyInt").GetValue(obj)); + PropertyInfo property = type.GetProperty("MyInt"); // Init-only properties can be serialized. - Assert.Equal(@"{""MyInt"":0}", await JsonSerializerWrapperForString.SerializeWrapper(obj, type)); + object obj = Activator.CreateInstance(type); + property.SetValue(obj, 1); + Assert.Equal(@"{""MyInt"":1}", await JsonSerializerWrapperForString.SerializeWrapper(obj, type)); + + // Deserializing init-only properties is not supported. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(@"{""MyInt"":1}", type)); } [Fact] @@ -94,15 +94,15 @@ public override async Task HonorCustomConverter_UsingPrivateSetter() string json = @"{""MyEnum"":""AnotherValue"",""MyInt"":2}"; - // Deserialization baseline, without enum converter, we get JsonException. + // Deserialization baseline, without enum converter, we get JsonException. NB order of members in deserialized type is significant for this assertion to succeed. await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json)); - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json, options); - Assert.Equal(MySmallEnum.AnotherValue, obj.GetMyEnum); - Assert.Equal(0, obj.MyInt); // Private setter can't be used with source-gen. + // JsonInclude not supported in source gen. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, options)); - // ConverterForInt32 throws this exception. - await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj, options)); + // JsonInclude on private getters not supported. + var obj = new StructWithPropertiesWithConverter(); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj, options)); } [Fact] @@ -116,25 +116,32 @@ public override async Task Public_And_NonPublicPropertyAccessors_PropertyAttribu Assert.Equal(3, obj.Y); Assert.Equal(4, obj.GetZ); - json = await JsonSerializerWrapperForString.SerializeWrapper(obj); - Assert.Contains(@"""W"":1", json); - Assert.Contains(@"""X"":2", json); - Assert.Contains(@"""Y"":3", json); - Assert.DoesNotContain(@"""Z"":", json); // Private setter cannot be used with source gen. + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(obj)); + } + + [Fact] + public override async Task HonorJsonPropertyName_PrivateGetter() + { + string json = @"{""prop1"":1}"; + + var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); + Assert.Equal(MySmallEnum.AnotherValue, obj.GetProxy()); + + // JsonInclude for private members not supported in source gen + await Assert.ThrowsAsync(async() => await JsonSerializerWrapperForString.SerializeWrapper(obj)); } [Fact] - public override async Task HonorJsonPropertyName() + public override async Task HonorJsonPropertyName_PrivateSetter() { - string json = @"{""prop1"":1,""prop2"":2}"; + string json = @"{""prop2"":2}"; - var obj = await JsonSerializerWrapperForString.DeserializeWrapper(json); - Assert.Equal(MySmallEnum.AnotherValue, obj.GetMyEnum); - Assert.Equal(0, obj.MyInt); // Private setter cannot be used with source gen. + // JsonInclude for private members not supported in source gen + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json)); - json = await JsonSerializerWrapperForString.SerializeWrapper(obj); - Assert.DoesNotContain(@"""prop1"":", json); // Private getter cannot be used with source gen. - Assert.Contains(@"""prop2"":0", json); + var obj = new StructWithPropertiesWithJsonPropertyName_PrivateSetter(); + obj.SetProxy(2); + Assert.Equal(json, await JsonSerializerWrapperForString.SerializeWrapper(obj)); } [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] @@ -161,10 +168,12 @@ public override async Task HonorJsonPropertyName() [JsonSerializable(typeof(StructWithBadIgnoreAttribute))] [JsonSerializable(typeof(Class_PropertyWith_InternalInitOnlySetter))] [JsonSerializable(typeof(Class_PropertyWith_ProtectedInitOnlySetter))] + [JsonSerializable(typeof(ClassWithIgnoredPublicProperty))] [JsonSerializable(typeof(ClassWithIgnoredPublicPropertyAndNewSlotPrivate))] [JsonSerializable(typeof(ClassWithIgnoredPropertyPolicyConflictPublic))] [JsonSerializable(typeof(ClassWithIgnoredPropertyNamingConflictPrivate))] [JsonSerializable(typeof(ClassWithIgnoredNewSlotProperty))] + [JsonSerializable(typeof(ClassWithObsoleteAndIgnoredProperty))] [JsonSerializable(typeof(ClassWithPublicGetterAndPrivateSetter))] [JsonSerializable(typeof(ClassWithInitializedProps))] [JsonSerializable(typeof(ClassWithNewSlotInternalProperty))] @@ -250,9 +259,17 @@ public override async Task HonorJsonPropertyName() [JsonSerializable(typeof(ClassTwiceInheritedWithPropertyPolicyConflictWhichThrows))] [JsonSerializable(typeof(MyClass_WithNonPublicAccessors))] [JsonSerializable(typeof(ClassWithThingsToIgnore_PerProperty))] - [JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName))] + [JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName_PrivateGetter))] + [JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName_PrivateSetter))] [JsonSerializable(typeof(ClassWithValueAndReferenceTypes))] [JsonSerializable(typeof(ClassWithReadOnlyStringProperty_IgnoreWhenWritingDefault))] + [JsonSerializable(typeof(ConcreteDerivedClass))] + [JsonSerializable(typeof(TypeWith_RefStringProp))] + [JsonSerializable(typeof(TypeWith_IgnoredRefStringProp))] + [JsonSerializable(typeof(TypeWith_PropWith_BadConverter))] + [JsonSerializable(typeof(TypeWith_IgnoredPropWith_BadConverter))] + [JsonSerializable(typeof(ClassWithIgnoredCallbacks))] + [JsonSerializable(typeof(ClassWithCallbacks))] internal sealed partial class PropertyVisibilityTestsContext_Metadata : JsonSerializerContext { } @@ -324,10 +341,12 @@ public override async Task JsonIgnoreCondition_WhenWritingNull_OnValueType_Fail_ [JsonSerializable(typeof(StructWithBadIgnoreAttribute))] [JsonSerializable(typeof(Class_PropertyWith_InternalInitOnlySetter))] [JsonSerializable(typeof(Class_PropertyWith_ProtectedInitOnlySetter))] + [JsonSerializable(typeof(ClassWithIgnoredPublicProperty))] [JsonSerializable(typeof(ClassWithIgnoredPublicPropertyAndNewSlotPrivate))] [JsonSerializable(typeof(ClassWithIgnoredPropertyPolicyConflictPublic))] [JsonSerializable(typeof(ClassWithIgnoredPropertyNamingConflictPrivate))] [JsonSerializable(typeof(ClassWithIgnoredNewSlotProperty))] + [JsonSerializable(typeof(ClassWithObsoleteAndIgnoredProperty))] [JsonSerializable(typeof(ClassWithPublicGetterAndPrivateSetter))] [JsonSerializable(typeof(ClassWithInitializedProps))] [JsonSerializable(typeof(ClassWithNewSlotInternalProperty))] @@ -413,9 +432,17 @@ public override async Task JsonIgnoreCondition_WhenWritingNull_OnValueType_Fail_ [JsonSerializable(typeof(ClassTwiceInheritedWithPropertyPolicyConflictWhichThrows))] [JsonSerializable(typeof(MyClass_WithNonPublicAccessors))] [JsonSerializable(typeof(ClassWithThingsToIgnore_PerProperty))] - [JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName))] + [JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName_PrivateGetter))] + [JsonSerializable(typeof(StructWithPropertiesWithJsonPropertyName_PrivateSetter))] [JsonSerializable(typeof(ClassWithValueAndReferenceTypes))] [JsonSerializable(typeof(ClassWithReadOnlyStringProperty_IgnoreWhenWritingDefault))] + [JsonSerializable(typeof(ConcreteDerivedClass))] + [JsonSerializable(typeof(TypeWith_RefStringProp))] + [JsonSerializable(typeof(TypeWith_IgnoredRefStringProp))] + [JsonSerializable(typeof(TypeWith_PropWith_BadConverter))] + [JsonSerializable(typeof(TypeWith_IgnoredPropWith_BadConverter))] + [JsonSerializable(typeof(ClassWithIgnoredCallbacks))] + [JsonSerializable(typeof(ClassWithCallbacks))] internal sealed partial class PropertyVisibilityTestsContext_Default : JsonSerializerContext { } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs new file mode 100644 index 00000000000000..fbe343eda582ab --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs @@ -0,0 +1,94 @@ +// 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.Runtime.Serialization; +using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Tests; + +namespace System.Text.Json.SourceGeneration.Tests +{ + public sealed partial class UnsupportedTypesTests_Metadata : UnsupportedTypesTests + { + public UnsupportedTypesTests_Metadata() : base( + new StringSerializerWrapper( + UnsupportedTypesTestsContext_Metadata.Default, + (options) => new UnsupportedTypesTestsContext_Metadata(options)), + supportsJsonPathOnSerialize: true) + { + } + + [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] + // Supported types: + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(ClassWithIntPtrConverter))] + // Unsupported types: + [JsonSerializable(typeof(Type))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(SerializationInfo))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(IntPtr))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(ClassWithIntPtr))] + [JsonSerializable(typeof(IntPtr?))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(UIntPtr))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(IAsyncEnumerable))] + [JsonSerializable(typeof(ClassWithType>))] + [JsonSerializable(typeof(ClassThatImplementsIAsyncEnumerable))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(ClassWithAsyncEnumerableConverter))] + +#if NETCOREAPP + [JsonSerializable(typeof(DateOnly))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(TimeOnly))] + [JsonSerializable(typeof(ClassWithType))] +#endif + internal sealed partial class UnsupportedTypesTestsContext_Metadata : JsonSerializerContext + { + } + } + + public sealed partial class UnsupportedTypesTests_Default : UnsupportedTypesTests + { + public UnsupportedTypesTests_Default() : base( + new StringSerializerWrapper( + UnsupportedTypesTestsContext_Default.Default, + (options) => new UnsupportedTypesTestsContext_Default(options)), + supportsJsonPathOnSerialize: false) + { + } + + // Supported types: + [JsonSerializable(typeof(int))] + [JsonSerializable(typeof(ClassWithIntPtrConverter))] + // Unsupported types: + [JsonSerializable(typeof(Type))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(SerializationInfo))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(IntPtr))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(ClassWithIntPtr))] + [JsonSerializable(typeof(IntPtr?))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(UIntPtr))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(IAsyncEnumerable))] + [JsonSerializable(typeof(ClassWithType>))] + [JsonSerializable(typeof(ClassThatImplementsIAsyncEnumerable))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(ClassWithAsyncEnumerableConverter))] +#if NETCOREAPP + [JsonSerializable(typeof(DateOnly))] + [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(TimeOnly))] + [JsonSerializable(typeof(ClassWithType))] +#endif + internal sealed partial class UnsupportedTypesTestsContext_Default : JsonSerializerContext + { + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs index 799de2b1032108..c658661b7a8c3f 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs @@ -25,10 +25,24 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))] [JsonSerializable(typeof(object[]))] + [JsonSerializable(typeof(byte[]))] [JsonSerializable(typeof(string))] + [JsonSerializable(typeof((string Label1, int Label2, bool)))] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties))] + [JsonSerializable(typeof(ClassWithCustomConverter))] + [JsonSerializable(typeof(StructWithCustomConverter))] + [JsonSerializable(typeof(ClassWithCustomConverterFactory))] + [JsonSerializable(typeof(StructWithCustomConverterFactory))] + [JsonSerializable(typeof(ClassWithCustomConverterProperty))] + [JsonSerializable(typeof(StructWithCustomConverterProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(ClassWithBadCustomConverter))] + [JsonSerializable(typeof(StructWithBadCustomConverter))] internal partial class SerializationContext : JsonSerializerContext, ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization; } [JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -49,13 +63,27 @@ internal partial class SerializationContext : JsonSerializerContext, ITestContex [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] internal partial class SerializationWithPerTypeAttributeContext : JsonSerializerContext, ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization; } - [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)] + [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, IncludeFields = true)] [JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RepeatedTypes.Location), GenerationMode = JsonSourceGenerationMode.Serialization, TypeInfoPropertyName = "RepeatedLocation")] [JsonSerializable(typeof(NumberTypes), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -74,10 +102,24 @@ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializer [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(byte[]), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof((string Label1, int Label2, bool)), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(RealWorldContextTests.ClassWithNullableProperties), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterFactory), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] internal partial class SerializationContextWithCamelCase : JsonSerializerContext, ITestContext { + public JsonSourceGenerationMode JsonSourceGenerationMode => JsonSourceGenerationMode.Serialization; } public class SerializationContextTests : RealWorldContextTests @@ -92,26 +134,36 @@ internal SerializationContextTests(ITestContext defaultContext, Func(() => SerializationContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => SerializationContext.Default.StructWithBadCustomConverter.SerializeHandler); } [Fact] @@ -324,6 +376,41 @@ void RunTest(ClassWithEnumAndNullable expected) } } + [Fact] + public override void ClassWithNullableProperties_Roundtrip() + { + RunTest(new ClassWithNullableProperties + { + Uri = new Uri("http://contoso.com"), + Array = new int[] { 42 }, + Poco = new ClassWithNullableProperties.MyPoco(), + + NullableUri = new Uri("http://contoso.com"), + NullableArray = new int[] { 42 }, + NullablePoco = new ClassWithNullableProperties.MyPoco() + }); + + RunTest(new ClassWithNullableProperties()); + + void RunTest(ClassWithNullableProperties expected) + { + string json = JsonSerializer.Serialize(expected, DefaultContext.ClassWithNullableProperties); + ClassWithNullableProperties actual = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ClassWithNullableProperties); + + Assert.Equal(expected.Uri, actual.Uri); + Assert.Equal(expected.Array, actual.Array); + Assert.Equal(expected.Poco, actual.Poco); + + Assert.Equal(expected.NullableUri, actual.NullableUri); + Assert.Equal(expected.NullableArray, actual.NullableArray); + Assert.Equal(expected.NullablePoco, actual.NullablePoco); + + Assert.Equal(expected.NullableUriParameter, actual.NullableUriParameter); + Assert.Equal(expected.NullableArrayParameter, actual.NullableArrayParameter); + Assert.Equal(expected.NullablePocoParameter, actual.NullablePocoParameter); + } + } + [Fact] public override void ParameterizedConstructor() { @@ -353,23 +440,36 @@ public sealed class SerializationWithPerTypeAttributeContextTests : Serializatio [Fact] public override void EnsureFastPathGeneratedAsExpected() { - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.Location.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.RepeatedLocation.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.IndexViewModel.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTemps.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType2.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyIntermediateType.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTempsImmutable.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedClass.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedNestedClass.Serialize); - Assert.Null(SerializationWithPerTypeAttributeContext.Default.ObjectArray.Serialize); - Assert.Null(SerializationWithPerTypeAttributeContext.Default.String.Serialize); - Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.Location.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.RepeatedLocation.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.IndexViewModel.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTemps.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType2.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyIntermediateType.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTempsImmutable.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedClass.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedNestedClass.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ObjectArray.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ByteArray.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.SampleEnum.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.String.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler); + Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverter.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverter.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactory.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterFactory.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterProperty.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterProperty.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterFactoryProperty.SerializeHandler); + Assert.Throws(() => SerializationWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => SerializationWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler); } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs index a086659da54779..2bfb07086eecd9 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs @@ -52,11 +52,11 @@ public static void SerializationFuncNotInvokedWhenNotSupported(JsonSerializerOpt [Fact] public static void DictionaryFastPathPrimitiveValueSupported() { - Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringString.Serialize); - Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringJsonMessage.Serialize); - Assert.NotNull(DictionaryTypeContext.Default.JsonMessage.Serialize); - Assert.Null(DictionaryTypeContext.Default.String.Serialize); - Assert.Null(DictionaryTypeContext.Default.Int32.Serialize); + Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringString.SerializeHandler); + Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringJsonMessage.SerializeHandler); + Assert.NotNull(DictionaryTypeContext.Default.JsonMessage.SerializeHandler); + Assert.Null(DictionaryTypeContext.Default.String.SerializeHandler); + Assert.Null(DictionaryTypeContext.Default.Int32.SerializeHandler); } // Options with features that apply only to deserialization. diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj new file mode 100644 index 00000000000000..8ac0061d4094bf --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj new file mode 100644 index 00000000000000..82a98d9773af10 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets similarity index 88% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.csproj rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets index 3fe38b92f50848..2f977168e80437 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets @@ -1,20 +1,18 @@ - + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true true - $(NoWarn);SYSLIB0020 + + + $(NoWarn);SYSLIB0020;SYSLIB1037;SYSLIB1038 $(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS - - - - @@ -38,12 +36,16 @@ + + + + @@ -61,20 +63,27 @@ + + + + + + + - + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs new file mode 100644 index 00000000000000..1fff23f8a6c55c --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs @@ -0,0 +1,271 @@ +// 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.Json.Serialization; + +namespace System.Text.Json.SourceGeneration.Tests +{ + /// + /// Custom converter that adds\substract 100 from MyIntProperty. + /// + public class CustomConverter_ClassWithCustomConverter : JsonConverter + { + public override ClassWithCustomConverter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + { + throw new JsonException("No StartObject"); + } + + ClassWithCustomConverter obj = new(); + + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName && + reader.GetString() != "MyInt") + { + throw new JsonException("Wrong property name"); + } + + reader.Read(); + obj.MyInt = reader.GetInt32() - 100; + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException("No EndObject"); + } + + return obj; + } + + public override void Write(Utf8JsonWriter writer, ClassWithCustomConverter value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteNumber(nameof(ClassWithCustomConverter.MyInt), value.MyInt + 100); + writer.WriteEndObject(); + } + } + + /// + /// Custom converter that adds\substract 100 from MyIntProperty. + /// + public class CustomConverter_ClassWithCustomConverterFactory : JsonConverter + { + public override ClassWithCustomConverterFactory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + { + throw new JsonException("No StartObject"); + } + + ClassWithCustomConverterFactory obj = new(); + + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName && + reader.GetString() != "MyInt") + { + throw new JsonException("Wrong property name"); + } + + reader.Read(); + obj.MyInt = reader.GetInt32() - 100; + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException("No EndObject"); + } + + return obj; + } + + public override void Write(Utf8JsonWriter writer, ClassWithCustomConverterFactory value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteNumber(nameof(ClassWithCustomConverterFactory.MyInt), value.MyInt + 100); + writer.WriteEndObject(); + } + } + + /// + /// Custom converter that adds\substract 100 from MyIntProperty. + /// + public class CustomConverter_StructWithCustomConverter : JsonConverter + { + public override StructWithCustomConverter Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + { + throw new JsonException("No StartObject"); + } + + StructWithCustomConverter obj = new(); + + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName && + reader.GetString() != "MyInt") + { + throw new JsonException("Wrong property name"); + } + + reader.Read(); + obj.MyInt = reader.GetInt32() - 100; + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException("No EndObject"); + } + + return obj; + } + + public override void Write(Utf8JsonWriter writer, StructWithCustomConverter value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteNumber(nameof(StructWithCustomConverter.MyInt), value.MyInt + 100); + writer.WriteEndObject(); + } + } + + /// + /// Custom converter that adds\substract 100 from MyIntProperty. + /// + public class CustomConverter_StructWithCustomConverterFactory : JsonConverter + { + public override StructWithCustomConverterFactory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + { + throw new JsonException("No StartObject"); + } + + StructWithCustomConverterFactory obj = new(); + + reader.Read(); + if (reader.TokenType != JsonTokenType.PropertyName && + reader.GetString() != "MyInt") + { + throw new JsonException("Wrong property name"); + } + + reader.Read(); + obj.MyInt = reader.GetInt32() - 100; + + reader.Read(); + if (reader.TokenType != JsonTokenType.EndObject) + { + throw new JsonException("No EndObject"); + } + + return obj; + } + + public override void Write(Utf8JsonWriter writer, StructWithCustomConverterFactory value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteNumber(nameof(StructWithCustomConverterFactory.MyInt), value.MyInt + 100); + writer.WriteEndObject(); + } + } + + public class CustomConverterFactory : JsonConverterFactory + { + public CustomConverterFactory() + { + } + + public override bool CanConvert(Type typeToConvert) + { + return ( + typeToConvert == typeof(StructWithCustomConverterFactory) || + typeToConvert == typeof(ClassWithCustomConverterFactory)); + } + + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + if (typeToConvert == typeof(StructWithCustomConverterFactory)) + { + return new CustomConverter_StructWithCustomConverterFactory(); + } + + if (typeToConvert == typeof(ClassWithCustomConverterFactory)) + { + return new CustomConverter_ClassWithCustomConverterFactory(); + } + + throw new InvalidOperationException("Not expected."); + } + } + + [JsonConverter(typeof(CustomConverter_ClassWithCustomConverter))] + public class ClassWithCustomConverter + { + public int MyInt { get; set; } + } + + [JsonConverter(typeof(CustomConverter_StructWithCustomConverter))] + public struct StructWithCustomConverter + { + public int MyInt { get; set; } + } + + [JsonConverter(typeof(CustomConverterFactory))] + public class ClassWithCustomConverterFactory + { + public int MyInt { get; set; } + } + + [JsonConverter(typeof(CustomConverterFactory))] + public struct StructWithCustomConverterFactory + { + public int MyInt { get; set; } + } + + public class ClassWithCustomConverterProperty + { + [JsonConverter(typeof(NestedPocoCustomConverter))] + public NestedPoco Property { get; set; } + + public class NestedPoco + { + public int Value { get; set; } + } + + public class NestedPocoCustomConverter : JsonConverter + { + public override NestedPoco? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => new NestedPoco { Value = reader.GetInt32() }; + public override void Write(Utf8JsonWriter writer, NestedPoco value, JsonSerializerOptions options) => writer.WriteNumberValue(value.Value); + } + } + + public struct StructWithCustomConverterProperty + { + [JsonConverter(typeof(ClassWithCustomConverterProperty.NestedPocoCustomConverter))] + public ClassWithCustomConverterProperty.NestedPoco Property { get; set; } + } + + public class ClassWithCustomConverterFactoryProperty + { + [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory + public Serialization.Tests.SampleEnum MyEnum { get; set; } + } + + public struct StructWithCustomConverterFactoryProperty + { + [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory + public Serialization.Tests.SampleEnum MyEnum { get; set; } + } + + [JsonConverter(typeof(CustomConverter_StructWithCustomConverter))] // Invalid + public class ClassWithBadCustomConverter + { + public int MyInt { get; set; } + } + + [JsonConverter(typeof(CustomConverter_StructWithCustomConverter))] // Invalid + public struct StructWithBadCustomConverter + { + public int MyInt { get; set; } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs index 887f65b80da83b..d28a73c7b24d55 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.cs @@ -60,6 +60,7 @@ public class ActiveOrUpcomingEvent public string Description { get; set; } public DateTimeOffset StartDate { get; set; } public DateTimeOffset EndDate { get; set; } + public TimeSpan Offset { get; set; } } public class CampaignSummaryViewModel diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/CompilationHelper.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs similarity index 61% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/CompilationHelper.cs rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs index 86a261f284e67a..485a79cd333cd6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/CompilationHelper.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/CompilationHelper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Globalization; using System.IO; using System.Linq; using System.Reflection; @@ -16,6 +17,11 @@ namespace System.Text.Json.SourceGeneration.UnitTests { public class CompilationHelper { + private static readonly CSharpParseOptions s_parseOptions = + new CSharpParseOptions(kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.Parse) + // workaround https://github.com/dotnet/roslyn/pull/55866. We can remove "LangVersion=Preview" when we get a Roslyn build with that change. + .WithLanguageVersion(LanguageVersion.Preview); + public static Compilation CreateCompilation( string source, MetadataReference[] additionalReferences = null, @@ -55,20 +61,30 @@ public static Compilation CreateCompilation( return CSharpCompilation.Create( assemblyName, - syntaxTrees: new[] { CSharpSyntaxTree.ParseText(source) }, + syntaxTrees: new[] { CSharpSyntaxTree.ParseText(source, s_parseOptions) }, references: references.ToArray(), options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary) ); } - private static GeneratorDriver CreateDriver(Compilation compilation, params ISourceGenerator[] generators) - => CSharpGeneratorDriver.Create( - generators: ImmutableArray.Create(generators), - parseOptions: new CSharpParseOptions(kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.Parse)); - - public static Compilation RunGenerators(Compilation compilation, out ImmutableArray diagnostics, params ISourceGenerator[] generators) + public static Compilation RunGenerators( + Compilation compilation, + out ImmutableArray diagnostics, +#if ROSLYN4_0_OR_GREATER + params IIncrementalGenerator[] generators) + { + CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create( + generators: generators.Select(g => g.AsSourceGenerator()), + parseOptions: s_parseOptions); +#else + params ISourceGenerator[] generators) { - CreateDriver(compilation, generators).RunGeneratorsAndUpdateCompilation(compilation, out Compilation outCompilation, out diagnostics); + CSharpGeneratorDriver driver = CSharpGeneratorDriver.Create( + generators: generators, + parseOptions: s_parseOptions); +#endif + + driver.RunGeneratorsAndUpdateCompilation(compilation, out Compilation outCompilation, out diagnostics); return outCompilation; } @@ -259,15 +275,147 @@ public class Location return CreateCompilation(source); } - internal static void CheckDiagnosticMessages(ImmutableArray diagnostics, DiagnosticSeverity level, string[] expectedMessages) + public static Compilation CreateCompilationWithInitOnlyProperties() + { + string source = @" + using System; + using System.Text.Json.Serialization; + + namespace HelloWorld + { + public class Location + { + public int Id { get; init; } + public string Address1 { get; init; } + public string Address2 { get; init; } + public string City { get; init; } + public string State { get; init; } + public string PostalCode { get; init; } + public string Name { get; init; } + public string PhoneNumber { get; init; } + public string Country { get; init; } + } + + [JsonSerializable(typeof(Location))] + public partial class MyJsonContext : JsonSerializerContext + { + } + }"; + + return CreateCompilation(source); + } + + public static Compilation CreateCompilationWithInaccessibleJsonIncludeProperties() { - string[] actualMessages = diagnostics.Where(diagnostic => diagnostic.Severity == level).Select(diagnostic => diagnostic.GetMessage()).ToArray(); + string source = @" + using System; + using System.Text.Json.Serialization; - // Can't depending on reflection order when generating type metadata. - Array.Sort(actualMessages); - Array.Sort(expectedMessages); + namespace HelloWorld + { + public class Location + { + [JsonInclude] + public int Id { get; private set; } + [JsonInclude] + public string Address1 { get; internal set; } + [JsonInclude] + private string Address2 { get; set; } + [JsonInclude] + public string PhoneNumber { internal get; set; } + [JsonInclude] + public string Country { private get; set; } + } - Assert.Equal(expectedMessages, actualMessages); + [JsonSerializable(typeof(Location))] + public partial class MyJsonContext : JsonSerializerContext + { + } + }"; + + return CreateCompilation(source); + } + + public static Compilation CreateReferencedLibRecordCompilation() + { + string source = @" + using System.Text.Json.Serialization; + + namespace ReferencedAssembly + { + public record LibRecord(int Id) + { + public string Address1 { get; set; } + public string Address2 { get; set; } + public string City { get; set; } + public string State { get; set; } + public string PostalCode { get; set; } + public string Name { get; set; } + [JsonInclude] + public string PhoneNumber; + [JsonInclude] + public string Country; + } + } +"; + + return CreateCompilation(source); + } + + public static Compilation CreateReferencedSimpleLibRecordCompilation() + { + string source = @" + using System.Text.Json.Serialization; + + namespace ReferencedAssembly + { + public record LibRecord + { + public int Id { get; set; } + public string Address1 { get; set; } + public string Address2 { get; set; } + public string City { get; set; } + public string State { get; set; } + public string PostalCode { get; set; } + public string Name { get; set; } + [JsonInclude] + public string PhoneNumber; + [JsonInclude] + public string Country; + } + } +"; + + return CreateCompilation(source); + } + + internal static void CheckDiagnosticMessages( + DiagnosticSeverity level, + ImmutableArray diagnostics, + (Location Location, string Message)[] expectedDiags, + bool sort = true) + { + (Location Location, string Message)[] actualDiags = diagnostics + .Where(diagnostic => diagnostic.Severity == level) + .Select(diagnostic => (diagnostic.Location, diagnostic.GetMessage())) + .ToArray(); + + if (sort) + { + // Can't depend on reflection order when generating type metadata. + Array.Sort(actualDiags); + Array.Sort(expectedDiags); + } + + if (CultureInfo.CurrentUICulture.Name.StartsWith("en", StringComparison.OrdinalIgnoreCase)) + { + Assert.Equal(expectedDiags, actualDiags); + } + else + { + // for non-English runs, just compare the number of messages are the same + Assert.Equal(expectedDiags.Length, actualDiags.Length); + } } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs new file mode 100644 index 00000000000000..1adc0fbec10da4 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs @@ -0,0 +1,259 @@ +// 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 Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using Xunit; + +namespace System.Text.Json.SourceGeneration.UnitTests +{ + public class JsonSourceGeneratorDiagnosticsTests + { + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/58226", TestPlatforms.Browser)] + public void SuccessfulSourceGeneration() + { + // Compile the referenced assembly first. + Compilation campaignCompilation = CompilationHelper.CreateCampaignSummaryViewModelCompilation(); + Compilation eventCompilation = CompilationHelper.CreateActiveOrUpcomingEventCompilation(); + + // Emit the image of the referenced assembly. + byte[] campaignImage = CompilationHelper.CreateAssemblyImage(campaignCompilation); + byte[] eventImage = CompilationHelper.CreateAssemblyImage(eventCompilation); + + // Main source for current compilation. + string source = @" + using System.Collections.Generic; + using System.Text.Json.Serialization; + using ReferencedAssembly; + + namespace JsonSourceGenerator + { + [JsonSerializable(typeof(JsonSourceGenerator.IndexViewModel)] + public partial class JsonContext : JsonSerializerContext + { + } + + public class IndexViewModel + { + public List ActiveOrUpcomingEvents { get; set; } + public CampaignSummaryViewModel FeaturedCampaign { get; set; } + public bool IsNewAccount { get; set; } + public bool HasFeaturedCampaign => FeaturedCampaign != null; + } + }"; + + MetadataReference[] additionalReferences = { + MetadataReference.CreateFromImage(campaignImage), + MetadataReference.CreateFromImage(eventImage), + }; + + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + + JsonSourceGenerator generator = new JsonSourceGenerator(); + + CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/58226", TestPlatforms.Browser)] + public void UnsuccessfulSourceGeneration() + { + static void RunTest(bool explicitRef) + { + // Compile the referenced assembly first. + Compilation campaignCompilation = CompilationHelper.CreateCampaignSummaryViewModelCompilation(); + Compilation eventCompilation = CompilationHelper.CreateActiveOrUpcomingEventCompilation(); + + // Emit the image of the referenced assembly. + byte[] campaignImage = CompilationHelper.CreateAssemblyImage(campaignCompilation); + byte[] eventImage = CompilationHelper.CreateAssemblyImage(eventCompilation); + + string optionalAttribute = explicitRef ? "[JsonSerializable(typeof(ActiveOrUpcomingEvent[,])]" : null; + + // Main source for current compilation. + string source = @$" + using System.Collections.Generic; + using System.Text.Json.Serialization; + using ReferencedAssembly; + + namespace JsonSourceGenerator + {{ + {optionalAttribute} + [JsonSerializable(typeof(JsonSourceGenerator.IndexViewModel)] + public partial class JsonContext : JsonSerializerContext + {{ + }} + + public class IndexViewModel + {{ + public ActiveOrUpcomingEvent[,] ActiveOrUpcomingEvents {{ get; set; }} + public CampaignSummaryViewModel FeaturedCampaign {{ get; set; }} + public bool IsNewAccount {{ get; set; }} + public bool HasFeaturedCampaign => FeaturedCampaign != null; + }} + }}"; + + MetadataReference[] additionalReferences = { + MetadataReference.CreateFromImage(campaignImage), + MetadataReference.CreateFromImage(eventImage), + }; + + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + + JsonSourceGenerator generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); + + Location location; + if (explicitRef) + { + // Unsupported type is not in compiling assembly, but is indicated directly with [JsonSerializable], so location points to attribute application. + INamedTypeSymbol symbol = (INamedTypeSymbol)compilation.GetSymbolsWithName("JsonContext").FirstOrDefault(); + SyntaxReference syntaxReference = symbol.GetAttributes().First().ApplicationSyntaxReference; + TextSpan textSpan = syntaxReference.Span; + location = syntaxReference.SyntaxTree.GetLocation(textSpan)!; + } + else + { + // Unsupported type is not in compiling assembly, and isn't indicated directly with [JsonSerializable], so location points to context type. + location = compilation.GetSymbolsWithName("JsonContext").First().Locations[0]; + } + + // Expected warning logs. + (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + { + (location, "Did not generate serialization metadata for type 'global::ReferencedAssembly.ActiveOrUpcomingEvent[]'.") + }; + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, expectedWarningDiagnostics); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } + + RunTest(explicitRef: true); + RunTest(false); + } + + [Fact] + public void NameClashSourceGeneration() + { + // Without resolution. + Compilation compilation = CompilationHelper.CreateRepeatedLocationsCompilation(); + JsonSourceGenerator generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); + + INamedTypeSymbol symbol = (INamedTypeSymbol)compilation.GetSymbolsWithName("JsonContext").FirstOrDefault(); + SyntaxReference syntaxReference = new List(symbol.GetAttributes())[1].ApplicationSyntaxReference; + TextSpan textSpan = syntaxReference.Span; + Location location = syntaxReference.SyntaxTree.GetLocation(textSpan)!; + + (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + { + (location, "There are multiple types named Location. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.") + }; + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, expectedWarningDiagnostics); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + + // With resolution. + compilation = CompilationHelper.CreateRepeatedLocationsWithResolutionCompilation(); + generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out generatorDiags, generator); + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } + + [Fact] + public void ProgramsThatDontUseGeneratorCompile() + { + // No STJ usage. + string source = @"using System; + + public class Program + { + public static void Main() + { + Console.WriteLine(""Hello World""); + } + } + "; + Compilation compilation = CompilationHelper.CreateCompilation(source); + JsonSourceGenerator generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + + // With STJ usage. + source = @"using System.Text.Json; + + public class Program + { + public static void Main() + { + JsonSerializer.Serialize(""Hello World""); + } + } + "; + compilation = CompilationHelper.CreateCompilation(source); + generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out generatorDiags, generator); + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } + + [Fact] + public void WarnOnClassesWithInitOnlyProperties() + { + Compilation compilation = CompilationHelper.CreateCompilationWithInitOnlyProperties(); + JsonSourceGenerator generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); + + Location location = compilation.GetSymbolsWithName("Id").First().Locations[0]; + + (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + { + (location, "The type 'Location' defines init-only properties, deserialization of which is currently not supported in source generation mode.") + }; + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, expectedWarningDiagnostics); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } + + [Fact] + public void WarnOnClassesWithInaccessibleJsonIncludeProperties() + { + Compilation compilation = CompilationHelper.CreateCompilationWithInaccessibleJsonIncludeProperties(); + JsonSourceGenerator generator = new JsonSourceGenerator(); + CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); + + Location idLocation = compilation.GetSymbolsWithName("Id").First().Locations[0]; + Location address2Location = compilation.GetSymbolsWithName("Address2").First().Locations[0]; + Location countryLocation = compilation.GetSymbolsWithName("Country").First().Locations[0]; + + (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + { + (idLocation, "The member 'Location.Id' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), + (address2Location, "The member 'Location.Address2' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), + (countryLocation, "The member 'Location.Country' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.") + }; + + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, expectedWarningDiagnostics, sort: false); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/JsonSourceGeneratorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs similarity index 61% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/JsonSourceGeneratorTests.cs rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs index f12e5b07c2057b..b75bdf829a1966 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/JsonSourceGeneratorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorTests.cs @@ -68,7 +68,7 @@ public void UsePrivates() Assert.Equal("HelloWorld.MyType", myType.FullName); // Check for received fields, properties and methods in created type. - string[] expectedPropertyNames = { "PublicPropertyInt", "PublicPropertyString",}; + string[] expectedPropertyNames = { "PublicPropertyInt", "PublicPropertyString", }; string[] expectedFieldNames = { "PublicChar", "PublicDouble" }; string[] expectedMethodNames = { "get_PrivatePropertyInt", "get_PrivatePropertyString", "get_PublicPropertyInt", "get_PublicPropertyString", "MyMethod", "MySecondMethod", "set_PrivatePropertyInt", "set_PrivatePropertyString", "set_PublicPropertyInt", "set_PublicPropertyString", "UsePrivates" }; CheckFieldsPropertiesMethods(myType, expectedFieldNames, expectedPropertyNames, expectedMethodNames); @@ -243,7 +243,7 @@ public void UsePrivates() string[] expectedPropertyNamesNotMyType = { "Address1", "Address2", "City", "Country", "Id", "Name", "PhoneNumber", "PostalCode", "State" }; string[] expectedMethodNamesNotMyType = { "get_Address1", "get_Address2", "get_City", "get_Country", "get_Id", "get_Name", "get_PhoneNumber", "get_PostalCode", "get_State", "set_Address1", "set_Address2", "set_City", "set_Country", "set_Id", "set_Name", "set_PhoneNumber", "set_PostalCode", "set_State" }; - CheckFieldsPropertiesMethods(notMyType, expectedFieldNamesNotMyType, expectedPropertyNamesNotMyType, expectedMethodNamesNotMyType ); + CheckFieldsPropertiesMethods(notMyType, expectedFieldNamesNotMyType, expectedPropertyNamesNotMyType, expectedMethodNamesNotMyType); } [Theory] @@ -289,9 +289,9 @@ public JsonSerializableAttribute(Type type) { } Assert.Null(types); } - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, Array.Empty()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); } [Theory] @@ -321,9 +321,9 @@ public JsonSerializableAttribute(string typeInfoPropertyName, Type type) { } CompilationHelper.RunGenerators(compilation, out ImmutableArray generatorDiags, generator); Assert.Null(generator.GetSerializableTypes()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, Array.Empty()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); } [Fact] @@ -448,24 +448,303 @@ public void UsePrivates() CheckFieldsPropertiesMethods(myType, expectedFieldNames, expectedPropertyNames, expectedMethodNames); } + [Fact] + public void Record() + { + // Compile the referenced assembly first. + Compilation referencedCompilation = CompilationHelper.CreateReferencedLibRecordCompilation(); + + // Emit the image of the referenced assembly. + byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation); + + string source = @" + using System.Text.Json.Serialization; + + namespace HelloWorld + { + [JsonSerializable(typeof(AppRecord))] + internal partial class JsonContext : JsonSerializerContext + { + } + + public record AppRecord(int Id) + { + public string Address1 { get; set; } + public string Address2 { get; set; } + public string City { get; set; } + public string State { get; set; } + public string PostalCode { get; set; } + public string Name { get; set; } + [JsonInclude] + public string PhoneNumber; + [JsonInclude] + public string Country; + } + }"; + + MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) }; + + Compilation compilation = CompilationHelper.CreateCompilation(source); + + JsonSourceGenerator generator = new JsonSourceGenerator(); + + Compilation newCompilation = CompilationHelper.RunGenerators(compilation, out ImmutableArray generatorDiags, generator); + + // Make sure compilation was successful. + CheckCompilationDiagnosticsErrors(generatorDiags); + CheckCompilationDiagnosticsErrors(newCompilation.GetDiagnostics()); + + Dictionary types = generator.GetSerializableTypes(); + + // Check base functionality of found types. + Assert.Equal(1, types.Count); + Type recordType = types["HelloWorld.AppRecord"]; + Assert.Equal("HelloWorld.AppRecord", recordType.FullName); + + // Check for received fields, properties and methods for NotMyType. + string[] expectedFieldsNames = { "Country", "PhoneNumber" }; + string[] expectedPropertyNames = { "Address1", "Address2", "City", "Id", "Name", "PostalCode", "State" }; + CheckFieldsPropertiesMethods(recordType, expectedFieldsNames, expectedPropertyNames); + + Assert.Equal(1, recordType.GetConstructors().Length); + } + + [Fact] + public void RecordInExternalAssembly() + { + // Compile the referenced assembly first. + Compilation referencedCompilation = CompilationHelper.CreateReferencedLibRecordCompilation(); + + // Emit the image of the referenced assembly. + byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation); + + string source = @" + using System.Text.Json.Serialization; + using ReferencedAssembly; + + namespace HelloWorld + { + [JsonSerializable(typeof(LibRecord))] + internal partial class JsonContext : JsonSerializerContext + { + } + }"; + + MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) }; + + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + + JsonSourceGenerator generator = new JsonSourceGenerator(); + + Compilation newCompilation = CompilationHelper.RunGenerators(compilation, out ImmutableArray generatorDiags, generator); + + // Make sure compilation was successful. + CheckCompilationDiagnosticsErrors(generatorDiags); + CheckCompilationDiagnosticsErrors(newCompilation.GetDiagnostics()); + + Dictionary types = generator.GetSerializableTypes(); + + Assert.Equal(1, types.Count); + Type recordType = types["ReferencedAssembly.LibRecord"]; + Assert.Equal("ReferencedAssembly.LibRecord", recordType.FullName); + + string[] expectedFieldsNames = { "Country", "PhoneNumber" }; + string[] expectedPropertyNames = { "Address1", "Address2", "City", "Id", "Name", "PostalCode", "State" }; + CheckFieldsPropertiesMethods(recordType, expectedFieldsNames, expectedPropertyNames); + + Assert.Equal(1, recordType.GetConstructors().Length); + } + + [Fact] + public void RecordDerivedFromRecordInExternalAssembly() + { + // Compile the referenced assembly first. + Compilation referencedCompilation = CompilationHelper.CreateReferencedSimpleLibRecordCompilation(); + + // Emit the image of the referenced assembly. + byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation); + + string source = @" + using System.Text.Json.Serialization; + using ReferencedAssembly; + + namespace HelloWorld + { + [JsonSerializable(typeof(AppRecord))] + internal partial class JsonContext : JsonSerializerContext + { + } + + internal record AppRecord : LibRecord + { + public string ExtraData { get; set; } + } + }"; + + MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) }; + + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + + JsonSourceGenerator generator = new JsonSourceGenerator(); + + Compilation newCompilation = CompilationHelper.RunGenerators(compilation, out ImmutableArray generatorDiags, generator); + + // Make sure compilation was successful. + CheckCompilationDiagnosticsErrors(generatorDiags); + CheckCompilationDiagnosticsErrors(newCompilation.GetDiagnostics()); + + Dictionary types = generator.GetSerializableTypes(); + + Assert.Equal(1, types.Count); + Type recordType = types["HelloWorld.AppRecord"]; + Assert.Equal("HelloWorld.AppRecord", recordType.FullName); + + string[] expectedFieldsNames = { "Country", "PhoneNumber" }; + string[] expectedPropertyNames = { "Address1", "Address2", "City", "ExtraData", "Id", "Name", "PostalCode", "State" }; + CheckFieldsPropertiesMethods(recordType, expectedFieldsNames, expectedPropertyNames, inspectBaseTypes: true); + + Assert.Equal(1, recordType.GetConstructors().Length); + } + private void CheckCompilationDiagnosticsErrors(ImmutableArray diagnostics) { Assert.Empty(diagnostics.Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); } - private void CheckFieldsPropertiesMethods(Type type, string[] expectedFields, string[] expectedProperties, string[] expectedMethods) + private void CheckFieldsPropertiesMethods( + Type type, + string[] expectedFields, + string[] expectedProperties, + string[] expectedMethods = null, + bool inspectBaseTypes = false) { BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; - string[] receivedFields = type.GetFields(bindingFlags).Select(field => field.Name).OrderBy(s => s).ToArray(); - string[] receivedProperties = type.GetProperties(bindingFlags).Select(property => property.Name).OrderBy(s => s).ToArray(); + string[] receivedFields; + string[] receivedProperties; + + if (!inspectBaseTypes) + { + receivedFields = type.GetFields(bindingFlags).Select(field => field.Name).OrderBy(s => s).ToArray(); + receivedProperties = type.GetProperties(bindingFlags).Select(property => property.Name).OrderBy(s => s).ToArray(); + } + else + { + List fields = new List(); + List props = new List(); + + Type currentType = type; + while (currentType != null) + { + fields.AddRange(currentType.GetFields(bindingFlags).Select(property => property.Name).OrderBy(s => s).ToArray()); + props.AddRange(currentType.GetProperties(bindingFlags).Select(property => property.Name).OrderBy(s => s).ToArray()); + currentType = currentType.BaseType; + } + + receivedFields = fields.ToArray(); + receivedProperties = props.ToArray(); + } + string[] receivedMethods = type.GetMethods().Select(method => method.Name).OrderBy(s => s).ToArray(); + Array.Sort(receivedFields); + Array.Sort(receivedProperties); + Array.Sort(receivedMethods); + Assert.Equal(expectedFields, receivedFields); Assert.Equal(expectedProperties, receivedProperties); - Assert.Equal(expectedMethods, receivedMethods); + + if (expectedMethods != null) + { + Assert.Equal(expectedMethods, receivedMethods); + } } // TODO: add test guarding against (de)serializing static classes. + + [Fact] + public void TestMultipleDefinitions() + { + // Adding a dependency to an assembly that has internal definitions of public types + // should not result in a collision and break generation. + // Verify usage of the extension GetBestTypeByMetadataName(this Compilation) instead of Compilation.GetTypeByMetadataName(). + var referencedSource = @" + namespace System.Text.Json.Serialization + { + internal class JsonSerializerContext { } + internal class JsonSerializableAttribute { } + internal class JsonSourceGenerationOptionsAttribute { } + }"; + + // Compile the referenced assembly first. + Compilation referencedCompilation = CompilationHelper.CreateCompilation(referencedSource); + + // Obtain the image of the referenced assembly. + byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation); + + // Generate the code + string source = @" + using System.Text.Json.Serialization; + namespace HelloWorld + { + [JsonSerializable(typeof(HelloWorld.MyType))] + internal partial class JsonContext : JsonSerializerContext + { + } + + public class MyType + { + public int MyInt { get; set; } + } + }"; + + MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) }; + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + JsonSourceGenerator generator = new JsonSourceGenerator(); + + Compilation newCompilation = CompilationHelper.RunGenerators( + compilation, + out ImmutableArray generatorDiags, generator); + + // Make sure compilation was successful. + Assert.Empty(generatorDiags.Where(diag => diag.Severity.Equals(DiagnosticSeverity.Error))); + Assert.Empty(newCompilation.GetDiagnostics().Where(diag => diag.Severity.Equals(DiagnosticSeverity.Error))); + + // Should find the generated type. + Dictionary types = generator.GetSerializableTypes(); + Assert.Equal(1, types.Count); + Assert.Equal("HelloWorld.MyType", types.Keys.First()); + } + + [Fact] + public static void NoWarningsDueToObsoleteMembers() + { + string source = @"using System; +using System.Text.Json.Serialization; + +namespace Test +{ + [JsonSerializable(typeof(ClassWithObsolete))] + public partial class JsonContext : JsonSerializerContext { } + + public class ClassWithObsolete + { + [Obsolete(""This is a test"")] + public bool Test { get; set; } + } +} +"; + + Compilation compilation = CompilationHelper.CreateCompilation(source); + JsonSourceGenerator generator = new JsonSourceGenerator(); + + Compilation newCompilation = CompilationHelper.RunGenerators(compilation, out _, generator); + ImmutableArray generatorDiags = newCompilation.GetDiagnostics(); + + // No diagnostics expected. + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); + CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj new file mode 100644 index 00000000000000..5a99fa881f97f2 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj @@ -0,0 +1,11 @@ + + + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion_3_11) + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj new file mode 100644 index 00000000000000..073d9ca3126c72 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj @@ -0,0 +1,12 @@ + + + $(MicrosoftCodeAnalysisCSharpWorkspacesVersion) + $(DefineConstants);ROSLYN4_0_OR_GREATER + + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/System.Text.Json.SourceGeneration.UnitTests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets similarity index 81% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/System.Text.Json.SourceGeneration.UnitTests.csproj rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets index fad3b73e1026df..da4a8b8d65997b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/System.Text.Json.SourceGeneration.UnitTests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/System.Text.Json.SourceGeneration.Unit.Tests.targets @@ -1,14 +1,13 @@ - + $(NetCoreAppCurrent);$(NetFrameworkCurrent) true - + - diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/TypeWrapperTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/TypeWrapperTests.cs similarity index 100% rename from src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/TypeWrapperTests.cs rename to src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/TypeWrapperTests.cs diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/JsonSourceGeneratorDiagnosticsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/JsonSourceGeneratorDiagnosticsTests.cs deleted file mode 100644 index caa283f25f91a3..00000000000000 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.UnitTests/JsonSourceGeneratorDiagnosticsTests.cs +++ /dev/null @@ -1,194 +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 Microsoft.CodeAnalysis; -using Xunit; - -namespace System.Text.Json.SourceGeneration.UnitTests -{ - public class JsonSourceGeneratorDiagnosticsTests - { - [Fact] - [ActiveIssue("Figure out issue with CampaignSummaryViewModel namespace.")] - public void SuccessfulSourceGeneration() - { - // Compile the referenced assembly first. - Compilation campaignCompilation = CompilationHelper.CreateCampaignSummaryViewModelCompilation(); - Compilation eventCompilation = CompilationHelper.CreateActiveOrUpcomingEventCompilation(); - - // Emit the image of the referenced assembly. - byte[] campaignImage = CompilationHelper.CreateAssemblyImage(campaignCompilation); - byte[] eventImage = CompilationHelper.CreateAssemblyImage(eventCompilation); - - // Main source for current compilation. - string source = @" - using System.Collections.Generic; - using System.Text.Json.Serialization; - using ReferencedAssembly; - - [assembly: JsonSerializable(typeof(JsonSourceGenerator.IndexViewModel)] - - namespace JsonSourceGenerator - { - public class IndexViewModel - { - public List ActiveOrUpcomingEvents { get; set; } - public CampaignSummaryViewModel FeaturedCampaign { get; set; } - public bool IsNewAccount { get; set; } - public bool HasFeaturedCampaign => FeaturedCampaign != null; - } - }"; - - MetadataReference[] additionalReferences = { - MetadataReference.CreateFromImage(campaignImage), - MetadataReference.CreateFromImage(eventImage), - }; - - Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); - - JsonSourceGenerator generator = new JsonSourceGenerator(); - - CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); - - // Expected info logs. - string[] expectedInfoDiagnostics = new string[] { - "Generated serialization metadata for type System.Collections.Generic.List", - "Generated serialization metadata for type System.Int32", - "Generated serialization metadata for type System.String", - "Generated serialization metadata for type System.DateTimeOffset", - "Generated serialization metadata for type System.Boolean", - "Generated serialization metadata for type ReferencedAssembly.ActiveOrUpcomingEvent", - "Generated serialization metadata for type ReferencedAssembly.CampaignSummaryViewModel", - "Generated serialization metadata for type JsonSourceGenerator.IndexViewModel", - }; - - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, expectedInfoDiagnostics); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, new string[] { }); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, new string[] { }); - } - - [Fact] - [ActiveIssue("Figure out issue with CampaignSummaryViewModel namespace.")] - public void UnsuccessfulSourceGeneration() - { - // Compile the referenced assembly first. - Compilation campaignCompilation = CompilationHelper.CreateCampaignSummaryViewModelCompilation(); - Compilation eventCompilation = CompilationHelper.CreateActiveOrUpcomingEventCompilation(); - - // Emit the image of the referenced assembly. - byte[] campaignImage = CompilationHelper.CreateAssemblyImage(campaignCompilation); - byte[] eventImage = CompilationHelper.CreateAssemblyImage(eventCompilation); - - // Main source for current compilation. - string source = @" - using System.Collections.Generic; - using System.Text.Json.Serialization; - using ReferencedAssembly; - - [assembly: JsonSerializable(typeof(JsonSourceGenerator.IndexViewModel)] - - namespace JsonSourceGenerator - { - public class IndexViewModel - { - public ISet ActiveOrUpcomingEvents { get; set; } - public CampaignSummaryViewModel FeaturedCampaign { get; set; } - public bool IsNewAccount { get; set; } - public bool HasFeaturedCampaign => FeaturedCampaign != null; - } - }"; - - MetadataReference[] additionalReferences = { - MetadataReference.CreateFromImage(campaignImage), - MetadataReference.CreateFromImage(eventImage), - }; - - Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); - - JsonSourceGenerator generator = new JsonSourceGenerator(); - - CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); - - // Expected success info logs. - string[] expectedInfoDiagnostics = new string[] { - "Generated serialization metadata for type JsonSourceGeneration.IndexViewModel", - "Generated serialization metadata for type System.Boolean", - "Generated serialization metadata for type ReferencedAssembly.CampaignSummaryViewModel" - }; - - // Expected warning logs. - string[] expectedWarningDiagnostics = new string[] { "Did not generate serialization metadata for type System.Collections.Generic.ISet" }; - - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, expectedInfoDiagnostics); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, expectedWarningDiagnostics); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, new string[] { }); - } - - [Fact] - public void NameClashSourceGeneration() - { - // Without resolution. - Compilation compilation = CompilationHelper.CreateRepeatedLocationsCompilation(); - JsonSourceGenerator generator = new JsonSourceGenerator(); - CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); - - string[] expectedWarningDiagnostics = new string[] { "There are multiple types named Location. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision." }; - - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, expectedWarningDiagnostics); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, Array.Empty()); - - // With resolution. - compilation = CompilationHelper.CreateRepeatedLocationsWithResolutionCompilation(); - generator = new JsonSourceGenerator(); - CompilationHelper.RunGenerators(compilation, out generatorDiags, generator); - - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, Array.Empty()); - } - - [Fact] - public void ProgramsThatDontUseGeneratorCompile() - { - // No STJ usage. - string source = @"using System; - -public class Program -{ - public static void Main() - { - Console.WriteLine(""Hello World""); - - } -} -"; - Compilation compilation = CompilationHelper.CreateCompilation(source); - JsonSourceGenerator generator = new JsonSourceGenerator(); - CompilationHelper.RunGenerators(compilation, out var generatorDiags, generator); - - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, Array.Empty()); - - // With STJ usage. - source = @"using System.Text.Json; - -public class Program -{ - public static void Main() - { - JsonSerializer.Serialize(""Hello World""); - } -} -"; - compilation = CompilationHelper.CreateCompilation(source); - generator = new JsonSourceGenerator(); - CompilationHelper.RunGenerators(compilation, out generatorDiags, generator); - - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Info, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Warning, Array.Empty()); - CompilationHelper.CheckDiagnosticMessages(generatorDiags, DiagnosticSeverity.Error, Array.Empty()); - } - } -} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExceptionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExceptionTests.cs index cf1b43ade3125d..fcd13f9ad4e816 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExceptionTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExceptionTests.cs @@ -512,92 +512,6 @@ public static void UnsupportedTypeFromRoot() Assert.DoesNotContain("Path: $", ex.Message); } - [Fact] - public static void DeserializeUnsupportedType() - { - // Any test payload is fine. - string json = @"""Some string"""; - - RunTest(json); - RunTest(json); - RunTest(json); - RunTest(json); -#if NETCOREAPP - RunTest(json); - RunTest(json); -#endif - - void RunTest(string json) - { - string fullName = typeof(T).FullName; - - NotSupportedException ex = Assert.Throws(() => JsonSerializer.Deserialize(json)); - string exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$", exAsStr); - - json = $@"{{""Prop"":{json}}}"; - - ex = Assert.Throws(() => JsonSerializer.Deserialize>(json)); - exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$.Prop", exAsStr); - - // NSE is not thrown because the serializer handles null. - if (!typeof(T).IsValueType) - { - Assert.Null(JsonSerializer.Deserialize("null")); - - ClassWithType obj = JsonSerializer.Deserialize>(@"{""Prop"":null}"); - Assert.Null(obj.Prop); - } - } - } - - [Fact] - public static void SerializeUnsupportedType() - { - RunTest(typeof(int)); - RunTest(new SerializationInfo(typeof(Type), new FormatterConverter())); - RunTest((IntPtr)123); - RunTest((UIntPtr)123); -#if NETCOREAPP - RunTest(DateOnly.MaxValue); - RunTest(TimeOnly.MinValue); -#endif - - void RunTest(T value) - { - Type type = typeof(T); - string fullName = type.FullName; - - NotSupportedException ex = Assert.Throws(() => JsonSerializer.Serialize(value)); - string exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$", exAsStr); - - ClassWithType obj = new ClassWithType { Prop = value }; - - ex = Assert.Throws(() => JsonSerializer.Serialize(obj)); - exAsStr = ex.ToString(); - Assert.Contains(fullName, exAsStr); - Assert.Contains("$.Prop", exAsStr); - - if (!type.IsValueType) - { - string serialized = JsonSerializer.Serialize((T)(object)null); - Assert.Equal("null", serialized); - - obj.Prop = (T)(object)null; - serialized = JsonSerializer.Serialize(obj); - Assert.Equal(@"{""Prop"":null}", serialized); - - serialized = JsonSerializer.Serialize(obj, new JsonSerializerOptions { IgnoreNullValues = true }); - Assert.Equal(@"{}", serialized); - } - } - } - [Theory] [InlineData(typeof(ClassWithBadCtor))] [InlineData(typeof(StructWithBadCtor))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs index 853ec365189827..00ca72aaeee5ea 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/ExtensionDataTests.cs @@ -1,1299 +1,10 @@ // 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.Collections.Immutable; -using System.Linq; -using System.Reflection; -using System.Text.Json.Nodes; -using System.Text.Json.Serialization; -using Xunit; - namespace System.Text.Json.Serialization.Tests { - public static class ExtensionDataTests + public sealed partial class ExtensionDataTestsDynamic : ExtensionDataTests { - [Fact] - public static void ExtensionPropertyNotUsed() - { - string json = @"{""MyNestedClass"":" + SimpleTestClass.s_json + "}"; - ClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); - Assert.Null(obj.MyOverflow); - } - - [Fact] - public static void ExtensionPropertyRoundTrip() - { - ClassWithExtensionProperty obj; - - { - string json = @"{""MyIntMissing"":2, ""MyInt"":1, ""MyNestedClassMissing"":" + SimpleTestClass.s_json + "}"; - obj = JsonSerializer.Deserialize(json); - Verify(); - } - - // Round-trip the json. - { - string json = JsonSerializer.Serialize(obj); - obj = JsonSerializer.Deserialize(json); - Verify(); - - // The json should not contain the dictionary name. - Assert.DoesNotContain(nameof(ClassWithExtensionProperty.MyOverflow), json); - } - - void Verify() - { - Assert.NotNull(obj.MyOverflow); - Assert.Equal(1, obj.MyInt); - Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); - - JsonProperty[] properties = obj.MyOverflow["MyNestedClassMissing"].EnumerateObject().ToArray(); - - // Verify a couple properties - Assert.Equal(1, properties.Where(prop => prop.Name == "MyInt16").First().Value.GetInt32()); - Assert.True(properties.Where(prop => prop.Name == "MyBooleanTrue").First().Value.GetBoolean()); - } - } - - [Fact] - public static void ExtensionFieldNotUsed() - { - string json = @"{""MyNestedClass"":" + SimpleTestClass.s_json + "}"; - ClassWithExtensionField obj = JsonSerializer.Deserialize(json); - Assert.Null(obj.MyOverflow); - } - - [Fact] - public static void ExtensionFieldRoundTrip() - { - ClassWithExtensionField obj; - - { - string json = @"{""MyIntMissing"":2, ""MyInt"":1, ""MyNestedClassMissing"":" + SimpleTestClass.s_json + "}"; - obj = JsonSerializer.Deserialize(json); - Verify(); - } - - // Round-trip the json. - { - string json = JsonSerializer.Serialize(obj); - obj = JsonSerializer.Deserialize(json); - Verify(); - - // The json should not contain the dictionary name. - Assert.DoesNotContain(nameof(ClassWithExtensionField.MyOverflow), json); - } - - void Verify() - { - Assert.NotNull(obj.MyOverflow); - Assert.Equal(1, obj.MyInt); - Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); - - JsonProperty[] properties = obj.MyOverflow["MyNestedClassMissing"].EnumerateObject().ToArray(); - - // Verify a couple properties - Assert.Equal(1, properties.Where(prop => prop.Name == "MyInt16").First().Value.GetInt32()); - Assert.True(properties.Where(prop => prop.Name == "MyBooleanTrue").First().Value.GetBoolean()); - } - } - - [Fact] - public static void ExtensionPropertyIgnoredWhenWritingDefault() - { - string expected = @"{}"; - string actual = JsonSerializer.Serialize(new ClassWithExtensionPropertyAsObject()); - Assert.Equal(expected, actual); - } - - [Fact] - public static void MultipleExtensionPropertyIgnoredWhenWritingDefault() - { - var obj = new ClassWithMultipleDictionaries(); - string actual = JsonSerializer.Serialize(obj); - Assert.Equal("{\"ActualDictionary\":null}", actual); - - obj = new ClassWithMultipleDictionaries - { - ActualDictionary = new Dictionary() - }; - actual = JsonSerializer.Serialize(obj); - Assert.Equal("{\"ActualDictionary\":{}}", actual); - - obj = new ClassWithMultipleDictionaries - { - MyOverflow = new Dictionary - { - { "test", "value" } - } - }; - actual = JsonSerializer.Serialize(obj); - Assert.Equal("{\"ActualDictionary\":null,\"test\":\"value\"}", actual); - - obj = new ClassWithMultipleDictionaries - { - ActualDictionary = new Dictionary(), - MyOverflow = new Dictionary - { - { "test", "value" } - } - }; - actual = JsonSerializer.Serialize(obj); - Assert.Equal("{\"ActualDictionary\":{},\"test\":\"value\"}", actual); - } - - [Fact] - public static void ExtensionPropertyInvalidJsonFail() - { - const string BadJson = @"{""Good"":""OK"",""Bad"":!}"; - - JsonException jsonException = Assert.Throws(() => JsonSerializer.Deserialize(BadJson)); - Assert.Contains("Path: $.Bad | LineNumber: 0 | BytePositionInLine: 19.", jsonException.ToString()); - Assert.NotNull(jsonException.InnerException); - Assert.IsAssignableFrom(jsonException.InnerException); - Assert.Contains("!", jsonException.InnerException.ToString()); - } - - [Fact] - public static void ExtensionPropertyAlreadyInstantiated() - { - Assert.NotNull(new ClassWithExtensionPropertyAlreadyInstantiated().MyOverflow); - - string json = @"{""MyIntMissing"":2}"; - - ClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); - Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); - } - - [Fact] - public static void ExtensionPropertyAsObject() - { - string json = @"{""MyIntMissing"":2}"; - - ClassWithExtensionPropertyAsObject obj = JsonSerializer.Deserialize(json); - Assert.IsType(obj.MyOverflow["MyIntMissing"]); - Assert.Equal(2, ((JsonElement)obj.MyOverflow["MyIntMissing"]).GetInt32()); - } - - [Fact] - public static void ExtensionPropertyCamelCasing() - { - // Currently we apply no naming policy. If we do (such as a ExtensionPropertyNamingPolicy), we'd also have to add functionality to the JsonDocument. - - ClassWithExtensionProperty obj; - const string jsonWithProperty = @"{""MyIntMissing"":1}"; - const string jsonWithPropertyCamelCased = @"{""myIntMissing"":1}"; - - { - // Baseline Pascal-cased json + no casing option. - obj = JsonSerializer.Deserialize(jsonWithProperty); - Assert.Equal(1, obj.MyOverflow["MyIntMissing"].GetInt32()); - string json = JsonSerializer.Serialize(obj); - Assert.Contains(@"""MyIntMissing"":1", json); - } - - { - // Pascal-cased json + camel casing option. - JsonSerializerOptions options = new JsonSerializerOptions(); - options.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - obj = JsonSerializer.Deserialize(jsonWithProperty, options); - Assert.Equal(1, obj.MyOverflow["MyIntMissing"].GetInt32()); - string json = JsonSerializer.Serialize(obj, options); - Assert.Contains(@"""MyIntMissing"":1", json); - } - - { - // Baseline camel-cased json + no casing option. - obj = JsonSerializer.Deserialize(jsonWithPropertyCamelCased); - Assert.Equal(1, obj.MyOverflow["myIntMissing"].GetInt32()); - string json = JsonSerializer.Serialize(obj); - Assert.Contains(@"""myIntMissing"":1", json); - } - - { - // Baseline camel-cased json + camel casing option. - JsonSerializerOptions options = new JsonSerializerOptions(); - options.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase; - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - obj = JsonSerializer.Deserialize(jsonWithPropertyCamelCased, options); - Assert.Equal(1, obj.MyOverflow["myIntMissing"].GetInt32()); - string json = JsonSerializer.Serialize(obj, options); - Assert.Contains(@"""myIntMissing"":1", json); - } - } - - [Fact] - public static void NullValuesIgnored() - { - const string json = @"{""MyNestedClass"":null}"; - const string jsonMissing = @"{""MyNestedClassMissing"":null}"; - - { - // Baseline with no missing. - ClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); - Assert.Null(obj.MyOverflow); - - string outJson = JsonSerializer.Serialize(obj); - Assert.Contains(@"""MyNestedClass"":null", outJson); - } - - { - // Baseline with missing. - ClassWithExtensionProperty obj = JsonSerializer.Deserialize(jsonMissing); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(JsonValueKind.Null, obj.MyOverflow["MyNestedClassMissing"].ValueKind); - } - - { - JsonSerializerOptions options = new JsonSerializerOptions(); - options.IgnoreNullValues = true; - - ClassWithExtensionProperty obj = JsonSerializer.Deserialize(jsonMissing, options); - - // Currently we do not ignore nulls in the extension data. The JsonDocument would also need to support this mode - // for any lower-level nulls. - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(JsonValueKind.Null, obj.MyOverflow["MyNestedClassMissing"].ValueKind); - } - } - - private class ClassWithInvalidExtensionProperty - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - private class ClassWithTwoExtensionProperties - { - [JsonExtensionData] - public Dictionary MyOverflow1 { get; set; } - - [JsonExtensionData] - public Dictionary MyOverflow2 { get; set; } - } - - [Fact] - public static void InvalidExtensionPropertyFail() - { - // Baseline - JsonSerializer.Deserialize(@"{}"); - JsonSerializer.Deserialize(@"{}"); - - Assert.Throws(() => JsonSerializer.Deserialize(@"{}")); - Assert.Throws(() => JsonSerializer.Deserialize(@"{}")); - } - - private class ClassWithIgnoredData - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - - [JsonIgnore] - public int MyInt { get; set; } - } - - [Fact] - public static void IgnoredDataShouldNotBeExtensionData() - { - ClassWithIgnoredData obj = JsonSerializer.Deserialize(@"{""MyInt"":1}"); - - Assert.Equal(0, obj.MyInt); - Assert.Null(obj.MyOverflow); - } - - private class ClassWithExtensionData - { - [JsonExtensionData] - public T Overflow { get; set; } - } - - public class CustomOverflowDictionary : Dictionary - { - } - - public class DictionaryOverflowConverter : JsonConverter> - { - public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) - { - writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); - } - } - - public class JsonElementOverflowConverter : JsonConverter> - { - public override Dictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, Dictionary value, JsonSerializerOptions options) - { - writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); - } - } - - public class JsonObjectOverflowConverter : JsonConverter - { - public override JsonObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, JsonObject value, JsonSerializerOptions options) - { - writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); - } - } - - public class CustomObjectDictionaryOverflowConverter : JsonConverter> - { - public override CustomOverflowDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, CustomOverflowDictionary value, JsonSerializerOptions options) - { - writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); - } - } - - public class CustomJsonElementDictionaryOverflowConverter : JsonConverter> - { - public override CustomOverflowDictionary Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - throw new NotImplementedException(); - } - - public override void Write(Utf8JsonWriter writer, CustomOverflowDictionary value, JsonSerializerOptions options) - { - writer.WriteString("MyCustomOverflowWrite", "OverflowValueWrite"); - } - } - - [Theory] - [InlineData(typeof(Dictionary), typeof(DictionaryOverflowConverter))] - [InlineData(typeof(Dictionary), typeof(JsonElementOverflowConverter))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomObjectDictionaryOverflowConverter))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomJsonElementDictionaryOverflowConverter))] - public static void ExtensionProperty_SupportsWritingToCustomSerializerWithOptions(Type overflowType, Type converterType) - { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_SupportsWritingToCustomSerializerWithOptionsInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(overflowType, converterType) - .Invoke(null, null); - } - - private static void ExtensionProperty_SupportsWritingToCustomSerializerWithOptionsInternal() - where TDictionary : new() - where TConverter : JsonConverter, new() - { - var root = new ClassWithExtensionData() - { - Overflow = new TDictionary() - }; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new TConverter()); - - string json = JsonSerializer.Serialize(root, options); - Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); - } - - private interface IClassWithOverflow - { - public T Overflow { get; set; } - } - - private class ClassWithExtensionDataWithAttributedConverter : IClassWithOverflow> - { - [JsonExtensionData] - [JsonConverter(typeof(DictionaryOverflowConverter))] - public Dictionary Overflow { get; set; } - } - - private class ClassWithJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow> - { - [JsonExtensionData] - [JsonConverter(typeof(JsonElementOverflowConverter))] - public Dictionary Overflow { get; set; } - } - - private class ClassWithCustomElementExtensionDataWithAttributedConverter : IClassWithOverflow> - { - [JsonExtensionData] - [JsonConverter(typeof(CustomObjectDictionaryOverflowConverter))] - public CustomOverflowDictionary Overflow { get; set; } - } - - private class ClassWithCustomJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow> - { - [JsonExtensionData] - [JsonConverter(typeof(CustomJsonElementDictionaryOverflowConverter))] - public CustomOverflowDictionary Overflow { get; set; } - } - - [Theory] - [InlineData(typeof(ClassWithExtensionDataWithAttributedConverter), typeof(Dictionary))] - [InlineData(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter), typeof(Dictionary))] - [InlineData(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary))] - [InlineData(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary))] - public static void ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverter(Type attributedType, Type dictionaryType) - { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverterInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(attributedType, dictionaryType) - .Invoke(null, null); - } - - private static void ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverterInternal() - where TRoot : IClassWithOverflow, new() - where TDictionary : new() - { - var root = new TRoot() - { - Overflow = new TDictionary() - }; - - string json = JsonSerializer.Serialize(root); - Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); - } - - [Theory] - [InlineData(typeof(Dictionary), typeof(DictionaryOverflowConverter), typeof(object))] - [InlineData(typeof(Dictionary), typeof(JsonElementOverflowConverter), typeof(JsonElement))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomObjectDictionaryOverflowConverter), typeof(object))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomJsonElementDictionaryOverflowConverter), typeof(JsonElement))] - public static void ExtensionProperty_IgnoresCustomSerializerWithOptions(Type overflowType, Type converterType, Type elementType) - { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_IgnoresCustomSerializerWithOptionsInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(overflowType, elementType, converterType) - .Invoke(null, null); - } - - [Fact] - public static void ExtensionProperty_IgnoresCustomSerializerWithOptions_JsonObject() - { - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonObjectOverflowConverter()); - - // A custom converter for JsonObject is not allowed on an extension property. - InvalidOperationException ex = Assert.Throws(() => - JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}", options)); - - Assert.Contains("JsonObject", ex.ToString()); - } - - private static void ExtensionProperty_IgnoresCustomSerializerWithOptionsInternal() - where TConverter : JsonConverter, new() - where TDictionary : IDictionary - { - var options = new JsonSerializerOptions(); - options.Converters.Add(new TConverter()); - - ClassWithExtensionData obj - = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}", options); - - Assert.Equal("TestValue", ((JsonElement)(object)obj.Overflow["TestKey"]).GetString()); - } - - [Theory] - [InlineData(typeof(ClassWithExtensionDataWithAttributedConverter), typeof(Dictionary), typeof(object))] - [InlineData(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter), typeof(Dictionary), typeof(JsonElement))] - [InlineData(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary), typeof(object))] - [InlineData(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary), typeof(JsonElement))] - public static void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverter(Type attributedType, Type dictionaryType, Type elementType) - { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_IgnoresCustomSerializerWithExplicitConverterInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(attributedType, dictionaryType, elementType) - .Invoke(null, null); - } - - [Fact] - public static void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverter_JsonObject() - { - ClassWithExtensionData obj - = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}"); - - Assert.Equal("TestValue", obj.Overflow["TestKey"].GetValue()); - } - - private static void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverterInternal() - where TRoot : IClassWithOverflow, new() - where TDictionary : IDictionary - { - ClassWithExtensionData obj - = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}"); - - Assert.Equal("TestValue", ((JsonElement)(object)obj.Overflow["TestKey"]).GetString()); - } - - [Fact] - public static void ExtensionPropertyObjectValue_Empty() - { - ClassWithExtensionPropertyAlreadyInstantiated obj = JsonSerializer.Deserialize(@"{}"); - Assert.Equal(@"{}", JsonSerializer.Serialize(obj)); - } - - [Fact] - public static void ExtensionPropertyObjectValue_SameAsExtensionPropertyName() - { - const string json = @"{""MyOverflow"":{""Key1"":""V""}}"; - - // Deserializing directly into the overflow is not supported by design. - ClassWithExtensionPropertyAsObject obj = JsonSerializer.Deserialize(json); - - // The JSON is treated as normal overflow. - Assert.NotNull(obj.MyOverflow["MyOverflow"]); - Assert.Equal(json, JsonSerializer.Serialize(obj)); - } - - private class ClassWithExtensionPropertyAsObjectAndNameProperty - { - public string Name { get; set; } - - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - public static IEnumerable JsonSerializerOptions() - { - yield return new object[] { null }; - yield return new object[] { new JsonSerializerOptions() }; - yield return new object[] { new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.JsonElement } }; - yield return new object[] { new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode } }; - } - - [Theory] - [MemberData(nameof(JsonSerializerOptions))] - public static void ExtensionPropertyDuplicateNames(JsonSerializerOptions options) - { - var obj = new ClassWithExtensionPropertyAsObjectAndNameProperty(); - obj.Name = "Name1"; - - obj.MyOverflow = new Dictionary(); - obj.MyOverflow["Name"] = "Name2"; - - string json = JsonSerializer.Serialize(obj, options); - Assert.Equal(@"{""Name"":""Name1"",""Name"":""Name2""}", json); - - // The overflow value comes last in the JSON so it overwrites the original value. - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal("Name2", obj.Name); - - // Since there was no overflow, this should be null. - Assert.Null(obj.MyOverflow); - } - - [Theory] - [MemberData(nameof(JsonSerializerOptions))] - public static void Null_SystemObject(JsonSerializerOptions options) - { - const string json = @"{""MissingProperty"":null}"; - - { - ClassWithExtensionPropertyAsObject obj = JsonSerializer.Deserialize(json, options); - - // A null value maps to , so the value is null. - object elem = obj.MyOverflow["MissingProperty"]; - Assert.Null(elem); - } - - { - ClassWithExtensionPropertyAsJsonObject obj = JsonSerializer.Deserialize(json, options); - - JsonObject jObject = obj.MyOverflow; - JsonNode jNode = jObject["MissingProperty"]; - // Since JsonNode is a reference type the value is null. - Assert.Null(jNode); - } - } - - [Fact] - public static void Null_JsonElement() - { - const string json = @"{""MissingProperty"":null}"; - - ClassWithExtensionPropertyAsJsonElement obj = JsonSerializer.Deserialize(json); - object elem = obj.MyOverflow["MissingProperty"]; - // Since JsonElement is a struct, it treats null as JsonValueKind.Null. - Assert.IsType(elem); - Assert.Equal(JsonValueKind.Null, ((JsonElement)elem).ValueKind); - } - - [Fact] - public static void Null_JsonObject() - { - const string json = @"{""MissingProperty"":null}"; - - ClassWithExtensionPropertyAsJsonObject obj = JsonSerializer.Deserialize(json); - object elem = obj.MyOverflow["MissingProperty"]; - // Since JsonNode is a reference type the value is null. - Assert.Null(elem); - } - - [Fact] - public static void ExtensionPropertyObjectValue() - { - // Baseline - ClassWithExtensionPropertyAlreadyInstantiated obj = JsonSerializer.Deserialize(@"{}"); - obj.MyOverflow.Add("test", new object()); - obj.MyOverflow.Add("test1", 1); - - Assert.Equal(@"{""test"":{},""test1"":1}", JsonSerializer.Serialize(obj)); - } - - private class DummyObj - { - public string Prop { get; set; } - } - - private struct DummyStruct - { - public string Prop { get; set; } - } - - [Theory] - [MemberData(nameof(JsonSerializerOptions))] - public static void ExtensionPropertyObjectValue_RoundTrip(JsonSerializerOptions options) - { - // Baseline - ClassWithExtensionPropertyAlreadyInstantiated obj = JsonSerializer.Deserialize(@"{}", options); - obj.MyOverflow.Add("test", new object()); - obj.MyOverflow.Add("test1", 1); - obj.MyOverflow.Add("test2", "text"); - obj.MyOverflow.Add("test3", new DummyObj() { Prop = "ObjectProp" }); - obj.MyOverflow.Add("test4", new DummyStruct() { Prop = "StructProp" }); - obj.MyOverflow.Add("test5", new Dictionary() { { "Key", "Value" }, { "Key1", "Value1" }, }); - - string json = JsonSerializer.Serialize(obj); - ClassWithExtensionPropertyAlreadyInstantiated roundTripObj = JsonSerializer.Deserialize(json, options); - - Assert.Equal(6, roundTripObj.MyOverflow.Count); - - if (options?.UnknownTypeHandling == JsonUnknownTypeHandling.JsonNode) - { - Assert.IsAssignableFrom(roundTripObj.MyOverflow["test"]); - Assert.IsAssignableFrom(roundTripObj.MyOverflow["test1"]); - Assert.IsAssignableFrom(roundTripObj.MyOverflow["test2"]); - Assert.IsAssignableFrom(roundTripObj.MyOverflow["test3"]); - - Assert.IsType(roundTripObj.MyOverflow["test"]); - - Assert.IsAssignableFrom(roundTripObj.MyOverflow["test1"]); - Assert.Equal(1, ((JsonValue)roundTripObj.MyOverflow["test1"]).GetValue()); - Assert.Equal(1, ((JsonValue)roundTripObj.MyOverflow["test1"]).GetValue()); - - Assert.IsAssignableFrom(roundTripObj.MyOverflow["test2"]); - Assert.Equal("text", ((JsonValue)roundTripObj.MyOverflow["test2"]).GetValue()); - - Assert.IsType(roundTripObj.MyOverflow["test3"]); - Assert.Equal("ObjectProp", ((JsonObject)roundTripObj.MyOverflow["test3"])["Prop"].GetValue()); - - Assert.IsType(roundTripObj.MyOverflow["test4"]); - Assert.Equal("StructProp", ((JsonObject)roundTripObj.MyOverflow["test4"])["Prop"].GetValue()); - - Assert.IsType(roundTripObj.MyOverflow["test5"]); - Assert.Equal("Value", ((JsonObject)roundTripObj.MyOverflow["test5"])["Key"].GetValue()); - Assert.Equal("Value1", ((JsonObject)roundTripObj.MyOverflow["test5"])["Key1"].GetValue()); - } - else - { - Assert.IsType(roundTripObj.MyOverflow["test"]); - Assert.IsType(roundTripObj.MyOverflow["test1"]); - Assert.IsType(roundTripObj.MyOverflow["test2"]); - Assert.IsType(roundTripObj.MyOverflow["test3"]); - - Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test"]).ValueKind); - - Assert.Equal(JsonValueKind.Number, ((JsonElement)roundTripObj.MyOverflow["test1"]).ValueKind); - Assert.Equal(1, ((JsonElement)roundTripObj.MyOverflow["test1"]).GetInt32()); - Assert.Equal(1, ((JsonElement)roundTripObj.MyOverflow["test1"]).GetInt64()); - - Assert.Equal(JsonValueKind.String, ((JsonElement)roundTripObj.MyOverflow["test2"]).ValueKind); - Assert.Equal("text", ((JsonElement)roundTripObj.MyOverflow["test2"]).GetString()); - - Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test3"]).ValueKind); - Assert.Equal("ObjectProp", ((JsonElement)roundTripObj.MyOverflow["test3"]).GetProperty("Prop").GetString()); - - Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test4"]).ValueKind); - Assert.Equal("StructProp", ((JsonElement)roundTripObj.MyOverflow["test4"]).GetProperty("Prop").GetString()); - - Assert.Equal(JsonValueKind.Object, ((JsonElement)roundTripObj.MyOverflow["test5"]).ValueKind); - Assert.Equal("Value", ((JsonElement)roundTripObj.MyOverflow["test5"]).GetProperty("Key").GetString()); - Assert.Equal("Value1", ((JsonElement)roundTripObj.MyOverflow["test5"]).GetProperty("Key1").GetString()); - } - } - - [Fact] - public static void DeserializeIntoJsonObjectProperty() - { - string json = @"{""MyDict"":{""Property1"":1}}"; - ClassWithExtensionPropertyAsJsonObject obj = - JsonSerializer.Deserialize(json); - - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(1, obj.MyOverflow["MyDict"]["Property1"].GetValue()); - } - - [Fact] - public static void DeserializeIntoSystemObjectProperty() - { - string json = @"{""MyDict"":{""Property1"":1}}"; - - Assert.Throws(() => - JsonSerializer.Deserialize(json)); - - // Cannot deserialize into System.Object overflow even if UnknownTypeHandling is set to use JsonNode. - var options = new JsonSerializerOptions { UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode }; - Assert.Throws(() => - JsonSerializer.Deserialize(json)); - } - - private class ClassWithReference - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - - public ClassWithExtensionProperty MyReference { get; set; } - } - - [Theory] - [InlineData(@"{""MyIntMissing"":2,""MyReference"":{""MyIntMissingChild"":3}}")] - [InlineData(@"{""MyReference"":{""MyIntMissingChild"":3},""MyIntMissing"":2}")] - [InlineData(@"{""MyReference"":{""MyNestedClass"":null,""MyInt"":0,""MyIntMissingChild"":3},""MyIntMissing"":2}")] - public static void NestedClass(string json) - { - ClassWithReference obj; - - void Verify() - { - Assert.IsType(obj.MyOverflow["MyIntMissing"]); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(2, obj.MyOverflow["MyIntMissing"].GetInt32()); - - ClassWithExtensionProperty child = obj.MyReference; - - Assert.IsType(child.MyOverflow["MyIntMissingChild"]); - Assert.IsType(child.MyOverflow["MyIntMissingChild"]); - Assert.Equal(1, child.MyOverflow.Count); - Assert.Equal(3, child.MyOverflow["MyIntMissingChild"].GetInt32()); - Assert.Null(child.MyNestedClass); - Assert.Equal(0, child.MyInt); - } - - obj = JsonSerializer.Deserialize(json); - Verify(); - - // Round-trip the json and verify. - json = JsonSerializer.Serialize(obj); - obj = JsonSerializer.Deserialize(json); - Verify(); - } - - private class ParentClassWithObject - { - public string Text { get; set; } - public ChildClassWithObject Child { get; set; } - - [JsonExtensionData] - public Dictionary ExtensionData { get; set; } = new Dictionary(); - } - - private class ChildClassWithObject - { - public int Number { get; set; } - - [JsonExtensionData] - public Dictionary ExtensionData { get; set; } = new Dictionary(); - } - - [Fact] - public static void NestedClassWithObjectExtensionDataProperty() - { - var child = new ChildClassWithObject { Number = 2 }; - child.ExtensionData.Add("SpecialInformation", "I am child class"); - - var parent = new ParentClassWithObject { Text = "Hello World" }; - parent.ExtensionData.Add("SpecialInformation", "I am parent class"); - parent.Child = child; - - // The extension data is based on the raw strings added above and not JsonElement. - Assert.Equal("Hello World", parent.Text); - Assert.IsType(parent.ExtensionData["SpecialInformation"]); - Assert.Equal("I am parent class", (string)parent.ExtensionData["SpecialInformation"]); - Assert.Equal(2, parent.Child.Number); - Assert.IsType(parent.Child.ExtensionData["SpecialInformation"]); - Assert.Equal("I am child class", (string)parent.Child.ExtensionData["SpecialInformation"]); - - // Round-trip and verify. Extension data is now based on JsonElement. - string json = JsonSerializer.Serialize(parent); - parent = JsonSerializer.Deserialize(json); - - Assert.Equal("Hello World", parent.Text); - Assert.IsType(parent.ExtensionData["SpecialInformation"]); - Assert.Equal("I am parent class", ((JsonElement)parent.ExtensionData["SpecialInformation"]).GetString()); - Assert.Equal(2, parent.Child.Number); - Assert.IsType(parent.Child.ExtensionData["SpecialInformation"]); - Assert.Equal("I am child class", ((JsonElement)parent.Child.ExtensionData["SpecialInformation"]).GetString()); - } - - private class ParentClassWithJsonElement - { - public string Text { get; set; } - - public List Children { get; set; } = new List(); - - [JsonExtensionData] - // Use SortedDictionary as verification of supporting derived dictionaries. - public SortedDictionary ExtensionData { get; set; } = new SortedDictionary(); - } - - private class ChildClassWithJsonElement - { - public int Number { get; set; } - - [JsonExtensionData] - public Dictionary ExtensionData { get; set; } = new Dictionary(); - } - - [Fact] - public static void NestedClassWithJsonElementExtensionDataProperty() - { - var child = new ChildClassWithJsonElement { Number = 4 }; - child.ExtensionData.Add("SpecialInformation", JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes("I am child class")).RootElement); - - var parent = new ParentClassWithJsonElement { Text = "Hello World" }; - parent.ExtensionData.Add("SpecialInformation", JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes("I am parent class")).RootElement); - parent.Children.Add(child); - - Verify(); - - // Round-trip and verify. - string json = JsonSerializer.Serialize(parent); - parent = JsonSerializer.Deserialize(json); - Verify(); - - void Verify() - { - Assert.Equal("Hello World", parent.Text); - Assert.Equal("I am parent class", parent.ExtensionData["SpecialInformation"].GetString()); - Assert.Equal(1, parent.Children.Count); - Assert.Equal(4, parent.Children[0].Number); - Assert.Equal("I am child class", parent.Children[0].ExtensionData["SpecialInformation"].GetString()); - } - } - - [Fact] - public static void DeserializeIntoObjectProperty() - { - ClassWithExtensionPropertyAsObject obj; - string json; - - // Baseline dictionary. - json = @"{""MyDict"":{""Property1"":1}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(1, ((JsonElement)obj.MyOverflow["MyDict"]).EnumerateObject().First().Value.GetInt32()); - - // Attempt to deserialize directly into the overflow property; this is just added as a normal missing property like MyDict above. - json = @"{""MyOverflow"":{""Property1"":1}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(1, ((JsonElement)obj.MyOverflow["MyOverflow"]).EnumerateObject().First().Value.GetInt32()); - - // Attempt to deserialize null into the overflow property. This is also treated as a missing property. - json = @"{""MyOverflow"":null}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Null(obj.MyOverflow["MyOverflow"]); - - // Attempt to deserialize object into the overflow property. This is also treated as a missing property. - json = @"{""MyOverflow"":{}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(JsonValueKind.Object, ((JsonElement)obj.MyOverflow["MyOverflow"]).ValueKind); - } - - [Fact] - public static void DeserializeIntoMultipleDictionaries() - { - ClassWithMultipleDictionaries obj; - string json; - - // Baseline dictionary. - json = @"{""ActualDictionary"":{""Key"": {""Property0"":-1}},""MyDict"":{""Property1"":1}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(1, ((JsonElement)obj.MyOverflow["MyDict"]).EnumerateObject().First().Value.GetInt32()); - Assert.Equal(1, obj.ActualDictionary.Count); - Assert.Equal(-1, ((JsonElement)obj.ActualDictionary["Key"]).EnumerateObject().First().Value.GetInt32()); - - // Attempt to deserialize null into the dictionary and overflow property. This is also treated as a missing property. - json = @"{""ActualDictionary"":null,""MyOverflow"":null}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Null(obj.MyOverflow["MyOverflow"]); - Assert.Null(obj.ActualDictionary); - - // Attempt to deserialize object into the dictionary and overflow property. This is also treated as a missing property. - json = @"{""ActualDictionary"":{},""MyOverflow"":{}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(JsonValueKind.Object, ((JsonElement)obj.MyOverflow["MyOverflow"]).ValueKind); - Assert.Equal(0, obj.ActualDictionary.Count); - } - - [Fact] - public static void DeserializeIntoJsonElementProperty() - { - ClassWithExtensionPropertyAsJsonElement obj; - string json; - - // Baseline dictionary. - json = @"{""MyDict"":{""Property1"":1}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(1, obj.MyOverflow["MyDict"].EnumerateObject().First().Value.GetInt32()); - - // Attempt to deserialize directly into the overflow property; this is just added as a normal missing property like MyDict above. - json = @"{""MyOverflow"":{""Property1"":1}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(1, obj.MyOverflow["MyOverflow"].EnumerateObject().First().Value.GetInt32()); - - // Attempt to deserialize null into the overflow property. This is also treated as a missing property. - json = @"{""MyOverflow"":null}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(JsonValueKind.Null, obj.MyOverflow["MyOverflow"].ValueKind); - - // Attempt to deserialize object into the overflow property. This is also treated as a missing property. - json = @"{""MyOverflow"":{}}"; - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(JsonValueKind.Object, obj.MyOverflow["MyOverflow"].ValueKind); - } - - [Fact] - public static void SerializerOutputRoundtripsWhenEscaping() - { - string jsonString = "{\"\u6C49\u5B57\":\"abc\",\"Class\":{\"\u6F22\u5B57\":\"xyz\"},\"\u62DC\u6258\":{\"\u62DC\u6258\u62DC\u6258\":1}}"; - - ClassWithEscapedProperty input = JsonSerializer.Deserialize(jsonString); - - Assert.Equal("abc", input.\u6C49\u5B57); - Assert.Equal("xyz", input.Class.\u6F22\u5B57); - - string normalizedString = JsonSerializer.Serialize(input); - - Assert.Equal(normalizedString, JsonSerializer.Serialize(JsonSerializer.Deserialize(normalizedString))); - } - - public class ClassWithEscapedProperty - { - public string \u6C49\u5B57 { get; set; } - public NestedClassWithEscapedProperty Class { get; set; } - - [JsonExtensionData] - public Dictionary Overflow { get; set; } - } - - public class NestedClassWithEscapedProperty - { - public string \u6F22\u5B57 { get; set; } - } - - private class ClassWithInvalidExtensionPropertyStringString - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - private class ClassWithInvalidExtensionPropertyObjectString - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - private class ClassWithInvalidExtensionPropertyStringJsonNode - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - [Fact] - public static void ExtensionProperty_InvalidDictionary() - { - var obj1 = new ClassWithInvalidExtensionPropertyStringString(); - Assert.Throws(() => JsonSerializer.Serialize(obj1)); - - var obj2 = new ClassWithInvalidExtensionPropertyObjectString(); - Assert.Throws(() => JsonSerializer.Serialize(obj2)); - - var obj3 = new ClassWithInvalidExtensionPropertyStringJsonNode(); - Assert.Throws(() => JsonSerializer.Serialize(obj3)); - } - - private class ClassWithExtensionPropertyAlreadyInstantiated - { - public ClassWithExtensionPropertyAlreadyInstantiated() - { - MyOverflow = new Dictionary(); - } - - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyAsObject - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyAsJsonElement - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyAsJsonObject - { - [JsonExtensionData] - public JsonObject MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyAsSystemObject - { - [JsonExtensionData] - public object MyOverflow { get; set; } - } - - private class ClassWithMultipleDictionaries - { - [JsonExtensionData] - public Dictionary MyOverflow { get; set; } - - public Dictionary ActualDictionary { get; set; } - } - - [Fact] - public static void DeserializeIntoImmutableDictionaryProperty() - { - // baseline - JsonSerializer.Deserialize(@"{}"); - JsonSerializer.Deserialize(@"{}"); - JsonSerializer.Deserialize(@"{}"); - JsonSerializer.Deserialize(@"{}"); - - Assert.Throws(() => JsonSerializer.Deserialize("{\"hello\":\"world\"}")); - Assert.Throws(() => JsonSerializer.Deserialize("{\"hello\":\"world\"}")); - Assert.Throws(() => JsonSerializer.Deserialize("{\"hello\":\"world\"}")); - Assert.Throws(() => JsonSerializer.Deserialize("{\"hello\":\"world\"}")); - Assert.Throws(() => JsonSerializer.Deserialize("{\"hello\":\"world\"}")); - Assert.Throws(() => JsonSerializer.Deserialize("{\"hello\":\"world\"}")); - } - - [Fact] - public static void SerializeIntoImmutableDictionaryProperty() - { - // attempt to serialize a null immutable dictionary - string expectedJson = "{}"; - var obj = new ClassWithExtensionPropertyAsImmutable(); - var json = JsonSerializer.Serialize(obj); - Assert.Equal(expectedJson, json); - - // attempt to serialize an empty immutable dictionary - expectedJson = "{}"; - obj = new ClassWithExtensionPropertyAsImmutable(); - obj.MyOverflow = ImmutableDictionary.Empty; - json = JsonSerializer.Serialize(obj); - Assert.Equal(expectedJson, json); - - // attempt to serialize a populated immutable dictionary - expectedJson = "{\"hello\":\"world\"}"; - obj = new ClassWithExtensionPropertyAsImmutable(); - var dictionaryStringObject = new Dictionary { { "hello", "world" } }; - obj.MyOverflow = ImmutableDictionary.CreateRange(dictionaryStringObject); - json = JsonSerializer.Serialize(obj); - Assert.Equal(expectedJson, json); - } - - private class ClassWithExtensionPropertyAsImmutable - { - [JsonExtensionData] - public ImmutableDictionary MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyAsImmutableJsonElement - { - [JsonExtensionData] - public ImmutableDictionary MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyPrivateConstructor - { - [JsonExtensionData] - public GenericIDictionaryWrapperPrivateConstructor MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyPrivateConstructorJsonElement - { - [JsonExtensionData] - public GenericIDictionaryWrapperPrivateConstructor MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyCustomIImmutable - { - [JsonExtensionData] - public GenericIImmutableDictionaryWrapper MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyCustomIImmutableJsonElement - { - [JsonExtensionData] - public GenericIImmutableDictionaryWrapper MyOverflow { get; set; } - } - - [Theory] - [InlineData(typeof(ClassWithExtensionPropertyNoGenericParameters))] - [InlineData(typeof(ClassWithExtensionPropertyOneGenericParameter))] - [InlineData(typeof(ClassWithExtensionPropertyThreeGenericParameters))] - public static void DeserializeIntoGenericDictionaryParameterCount(Type type) - { - object obj = JsonSerializer.Deserialize("{\"hello\":\"world\"}", type); - - IDictionary extData = (IDictionary)type.GetProperty("MyOverflow").GetValue(obj)!; - Assert.Equal("world", ((JsonElement)extData["hello"]).GetString()); - } - - private class ClassWithExtensionPropertyNoGenericParameters - { - [JsonExtensionData] - public StringToObjectIDictionaryWrapper MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyOneGenericParameter - { - [JsonExtensionData] - public StringToGenericIDictionaryWrapper MyOverflow { get; set; } - } - - private class ClassWithExtensionPropertyThreeGenericParameters - { - [JsonExtensionData] - public GenericIDictonaryWrapperThreeGenericParameters MyOverflow { get; set; } - } - - [Fact] - public static void CustomObjectConverterInExtensionProperty() - { - const string Json = "{\"hello\": \"world\"}"; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new ObjectConverter()); - - ClassWithExtensionPropertyAsObject obj = JsonSerializer.Deserialize(Json, options); - object overflowProp = obj.MyOverflow["hello"]; - Assert.IsType(overflowProp); - Assert.Equal("world!!!", ((string)overflowProp)); - - string newJson = JsonSerializer.Serialize(obj, options); - Assert.Equal("{\"hello\":\"world!!!\"}", newJson); - } - - private class ObjectConverter : JsonConverter - { - public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - return reader.GetString() + "!!!"; - } - - public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) - { - // Since we are in a user-provided (not internal to S.T.Json) object converter, - // this converter will be called, not the internal string converter. - writer.WriteStringValue((string)value); - } - } - - [Fact] - public static void CustomJsonElementConverterInExtensionProperty() - { - const string Json = "{\"hello\": \"world\"}"; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonElementConverter()); - - ClassWithExtensionPropertyAsJsonElement obj = JsonSerializer.Deserialize(Json, options); - JsonElement overflowProp = obj.MyOverflow["hello"]; - Assert.Equal(JsonValueKind.Undefined, overflowProp.ValueKind); - - string newJson = JsonSerializer.Serialize(obj, options); - Assert.Equal("{\"hello\":{\"Hi\":\"There\"}}", newJson); - } - - private class JsonElementConverter : JsonConverter - { - public override JsonElement Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - // Just return an empty JsonElement. - reader.Skip(); - return new JsonElement(); - } - - public override void Write(Utf8JsonWriter writer, JsonElement value, JsonSerializerOptions options) - { - // Write a string we can test against easily. - writer.WriteStartObject(); - writer.WriteString("Hi", "There"); - writer.WriteEndObject(); - } - } - - [Fact] - public static void CustomJsonObjectConverterInExtensionProperty() - { - const string Json = "{\"hello\": \"world\"}"; - - var options = new JsonSerializerOptions(); - options.Converters.Add(new JsonObjectConverter()); - - // A custom converter for JsonObject is not allowed on an extension property. - InvalidOperationException ex = Assert.Throws(() => - JsonSerializer.Deserialize(Json, options)); - - Assert.Contains("JsonObject", ex.ToString()); - } - - private class JsonObjectConverter : JsonConverter - { - public override JsonObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - // Just return an empty JsonElement. - reader.Skip(); - return new JsonObject(); - } - - public override void Write(Utf8JsonWriter writer, JsonObject value, JsonSerializerOptions options) - { - // Write a string we can test against easily. - writer.WriteStartObject(); - writer.WriteString("Hi", "There"); - writer.WriteEndObject(); - } - } + public ExtensionDataTestsDynamic() : base(JsonSerializerWrapperForString.StringSerializer) { } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs index aeb4c30fd2cabd..515579fc26ec85 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs @@ -61,9 +61,10 @@ private class MyPoco { } internal partial class MyDummyContext : JsonSerializerContext { - public MyDummyContext() : base(new JsonSerializerOptions(), new JsonSerializerOptions()) { } - public MyDummyContext(JsonSerializerOptions options) : base(options, new JsonSerializerOptions()) { } + public MyDummyContext() : base(new JsonSerializerOptions()) { } + public MyDummyContext(JsonSerializerOptions options) : base(options) { } public override JsonTypeInfo? GetTypeInfo(Type type) => throw new NotImplementedException(); + protected override JsonSerializerOptions? GeneratedSerializerOptions => null; } private JsonTypeInfo myDummyTypeInfo = GetTypeInfo(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs index c25e7803f9220d..567a2776b1e0c8 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs @@ -89,17 +89,20 @@ public void OptionsImmutableAfterBinding() private class MyJsonContext : JsonSerializerContext { - public MyJsonContext() : base(null, null) { } + public MyJsonContext() : base(null) { } - public MyJsonContext(JsonSerializerOptions options) : base(options, null) { } + public MyJsonContext(JsonSerializerOptions options) : base(options) { } public override JsonTypeInfo? GetTypeInfo(Type type) => throw new NotImplementedException(); + + protected override JsonSerializerOptions? GeneratedSerializerOptions => null; } private class MyJsonContextThatSetsOptionsInParameterlessCtor : JsonSerializerContext { - public MyJsonContextThatSetsOptionsInParameterlessCtor() : base(new JsonSerializerOptions(), null) { } + public MyJsonContextThatSetsOptionsInParameterlessCtor() : base(new JsonSerializerOptions()) { } public override JsonTypeInfo? GetTypeInfo(Type type) => throw new NotImplementedException(); + protected override JsonSerializerOptions? GeneratedSerializerOptions => null; } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs new file mode 100644 index 00000000000000..a424cb884f5605 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.Json.Serialization.Tests +{ + public sealed partial class NodeInteropTestsDynamic : NodeInteropTests + { + public NodeInteropTestsDynamic() : base(JsonSerializerWrapperForString.StringSerializer) { } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.ReadTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.ReadTests.cs index 6a36e96d3818b9..c8a745398af275 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.ReadTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.ReadTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text.Json.Nodes; using Xunit; namespace System.Text.Json.Serialization.Tests @@ -655,5 +656,20 @@ public static void TooLittleJsonFails(string json) Assert.Equal(0, reader.BytesConsumed); } + + [Theory] + [InlineData(JsonUnknownTypeHandling.JsonElement, typeof(JsonElement))] + [InlineData(JsonUnknownTypeHandling.JsonNode, typeof(JsonNode))] + public static void ReadSystemObjectWithNumberHandling(JsonUnknownTypeHandling unknownTypeHandling, Type expectedType) + { + var options = new JsonSerializerOptions + { + NumberHandling = JsonNumberHandling.AllowReadingFromString, + UnknownTypeHandling = unknownTypeHandling + }; + + object result = JsonSerializer.Deserialize(@"{ ""key"" : ""42"" }", options); + Assert.IsAssignableFrom(expectedType, result); + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.WriteTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.WriteTests.cs index d4e551d6d01b25..c569770e3027e1 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.WriteTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Object.WriteTests.cs @@ -138,5 +138,13 @@ public static void EscapingShouldntStackOverflow() Assert.Equal("{\"name\":\"\u6D4B\u8A6611\"}", result); } + + [Fact] + public static void WriteSystemObjectWithNumberHandling() + { + var options = new JsonSerializerOptions { NumberHandling = JsonNumberHandling.AllowReadingFromString }; + string result = JsonSerializer.Serialize(new object(), options); + Assert.Equal("{}", result); + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PropertyNameTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PropertyNameTests.cs index 6a14f3ed63cb85..1423174297bff6 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PropertyNameTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/PropertyNameTests.cs @@ -1,185 +1,28 @@ -// Licensed to the .NET Foundation under one or more agreements. +// 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.Text.Encodings.Web; +using System.Threading.Tasks; using Xunit; namespace System.Text.Json.Serialization.Tests { - public static class PropertyNameTests + public sealed partial class PropertyNameTestsDynamic : PropertyNameTests { - [Fact] - public static void CamelCaseDeserializeNoMatch() - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - SimpleTestClass obj = JsonSerializer.Deserialize(@"{""MyInt16"":1}", options); - - // This is 0 (default value) because the data does not match the property "MyInt16" that is assuming camel-casing of "myInt16". - Assert.Equal(0, obj.MyInt16); - } - - [Fact] - public static void CamelCaseDeserializeMatch() - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - SimpleTestClass obj = JsonSerializer.Deserialize(@"{""myInt16"":1}", options); - - // This is 1 because the data matches the property "MyInt16" that is assuming camel-casing of "myInt16". - Assert.Equal(1, obj.MyInt16); - } - - [Fact] - public static void CamelCaseSerialize() - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - SimpleTestClass obj = JsonSerializer.Deserialize(@"{}", options); - - string json = JsonSerializer.Serialize(obj, options); - Assert.Contains(@"""myInt16"":0", json); - Assert.Contains(@"""myInt32"":0", json); - } - - [Fact] - public static void CustomNamePolicy() - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = new UppercaseNamingPolicy(); - - SimpleTestClass obj = JsonSerializer.Deserialize(@"{""MYINT16"":1}", options); - - // This is 1 because the data matches the property "MYINT16" that is uppercase of "myInt16". - Assert.Equal(1, obj.MyInt16); - } - - [Fact] - public static void NullNamePolicy() - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = new NullNamingPolicy(); - - // A policy that returns null is not allowed. - Assert.Throws(() => JsonSerializer.Deserialize(@"{}", options)); - Assert.Throws(() => JsonSerializer.Serialize(new SimpleTestClass(), options)); - } - - [Fact] - public static void IgnoreCase() - { - { - // A non-match scenario with no options (case-sensitive by default). - SimpleTestClass obj = JsonSerializer.Deserialize(@"{""myint16"":1}"); - Assert.Equal(0, obj.MyInt16); - } - - { - // A non-match scenario with default options (case-sensitive by default). - var options = new JsonSerializerOptions(); - SimpleTestClass obj = JsonSerializer.Deserialize(@"{""myint16"":1}", options); - Assert.Equal(0, obj.MyInt16); - } - - { - var options = new JsonSerializerOptions(); - options.PropertyNameCaseInsensitive = true; - SimpleTestClass obj = JsonSerializer.Deserialize(@"{""myint16"":1}", options); - Assert.Equal(1, obj.MyInt16); - } - } - - [Fact] - public static void JsonPropertyNameAttribute() - { - { - OverridePropertyNameDesignTime_TestClass obj = JsonSerializer.Deserialize(@"{""Blah"":1}"); - Assert.Equal(1, obj.myInt); - - obj.myObject = 2; - - string json = JsonSerializer.Serialize(obj); - Assert.Contains(@"""Blah"":1", json); - Assert.Contains(@"""BlahObject"":2", json); - } - - // The JsonPropertyNameAttribute should be unaffected by JsonNamingPolicy and PropertyNameCaseInsensitive. - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - options.PropertyNameCaseInsensitive = true; - - OverridePropertyNameDesignTime_TestClass obj = JsonSerializer.Deserialize(@"{""Blah"":1}", options); - Assert.Equal(1, obj.myInt); - - string json = JsonSerializer.Serialize(obj); - Assert.Contains(@"""Blah"":1", json); - } - } - - [Fact] - public static void JsonNameAttributeDuplicateDesignTimeFail() - { - { - var options = new JsonSerializerOptions(); - Assert.Throws(() => JsonSerializer.Deserialize("{}", options)); - } - - { - var options = new JsonSerializerOptions(); - Assert.Throws(() => JsonSerializer.Serialize(new DuplicatePropertyNameDesignTime_TestClass(), options)); - } - } + public PropertyNameTestsDynamic() : base(JsonSerializerWrapperForString.StringSerializer) { } [Fact] - public static void JsonNullNameAttribute() + public async Task JsonNullNameAttribute() { var options = new JsonSerializerOptions(); options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.PropertyNameCaseInsensitive = true; // A null name in JsonPropertyNameAttribute is not allowed. - Assert.Throws(() => JsonSerializer.Serialize(new NullPropertyName_TestClass(), options)); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new NullPropertyName_TestClass(), options)); } [Fact] - public static void JsonNameConflictOnCamelCasingFail() - { - { - // Baseline comparison - no options set. - IntPropertyNamesDifferentByCaseOnly_TestClass obj = JsonSerializer.Deserialize("{}"); - JsonSerializer.Serialize(obj); - } - - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - Assert.Throws(() => JsonSerializer.Deserialize("{}", options)); - Assert.Throws(() => JsonSerializer.Serialize(new IntPropertyNamesDifferentByCaseOnly_TestClass(), options)); - } - - { - // Baseline comparison - no options set. - ObjectPropertyNamesDifferentByCaseOnly_TestClass obj = JsonSerializer.Deserialize("{}"); - JsonSerializer.Serialize(obj); - } - - { - var options = new JsonSerializerOptions(); - options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - - Assert.Throws(() => JsonSerializer.Deserialize("{}", options)); - Assert.Throws(() => JsonSerializer.Serialize(new ObjectPropertyNamesDifferentByCaseOnly_TestClass(), options)); - } - } - - [Fact] - public static void JsonNameConflictOnCaseInsensitiveFail() + public async Task JsonNameConflictOnCaseInsensitiveFail() { string json = @"{""myInt"":1,""MyInt"":2}"; @@ -187,407 +30,9 @@ public static void JsonNameConflictOnCaseInsensitiveFail() var options = new JsonSerializerOptions(); options.PropertyNameCaseInsensitive = true; - Assert.Throws(() => JsonSerializer.Deserialize(json, options)); - Assert.Throws(() => JsonSerializer.Serialize(new IntPropertyNamesDifferentByCaseOnly_TestClass(), options)); - } - } - - [Fact] - public static void JsonOutputNotAffectedByCasingPolicy() - { - { - // Baseline. - string json = JsonSerializer.Serialize(new SimpleTestClass()); - Assert.Contains(@"""MyInt16"":0", json); - } - - // The JSON output should be unaffected by PropertyNameCaseInsensitive. - { - var options = new JsonSerializerOptions(); - options.PropertyNameCaseInsensitive = true; - - string json = JsonSerializer.Serialize(new SimpleTestClass(), options); - Assert.Contains(@"""MyInt16"":0", json); - } - } - - [Fact] - public static void EmptyPropertyName() - { - string json = @"{"""":1}"; - - { - var obj = new EmptyPropertyName_TestClass(); - obj.MyInt1 = 1; - - string jsonOut = JsonSerializer.Serialize(obj); - Assert.Equal(json, jsonOut); - } - - { - EmptyPropertyName_TestClass obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyInt1); - } - } - - [Fact] - public static void EmptyPropertyNameInExtensionData() - { - { - string json = @"{"""":42}"; - EmptyClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(42, obj.MyOverflow[""].GetInt32()); - } - - { - // Verify that last-in wins. - string json = @"{"""":42, """":43}"; - EmptyClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(43, obj.MyOverflow[""].GetInt32()); - } - } - - [Fact] - public static void EmptyPropertyName_WinsOver_ExtensionDataEmptyPropertyName() - { - string json = @"{"""":1}"; - - ClassWithEmptyPropertyNameAndExtensionProperty obj; - - // Create a new options instances to re-set any caches. - JsonSerializerOptions options = new JsonSerializerOptions(); - - // Verify the real property wins over the extension data property. - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal(1, obj.MyInt1); - Assert.Null(obj.MyOverflow); - } - - [Fact] - public static void EmptyPropertyNameAndExtensionData_ExtDataFirst() - { - // Verify any caching treats real property (with empty name) differently than a missing property. - - ClassWithEmptyPropertyNameAndExtensionProperty obj; - - // Create a new options instances to re-set any caches. - JsonSerializerOptions options = new JsonSerializerOptions(); - - // First populate cache with a missing property name. - string json = @"{""DoesNotExist"":42}"; - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal(0, obj.MyInt1); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(42, obj.MyOverflow["DoesNotExist"].GetInt32()); - - // Then use an empty property. - json = @"{"""":43}"; - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal(43, obj.MyInt1); - Assert.Null(obj.MyOverflow); - } - - [Fact] - public static void EmptyPropertyAndExtensionData_PropertyFirst() - { - // Verify any caching treats real property (with empty name) differently than a missing property. - - ClassWithEmptyPropertyNameAndExtensionProperty obj; - - // Create a new options instances to re-set any caches. - JsonSerializerOptions options = new JsonSerializerOptions(); - - // First use an empty property. - string json = @"{"""":43}"; - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal(43, obj.MyInt1); - Assert.Null(obj.MyOverflow); - - // Then populate cache with a missing property name. - json = @"{""DoesNotExist"":42}"; - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal(0, obj.MyInt1); - Assert.Equal(1, obj.MyOverflow.Count); - Assert.Equal(42, obj.MyOverflow["DoesNotExist"].GetInt32()); - } - - [Fact] - public static void UnicodePropertyNames() - { - ClassWithUnicodeProperty obj = JsonSerializer.Deserialize("{\"A\u0467\":1}"); - Assert.Equal(1, obj.A\u0467); - - // Specifying encoder on options does not impact deserialize. - var options = new JsonSerializerOptions(); - options.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; - - obj = JsonSerializer.Deserialize("{\"A\u0467\":1}", options); - Assert.Equal(1, obj.A\u0467); - - string json; - - // Verify the name is escaped after serialize. - json = JsonSerializer.Serialize(obj); - Assert.Contains(@"""A\u0467"":1", json); - - // With custom escaper - json = JsonSerializer.Serialize(obj, options); - Assert.Contains("\"A\u0467\":1", json); - - // Verify the name is unescaped after deserialize. - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.A\u0467); - - // With custom escaper - obj = JsonSerializer.Deserialize(json, options); - Assert.Equal(1, obj.A\u0467); - } - - [Fact] - public static void UnicodePropertyNamesWithPooledAlloc() - { - // We want to go over StackallocByteThreshold=256 to force a pooled allocation, so this property is 400 chars and 401 bytes. - ClassWithUnicodeProperty obj = JsonSerializer.Deserialize("{\"A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\":1}"); - Assert.Equal(1, obj.A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890); - - // Verify the name is escaped after serialize. - string json = JsonSerializer.Serialize(obj); - Assert.Contains(@"""A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"":1", json); - - // Verify the name is unescaped after deserialize. - obj = JsonSerializer.Deserialize(json); - Assert.Equal(1, obj.A\u046734567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890); - } - - [Fact] - public static void ExtensionDataDictionarySerialize_DoesNotHonor() - { - var options = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - - EmptyClassWithExtensionProperty obj = JsonSerializer.Deserialize(@"{""Key1"": 1}", options); - - // Ignore naming policy for extension data properties by default. - Assert.False(obj.MyOverflow.ContainsKey("key1")); - Assert.Equal(1, obj.MyOverflow["Key1"].GetInt32()); - } - - private class ClassWithPropertyNamePermutations - { - public int a { get; set; } - public int aa { get; set; } - public int aaa { get; set; } - public int aaaa { get; set; } - public int aaaaa { get; set; } - public int aaaaaa { get; set; } - - // 7 characters - caching code only keys up to 7. - public int aaaaaaa { get; set; } - public int aaaaaab { get; set; } - - // 8 characters. - public int aaaaaaaa { get; set; } - public int aaaaaaab { get; set; } - - // 9 characters. - public int aaaaaaaaa { get; set; } - public int aaaaaaaab { get; set; } - - public int \u0467 { get; set; } - public int \u0467\u0467 { get; set; } - public int \u0467\u0467a { get; set; } - public int \u0467\u0467b { get; set; } - public int \u0467\u0467\u0467 { get; set; } - public int \u0467\u0467\u0467a { get; set; } - public int \u0467\u0467\u0467b { get; set; } - public int \u0467\u0467\u0467\u0467 { get; set; } - public int \u0467\u0467\u0467\u0467a { get; set; } - public int \u0467\u0467\u0467\u0467b { get; set; } - } - - [Fact] - public static void CachingKeys() - { - ClassWithPropertyNamePermutations obj; - - void Verify() - { - Assert.Equal(1, obj.a); - Assert.Equal(2, obj.aa); - Assert.Equal(3, obj.aaa); - Assert.Equal(4, obj.aaaa); - Assert.Equal(5, obj.aaaaa); - Assert.Equal(6, obj.aaaaaa); - Assert.Equal(7, obj.aaaaaaa); - Assert.Equal(7, obj.aaaaaab); - Assert.Equal(8, obj.aaaaaaaa); - Assert.Equal(8, obj.aaaaaaab); - Assert.Equal(9, obj.aaaaaaaaa); - Assert.Equal(9, obj.aaaaaaaab); - - Assert.Equal(2, obj.\u0467); - Assert.Equal(4, obj.\u0467\u0467); - Assert.Equal(5, obj.\u0467\u0467a); - Assert.Equal(5, obj.\u0467\u0467b); - Assert.Equal(6, obj.\u0467\u0467\u0467); - Assert.Equal(7, obj.\u0467\u0467\u0467a); - Assert.Equal(7, obj.\u0467\u0467\u0467b); - Assert.Equal(8, obj.\u0467\u0467\u0467\u0467); - Assert.Equal(9, obj.\u0467\u0467\u0467\u0467a); - Assert.Equal(9, obj.\u0467\u0467\u0467\u0467b); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.DeserializeWrapper(json, options)); + await Assert.ThrowsAsync(async () => await JsonSerializerWrapperForString.SerializeWrapper(new IntPropertyNamesDifferentByCaseOnly_TestClass(), options)); } - - obj = new ClassWithPropertyNamePermutations - { - a = 1, - aa = 2, - aaa = 3, - aaaa = 4, - aaaaa = 5, - aaaaaa = 6, - aaaaaaa = 7, - aaaaaab = 7, - aaaaaaaa = 8, - aaaaaaab = 8, - aaaaaaaaa = 9, - aaaaaaaab = 9, - \u0467 = 2, - \u0467\u0467 = 4, - \u0467\u0467a = 5, - \u0467\u0467b = 5, - \u0467\u0467\u0467 = 6, - \u0467\u0467\u0467a = 7, - \u0467\u0467\u0467b = 7, - \u0467\u0467\u0467\u0467 = 8, - \u0467\u0467\u0467\u0467a = 9, - \u0467\u0467\u0467\u0467b = 9, - }; - - // Verify baseline. - Verify(); - - string json = JsonSerializer.Serialize(obj); - - // Verify the length is consistent with a verified value. - Assert.Equal(354, json.Length); - - obj = JsonSerializer.Deserialize(json); - - // Verify round-tripped object. - Verify(); } - - [Theory] - [InlineData(0x1, 'v')] - [InlineData(0x1, '\u0467')] - [InlineData(0x10, 'v')] - [InlineData(0x10, '\u0467')] - [InlineData(0x100, 'v')] - [InlineData(0x100, '\u0467')] - [InlineData(0x1000, 'v')] - [InlineData(0x1000, '\u0467')] - [InlineData(0x10000, 'v')] - [InlineData(0x10000, '\u0467')] - public static void LongPropertyNames(int propertyLength, char ch) - { - // Although the CLR may limit member length to 1023 bytes, the serializer doesn't have a hard limit. - - string val = new string(ch, propertyLength); - string json = @"{""" + val + @""":1}"; - - EmptyClassWithExtensionProperty obj = JsonSerializer.Deserialize(json); - - Assert.True(obj.MyOverflow.ContainsKey(val)); - - var options = new JsonSerializerOptions - { - // Avoid escaping '\u0467'. - Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping - }; - - string jsonRoundTripped = JsonSerializer.Serialize(obj, options); - Assert.Equal(json, jsonRoundTripped); - } - - [Fact] - public static void BadNamingPolicy_ThrowsInvalidOperation() - { - var options = new JsonSerializerOptions { DictionaryKeyPolicy = new NullNamingPolicy() }; - - var inputPrimitive = new Dictionary - { - { "validKey", 1 } - }; - - Assert.Throws(() => JsonSerializer.Serialize(inputPrimitive, options)); - - var inputClass = new Dictionary - { - { "validKey", new OverridePropertyNameDesignTime_TestClass() } - }; - - Assert.Throws(() => JsonSerializer.Serialize(inputClass, options)); - } - } - - public class OverridePropertyNameDesignTime_TestClass - { - [JsonPropertyName("Blah")] - public int myInt { get; set; } - - [JsonPropertyName("BlahObject")] - public object myObject { get; set; } - } - - public class DuplicatePropertyNameDesignTime_TestClass - { - [JsonPropertyName("Blah")] - public int MyInt1 { get; set; } - - [JsonPropertyName("Blah")] - public int MyInt2 { get; set; } - } - - public class EmptyPropertyName_TestClass - { - [JsonPropertyName("")] - public int MyInt1 { get; set; } - } - - public class NullPropertyName_TestClass - { - [JsonPropertyName(null)] - public int MyInt1 { get; set; } - } - - public class IntPropertyNamesDifferentByCaseOnly_TestClass - { - public int myInt { get; set; } - public int MyInt { get; set; } - } - - public class ObjectPropertyNamesDifferentByCaseOnly_TestClass - { - public int myObject { get; set; } - public int MyObject { get; set; } - } - - public class EmptyClassWithExtensionProperty - { - [JsonExtensionData] - public IDictionary MyOverflow { get; set; } - } - - public class ClassWithEmptyPropertyNameAndExtensionProperty - { - [JsonPropertyName("")] - public int MyInt1 { get; set; } - - [JsonExtensionData] - public IDictionary MyOverflow { get; set; } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs index 35d96103569f37..d7e6e92ba90e02 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs @@ -289,7 +289,7 @@ public async Task LargeJsonFile(int bufferSize) [InlineData(1000, false, false)] public async Task VeryLargeJsonFileTest(int payloadSize, bool ignoreNull, bool writeIndented) { - List list = PopulateLargeObject(payloadSize); + List list = JsonTestHelper.PopulateLargeObject(payloadSize); JsonSerializerOptions options = new JsonSerializerOptions { @@ -337,10 +337,10 @@ public async Task DeepNestedJsonFileTest(int depthFactor, bool ignoreNull, bool int length = ListLength * depthFactor; List[] orders = new List[length]; - orders[0] = PopulateLargeObject(1); + orders[0] = JsonTestHelper.PopulateLargeObject(1); for (int i = 1; i < length; i++ ) { - orders[i] = PopulateLargeObject(1); + orders[i] = JsonTestHelper.PopulateLargeObject(1); orders[i - 1][0].RelatedOrder = orders[i]; } @@ -381,10 +381,10 @@ public async Task NestedJsonFileCircularDependencyTest(int depthFactor) int length = ListLength * depthFactor; List[] orders = new List[length]; - orders[0] = PopulateLargeObject(1000); + orders[0] = JsonTestHelper.PopulateLargeObject(1000); for (int i = 1; i < length; i++) { - orders[i] = PopulateLargeObject(1); + orders[i] = JsonTestHelper.PopulateLargeObject(1); orders[i - 1][0].RelatedOrder = orders[i]; } @@ -464,188 +464,6 @@ private static List GenerateListOfSize(int size) } return list; } - - internal static List PopulateLargeObject(int size) - { - List orders = new List(size); - for (int i = 0; i < size; i++) - { - Order order = new Order - { - OrderNumber = i, - Customer = new User - { - UserId = "222ffbbb888kkk", - Name = "John Doe", - Username = "johndoe", - CreatedAt = new DateTime(), - ImageId = string.Empty, - UserType = UserType.Customer, - UpdatedAt = new DateTime(), - TwitterId = string.Empty, - FacebookId = "9988998877662222111", - SubscriptionType = 2, - IsNew = true, - IsEmployee = false - }, - ShippingInfo = new List - { - new ShippingInfo() - { - OrderNumber = i, - Employee = new User - { - UserId = "222ffbbb888" + i, - Name = "Shipping Coordinator", - Username = "coordinator" + i, - CreatedAt = new DateTime(), - ImageId = string.Empty, - UserType = UserType.Employee, - UpdatedAt = new DateTime(), - TwitterId = string.Empty, - SubscriptionType = 0, - IsEmployee = true - }, - CarrierId = "TTT123999MMM", - ShippingType = "Ground", - EstimatedDelivery = new DateTime(), - Tracking = new Uri("http://TestShipCompany.test/track/123" + i), - CarrierName = "TestShipCompany", - HandlingInstruction = "Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats", - CurrentStatus = "Out for delivery", - IsDangerous = false - } - }, - OneTime = true, - Cancelled = false, - IsGift = i % 2 == 0, - IsGPickUp = i % 5 == 0, - ShippingAddress = new Address() - { - City = "Redmond" - }, - PickupAddress = new Address - { - City = "Bellevue" - }, - Coupon = SampleEnumInt64.Max, - UserInteractions = new List - { - new Comment - { - Id = 200 + i, - OrderNumber = i, - Customer = new User - { - UserId = "222ffbbb888kkk", - Name = "John Doe", - Username = "johndoe", - CreatedAt = new DateTime(), - ImageId = string.Empty, - UserType = UserType.Customer, - UpdatedAt = new DateTime(), - TwitterId = "twitterId" + i, - FacebookId = "9988998877662222111", - SubscriptionType = 2, - IsNew = true, - IsEmployee = false - }, - Title = "Green Field", - Message = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to", - Responses = new List() - } - }, - Created = new DateTime(2019, 11, 10), - Confirmed = new DateTime(2019, 11, 11), - ShippingDate = new DateTime(2019, 11, 12), - EstimatedDelivery = new DateTime(2019, 11, 15), - ReviewedBy = new User() - { - UserId = "222ffbbb888" + i, - Name = "Shipping Coordinator", - Username = "coordinator" + i, - CreatedAt = new DateTime(), - ImageId = string.Empty, - UserType = UserType.Employee, - UpdatedAt = new DateTime(), - TwitterId = string.Empty, - SubscriptionType = 0, - IsEmployee = true - } - }; - List products = new List(); - for (int j = 0; j < i % 4; j++) - { - Product product = new Product() - { - ProductId = Guid.NewGuid(), - Name = "Surface Pro", - SKU = "LL123" + j, - Brand = new TestClassWithInitializedProperties(), - ProductCategory = new SimpleTestClassWithNonGenericCollectionWrappers(), - Description = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to", - Created = new DateTime(2000, 10, 12), - Title = "Surface Pro 6 for Business - 512GB", - Price = new Price(), - BestChoice = true, - AverageStars = 4.8f, - Featured = true, - ProductRestrictions = new TestClassWithInitializedProperties(), - SalesInfo = new SimpleTestClassWithGenericCollectionWrappers(), - Origin = SampleEnum.One, - Manufacturer = new BasicCompany(), - Fragile = true, - DetailsUrl = new Uri("http://dotnet.test/link/entries/entry/1"), - NetWeight = 2.7m, - GrossWeight = 3.3m, - Length = i, - Height = i + 1, - Width = i + 2, - FeaturedImage = new FeaturedImage(), - PreviewImage = new PreviewImage(), - KeyWords = new List { "surface", "pro", "laptop" }, - RelatedImages = new List(), - RelatedVideo = new Uri("http://dotnet.test/link/entries/entry/2"), - GuaranteeStartsAt = new DateTime(), - GuaranteeEndsAt = new DateTime(), - IsActive = true, - RelatedProducts = new List() - }; - product.SalesInfo.Initialize(); - List reviews = new List(); - for (int k = 0; k < i % 3; k++) - { - - Review review = new Review - { - Customer = new User - { - UserId = "333344445555", - Name = "Customer" + i + k, - Username = "cust" + i + k, - CreatedAt = new DateTime(), - ImageId = string.Empty, - UserType = UserType.Customer, - SubscriptionType = k - }, - ProductSku = product.SKU, - CustomerName = "Customer" + i + k, - Stars = j + k, - Title = $"Title {i}{j}{k}", - Comment = "", - Images = new List{ new Uri($"http://dotnet.test/link/images/image/{k}"), new Uri($"http://dotnet.test/link/images/image/{j}")}, - ReviewId = i + j +k - }; - reviews.Add(review); - } - product.Reviews = reviews; - products.Add(product); - } - order.Products = products; - orders.Add(order); - } - return orders; - } } public sealed class TestStream : Stream diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnsupportedTypesTests.cs new file mode 100644 index 00000000000000..8de761544db237 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/UnsupportedTypesTests.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Text.Json.Serialization.Tests +{ + public sealed partial class UnsupportedTypesTestsDynamic : UnsupportedTypesTests + { + public UnsupportedTypesTestsDynamic() : base( + JsonSerializerWrapperForString.StringSerializer, + supportsJsonPathOnSerialize: true) + { + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj index 3485690c39a559..475d0b30ee3bfb 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj @@ -40,12 +40,16 @@ + + + + @@ -63,6 +67,7 @@ + @@ -85,7 +90,6 @@ - @@ -152,6 +156,7 @@ + @@ -170,7 +175,6 @@ - @@ -178,6 +182,7 @@ + @@ -212,6 +217,6 @@ - + diff --git a/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj b/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj index 3f57e01ad4d1be..f699d479cc83a9 100644 --- a/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj +++ b/src/libraries/System.Threading.AccessControl/ref/System.Threading.AccessControl.csproj @@ -14,7 +14,7 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Threading.AccessControl/src/CompatibilitySuppressions.xml b/src/libraries/System.Threading.AccessControl/src/CompatibilitySuppressions.xml index e3b9814aa9f0ff..1fabb2d07af7b1 100644 --- a/src/libraries/System.Threading.AccessControl/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Threading.AccessControl/src/CompatibilitySuppressions.xml @@ -1,10 +1,5 @@ - + - - CP0001 - lib/netstandard2.0/System.Threading.AccessControl.dll - lib/net461/System.Threading.AccessControl.dll - PKV006 .NETFramework,Version=v4.6 diff --git a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj index f71a0d7bc6dc68..a2fbcb45dce432 100644 --- a/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj +++ b/src/libraries/System.Threading.AccessControl/src/System.Threading.AccessControl.csproj @@ -62,15 +62,16 @@ System.Security.AccessControl.SemaphoreSecurity + + + - - diff --git a/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/Parallel.ForEachAsync.cs b/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/Parallel.ForEachAsync.cs index ee56e0d1a18d15..3a7d40b7d0489b 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/Parallel.ForEachAsync.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/src/System/Threading/Tasks/Parallel.ForEachAsync.cs @@ -480,18 +480,10 @@ public void Complete() } else { - // Fault with all of the received exceptions, but filter out those due to inner cancellation, - // as they're effectively an implementation detail and stem from the original exception. - Debug.Assert(_exceptions.Count > 0, "If _exceptions was created, it should have also been populated."); - for (int i = 0; i < _exceptions.Count; i++) - { - if (_exceptions[i] is OperationCanceledException oce && oce.CancellationToken == Cancellation.Token) - { - _exceptions[i] = null!; - } - } - _exceptions.RemoveAll(e => e is null); - Debug.Assert(_exceptions.Count > 0, "Since external cancellation wasn't requested, there should have been a non-cancellation exception that triggered internal cancellation."); + // Fail the task with the resulting exceptions. The first should be the initial + // exception that triggered the operation to shut down. The others, if any, may + // include cancellation exceptions from other concurrent operations being canceled + // in response to the primary exception. taskSet = TrySetException(_exceptions); } diff --git a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs index 91747d3828b622..97ac99bc159600 100644 --- a/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs +++ b/src/libraries/System.Threading.Tasks.Parallel/tests/ParallelForEachAsyncTests.cs @@ -618,6 +618,64 @@ static async IAsyncEnumerable Iterate() Assert.True(t.IsCanceled); } + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [InlineData(false)] + [InlineData(true)] + public async Task Cancellation_FaultsForOceForNonCancellation(bool internalToken) + { + static async IAsyncEnumerable Iterate() + { + int counter = 0; + while (true) + { + await Task.Yield(); + yield return counter++; + } + } + + var cts = new CancellationTokenSource(); + + Task t = Parallel.ForEachAsync(Iterate(), new ParallelOptions { CancellationToken = cts.Token }, (item, cancellationToken) => + { + throw new OperationCanceledException(internalToken ? cancellationToken : cts.Token); + }); + + await Assert.ThrowsAnyAsync(() => t); + Assert.True(t.IsFaulted); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [InlineData(0, 4)] + [InlineData(1, 4)] + [InlineData(2, 4)] + [InlineData(3, 4)] + [InlineData(4, 4)] + public async Task Cancellation_InternalCancellationExceptionsArentFilteredOut(int numThrowingNonCanceledOce, int total) + { + var cts = new CancellationTokenSource(); + + var barrier = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + int remainingCount = total; + + Task t = Parallel.ForEachAsync(Enumerable.Range(0, total), new ParallelOptions { CancellationToken = cts.Token, MaxDegreeOfParallelism = total }, async (item, cancellationToken) => + { + // Wait for all operations to be started + if (Interlocked.Decrement(ref remainingCount) == 0) + { + barrier.SetResult(); + } + await barrier.Task; + + throw item < numThrowingNonCanceledOce ? + new OperationCanceledException(cancellationToken) : + throw new FormatException(); + }); + + await Assert.ThrowsAnyAsync(() => t); + Assert.Equal(total, t.Exception.InnerExceptions.Count); + Assert.Equal(numThrowingNonCanceledOce, t.Exception.InnerExceptions.Count(e => e is OperationCanceledException)); + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void Exception_FromGetEnumerator_Sync() { @@ -672,7 +730,6 @@ static IEnumerable Iterate() Task t = Parallel.ForEachAsync(Iterate(), (item, cancellationToken) => default); await Assert.ThrowsAsync(() => t); Assert.True(t.IsFaulted); - Assert.Equal(1, t.Exception.InnerExceptions.Count); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] @@ -694,7 +751,6 @@ static async IAsyncEnumerable Iterate() Task t = Parallel.ForEachAsync(Iterate(), (item, cancellationToken) => default); await Assert.ThrowsAsync(() => t); Assert.True(t.IsFaulted); - Assert.Equal(1, t.Exception.InnerExceptions.Count); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] @@ -771,7 +827,6 @@ public async Task Exception_FromDispose_Sync() Task t = Parallel.ForEachAsync((IEnumerable)new ThrowsExceptionFromDispose(), (item, cancellationToken) => default); await Assert.ThrowsAsync(() => t); Assert.True(t.IsFaulted); - Assert.Equal(1, t.Exception.InnerExceptions.Count); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] @@ -780,7 +835,6 @@ public async Task Exception_FromDispose_Async() Task t = Parallel.ForEachAsync((IAsyncEnumerable)new ThrowsExceptionFromDispose(), (item, cancellationToken) => default); await Assert.ThrowsAsync(() => t); Assert.True(t.IsFaulted); - Assert.Equal(1, t.Exception.InnerExceptions.Count); } [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] diff --git a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs index d90c0685451f3a..d4f156df42bc40 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs @@ -523,6 +523,7 @@ public static void CancellationDoesntResultInEventFiring() TaskScheduler.UnobservedTaskException -= handler; } + [ActiveIssue("https://github.com/dotnet/runtime/issues/57751")] [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPreciseGcSupported))] public static async Task AsyncMethodsDropsStateMachineAndExecutionContextUponCompletion() { diff --git a/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs b/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs index 8374c56056996a..5ba5ec4922ab33 100644 --- a/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs +++ b/src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs @@ -29,6 +29,7 @@ public void SuppressFlow_TaskCapturesContextAccordingly(bool suppressFlow) } } + [ActiveIssue("https://github.com/dotnet/runtime/issues/57331")] [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsPreciseGcSupported))] public static async Task TaskDropsExecutionContextUponCompletion() { diff --git a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs index 2682166b24c512..7aabd01c39f1e2 100644 --- a/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs +++ b/src/libraries/System.Threading/tests/SemaphoreSlimTests.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Threading.Tests @@ -615,5 +617,28 @@ public static void TestConcurrentWaitAndWaitAsync(int syncWaiters, int asyncWait semaphore.Release(totalWaiters / 2); Task.WaitAll(tasks); } + + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] + public void WaitAsync_Timeout_NoUnhandledException() + { + RemoteExecutor.Invoke(async () => + { + Exception error = null; + TaskScheduler.UnobservedTaskException += (s, e) => Volatile.Write(ref error, e.Exception); + + var sem = new SemaphoreSlim(0); + for (int i = 0; i < 2; ++i) + { + await sem.WaitAsync(1); + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + if (Volatile.Read(ref error) is Exception e) + { + throw e; + } + }).Dispose(); + } } } diff --git a/src/libraries/System.Windows.Extensions/src/CompatibilitySuppressions.xml b/src/libraries/System.Windows.Extensions/src/CompatibilitySuppressions.xml index c6379c3e4ac3ca..7dc1f27798f23a 100644 --- a/src/libraries/System.Windows.Extensions/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Windows.Extensions/src/CompatibilitySuppressions.xml @@ -1,12 +1,12 @@ - + PKV006 - .NETCoreapp,Version=v3.0 + .NETCoreApp,Version=v3.0 PKV007 - .NETCoreapp,Version=v3.0-win + .NETCoreApp,Version=v3.0-win - \ No newline at end of file + diff --git a/src/libraries/externals.csproj b/src/libraries/externals.csproj index 6ef3ddc0f19015..969ed9603a2cda 100644 --- a/src/libraries/externals.csproj +++ b/src/libraries/externals.csproj @@ -9,6 +9,7 @@ true false true + true @@ -16,7 +17,7 @@ Version="$(MicrosoftDiaSymReaderNativeVersion)" /> - + - + + + + + + + + + + $(AppleTestTarget) - + false @@ -415,10 +415,10 @@ - + $(_BuildWasmAppsPayloadArchive) - set "HELIX_XUNIT_ARGS=-class Wasm.Build.Tests.%(Identity)" - export "HELIX_XUNIT_ARGS=-class Wasm.Build.Tests.%(Identity)" + set "HELIX_XUNIT_ARGS=-class %(Identity)" + export "HELIX_XUNIT_ARGS=-class %(Identity)" $(HelixCommand) $(_workItemTimeout) diff --git a/src/libraries/shims/ApiCompat.proj b/src/libraries/shims/ApiCompat.proj index 4ade3e1c90441e..d28a09f2d21372 100644 --- a/src/libraries/shims/ApiCompat.proj +++ b/src/libraries/shims/ApiCompat.proj @@ -3,9 +3,9 @@ false - net5.0 + net6.0 microsoft.netcore.app.ref - 5.0.0 + 6.0.0 diff --git a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt index 69f17447741d89..740cf4995ce1bb 100644 --- a/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt +++ b/src/libraries/shims/ApiCompatBaseline.PreviousNetCoreApp.txt @@ -68,8 +68,8 @@ CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerAttribute' on ' CannotRemoveAttribute : Attribute 'System.ComponentModel.DesignerAttribute' exists on 'System.ComponentModel.MarshalByValueComponent' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.ComponentModel.TypeDescriptionProvider.CreateInstance(System.IServiceProvider, System.Type, System.Type[], System.Object[])' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.ComponentModel.TypeDescriptor.CreateInstance(System.IServiceProvider, System.Type, System.Type[], System.Object[])' in the contract but not the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("windows")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("windows")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.AllowNullAttribute' exists on parameter 'value' on member 'System.Net.Cookie.Name.set(System.String)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Net.HttpListener.ExtendedProtectionPolicy.set(System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Net.HttpListenerResponse.Abort()' in the contract but not the implementation. @@ -97,8 +97,8 @@ CannotChangeAttribute : Attribute 'System.ComponentModel.DesignerAttribute' on ' CannotRemoveAttribute : Attribute 'System.ComponentModel.DesignerAttribute' exists on 'System.ComponentModel.MarshalByValueComponent' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.ComponentModel.TypeDescriptionProvider.CreateInstance(System.IServiceProvider, System.Type, System.Type[], System.Object[])' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.ComponentModel.TypeDescriptor.CreateInstance(System.IServiceProvider, System.Type, System.Type[], System.Object[])' in the contract but not the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("windows")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("windows")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.AllowNullAttribute' exists on parameter 'value' on member 'System.Net.Cookie.Name.set(System.String)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Net.HttpListener.ExtendedProtectionPolicy.set(System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy)' in the contract but not the implementation. CannotRemoveAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' exists on 'System.Net.HttpListenerResponse.Abort()' in the contract but not the implementation. @@ -130,8 +130,8 @@ CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatfo CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Console.WindowHeight.get()' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("android")]' in the implementation. CannotChangeAttribute : Attribute 'System.Runtime.Versioning.UnsupportedOSPlatformAttribute' on 'System.Console.WindowWidth.get()' changed from '[UnsupportedOSPlatformAttribute("browser")]' in the contract to '[UnsupportedOSPlatformAttribute("android")]' in the implementation. Compat issues with assembly System.Diagnostics.Process: -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("windows")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. -CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("windows")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MaxWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. +CannotChangeAttribute : Attribute 'System.Runtime.Versioning.SupportedOSPlatformAttribute' on 'System.Diagnostics.Process.MinWorkingSet.set(System.IntPtr)' changed from '[SupportedOSPlatformAttribute("freebsd")]' in the contract to '[SupportedOSPlatformAttribute("freebsd")]' in the implementation. Compat issues with assembly System.Net: CannotRemoveAttribute : Attribute 'System.Diagnostics.CodeAnalysis.AllowNullAttribute' exists on parameter 'value' on member 'System.Net.Cookie.Name.set(System.String)' in the contract but not the implementation. Compat issues with assembly System.Net.HttpListener: diff --git a/src/libraries/src.proj b/src/libraries/src.proj index 8b38ce5b449390..4e0fea066f7507 100644 --- a/src/libraries/src.proj +++ b/src/libraries/src.proj @@ -14,6 +14,11 @@ Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" Condition="'$(BuildAllConfigurations)' != 'true'" /> + + <_allSrc Remove="Microsoft.Extensions.DependencyInjection.Specification.Tests\src\Microsoft.Extensions.DependencyInjection.Specification.Tests.csproj; + Microsoft.Windows.Compatibility\src\Microsoft.Windows.Compatibility.csproj" + Condition="'$(DotNetBuildFromSource)' == 'true'" /> + - + + + + + + + + @@ -81,7 +88,6 @@ - @@ -120,6 +126,7 @@ + @@ -139,77 +146,52 @@ + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - + + - - - - - - - - - - - - - - + + + @@ -230,6 +212,17 @@ + + + + + + + + + + + @@ -278,6 +271,10 @@ + + + + @@ -307,8 +304,9 @@ - + + + + + + + + + + + + $(TestArchiveRoot)tests/ + $(TestArchiveRoot)runonly/ + + $(TestArchiveNormalTestsRoot)$(OSPlatformConfig)/ + $(TestArchiveFunctionalTestsRoot)$(OSPlatformConfig)/ + + $(AppBundleRoot)/tests/ + $(AppBundleRoot)/runonly/ + + $(AppBundleRoot)/tests.all/ + $(AppBundleRoot)/runonly.all/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_NuGetConfigForWorkloadInstall>$(ArtifactsBinDir)workload-nuget.config + + @@ -6,7 +10,7 @@ - + @@ -16,6 +20,7 @@ + @@ -23,15 +28,22 @@ - + - <_DotNetInstallScriptPath Condition="!$([MSBuild]::IsOSPlatform('windows'))">$(DOTNET_INSTALL_DIR)/dotnet-install.sh - <_DotNetInstallScriptPath Condition=" $([MSBuild]::IsOSPlatform('windows'))">$(RepoRoot).dotnet\dotnet-install.ps1 - + <_DotNetInstallScriptName Condition="!$([MSBuild]::IsOSPlatform('windows'))">dotnet-install.sh + <_DotNetInstallScriptName Condition=" $([MSBuild]::IsOSPlatform('windows'))">dotnet-install.ps1 + + <_DotNetInstallScriptPath>$(ArtifactsObjDir)$(_DotNetInstallScriptName) + + + @@ -60,7 +72,7 @@ - <_NuGetSourceForWorkloads Include="dotnet6" Value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json" /> <_BuiltNuGets Include="$(LibrariesShippingPackagesDir)\*.nupkg" /> + <_PackageVersion Condition="'$(StabilizePackageVersion)' == 'true'">$(ProductVersion) + <_PackageVersion Condition="'$(_PackageVersion)' == ''">$(PackageVersion) - <_AOTCrossNuGetPath>$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.AOT.$(NETCoreSdkRuntimeIdentifier).Cross.$(RuntimeIdentifier).$(PackageVersion).nupkg + <_AOTCrossNuGetPath>$(LibrariesShippingPackagesDir)Microsoft.NETCore.App.Runtime.AOT.$(NETCoreSdkRuntimeIdentifier).Cross.$(RuntimeIdentifier).$(_PackageVersion).nupkg @@ -112,11 +124,59 @@ + + + + + + + + + + + + + + + + + + + + + + + $(RepoRoot)NuGet.config + + @(RestoreTestSource -> '<add key="%(Key)" value="%(Identity)" />', '%0A ') + + $([System.IO.File]::ReadAllText('$(TemplateNuGetConfigFile)').Replace( + '<!-- TEST_RESTORE_SOURCES_INSERTION_LINE -->', + '$(RestoreTestSourceConfigLines)')) + + + $([System.Text.RegularExpressions.Regex]::Replace( + '$(TestRestoreNuGetConfigContent)', + '<add key=".+" value="https://pkgs.dev.azure.com/dnceng/internal/.+" />', + '')) + + + + diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt index bd636b92e284ea..49a73b1b709c37 100644 --- a/src/mono/CMakeLists.txt +++ b/src/mono/CMakeLists.txt @@ -205,6 +205,9 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(HOST_LINUX 1) add_definitions(-D_GNU_SOURCE -D_REENTRANT) add_definitions(-D_THREAD_SAFE) + # Enable the "full RELRO" options (RELRO & BIND_NOW) at link time + add_link_options(-Wl,-z,relro) + add_link_options(-Wl,-z,now) elseif(CMAKE_SYSTEM_NAME STREQUAL "Android") set(HOST_LINUX 1) add_definitions(-D_GNU_SOURCE -D_REENTRANT) @@ -244,12 +247,18 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") add_compile_options(/W3) # set warning level 3 add_compile_options(/EHsc) # set exception handling behavior add_compile_options(/FC) # use full pathnames in diagnostics + add_link_options(/STACK:0x800000) # set stack size to 8MB (default is 1MB) if(CMAKE_BUILD_TYPE STREQUAL "Release") - add_compile_options(/Oi) # enable intrinsics - add_compile_options(/GF) # enable string pooling - add_compile_options(/Zi) # enable debugging information - add_compile_options(/GL) # whole program optimization - add_link_options(/LTCG) # link-time code generation + add_compile_options(/Oi) # enable intrinsics + add_compile_options(/GF) # enable string pooling + add_compile_options(/Zi) # enable debugging information + add_compile_options(/GL) # whole program optimization + add_link_options(/LTCG) # link-time code generation + add_link_options(/DEBUG) # enable debugging information + add_link_options(/OPT:REF) # optimize: remove unreferenced functions & data + add_link_options(/OPT:ICF) # optimize: enable COMDAT folding + # the combination of /Zi compiler flag and /DEBUG /OPT:REF /OPT:ICF + # linker flags is needed to create .pdb output on release builds endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS") set(HOST_SOLARIS 1) @@ -719,11 +728,13 @@ endif() ###################################### # EXTRACT VERSION ###################################### -if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/_version.h") - if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/_version.h") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_version.h" "#undef VER_PRODUCTVERSION_STR\n#define VER_PRODUCTVERSION_STR \"42.42.42.42424\"\n") - else() - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/_version.h" "static char sccsid[] __attribute__((used)) = \"@(#)Version 42.42.42.42424 @Commit: AAA\";\n") + endif() +else() + if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/version.c") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version.c" "static char sccsid[] __attribute__((used)) = \"@(#)Version 42.42.42.42424 @Commit: AAA\";\n") endif() endif() if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows" AND NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/NativeVersion.rc") @@ -745,7 +756,7 @@ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/_version.h" product_version_string_line REGEX "VER_PRODUCTVERSION_STR ") string(REGEX REPLACE ".*VER_PRODUCTVERSION_STR *(.*)" "\\1" product_version_string ${product_version_string_line}) else() - file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/_version.h" product_version_string_line REGEX "sccsid") + file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/version.c" product_version_string_line REGEX "sccsid") string(REGEX REPLACE ".*Version *(.*)\";" "\"\\1\"" product_version_string ${product_version_string_line}) endif() diff --git a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj index 1878cb4ed7c053..cb69737648039a 100644 --- a/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -32,6 +32,7 @@ v4.0.30319 $(ProductVersion) + $(ProductVersion) true $(NoWarn),0419,0649 enable @@ -265,12 +266,24 @@ + + Common\Interop\Unix\System.Native\Interop.GetEnv.cs + + + Common\Interop\Unix\System.Native\Interop.GetEnviron.cs + + + + Common\Interop\OSX\Interop.SearchPath.cs + + Common\Interop\OSX\Interop.SearchPath.iOS.cs + diff --git a/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs index 94cb9eb7feea62..6a61e0ebd53f35 100644 --- a/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Array.Mono.cs @@ -164,6 +164,7 @@ private static void Copy(Array sourceArray, int sourceIndex, Array destinationAr Type src_type = sourceArray.GetType().GetElementType()!; Type dst_type = destinationArray.GetType().GetElementType()!; + Type dst_elem_type = dst_type; bool dst_type_vt = dst_type.IsValueType && Nullable.GetUnderlyingType(dst_type) == null; bool src_is_enum = src_type.IsEnum; @@ -196,12 +197,9 @@ private static void Copy(Array sourceArray, int sourceIndex, Array destinationAr { object srcval = sourceArray.GetValueImpl(source_pos + i); - if (!src_type.IsValueType && dst_is_enum) + if (dst_type_vt && (srcval == null || (src_type == typeof(object) && !dst_elem_type.IsAssignableFrom (srcval.GetType())))) throw new InvalidCastException(SR.InvalidCast_DownCastArrayElement); - if (dst_type_vt && (srcval == null || (src_type == typeof(object) && srcval.GetType() != dst_type))) - throw new InvalidCastException(); - try { destinationArray.SetValueRelaxedImpl(srcval, dest_pos + i); diff --git a/src/mono/System.Private.CoreLib/src/System/Environment.Android.cs b/src/mono/System.Private.CoreLib/src/System/Environment.Android.cs new file mode 100644 index 00000000000000..44c8988532f367 --- /dev/null +++ b/src/mono/System.Private.CoreLib/src/System/Environment.Android.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.IO; +using System.Threading; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Diagnostics; + +namespace System +{ + public static partial class Environment + { + private static Dictionary? s_specialFolders; + + private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option) + { + if (s_specialFolders == null) + { + Interlocked.CompareExchange(ref s_specialFolders, new Dictionary(), null); + } + + string? path; + lock (s_specialFolders) + { + if (!s_specialFolders.TryGetValue(folder, out path)) + { + path = GetSpecialFolder(folder) ?? string.Empty; + s_specialFolders[folder] = path; + } + } + return path; + } + + private static string? GetSpecialFolder(SpecialFolder folder) + { + string? home = null; + try + { + home = PersistedFiles.GetHomeDirectory(); + } + catch (Exception exc) + { + Debug.Fail($"Unable to get home directory: {exc}"); + } + + // Fall back to '/' when we can't determine the home directory. + // This location isn't writable by non-root users which provides some safeguard + // that the application doesn't write data which is meant to be private. + if (string.IsNullOrEmpty(home)) + { + home = "/"; + } + + switch (folder) + { + case SpecialFolder.Personal: + case SpecialFolder.LocalApplicationData: + return home; + + case SpecialFolder.ApplicationData: + return Path.Combine(home, ".config"); + + case SpecialFolder.Desktop: + case SpecialFolder.DesktopDirectory: + return Path.Combine(home, "Desktop"); + + case SpecialFolder.MyMusic: + return Path.Combine(home, "Music"); + + case SpecialFolder.MyPictures: + return Path.Combine(home, "Pictures"); + + case SpecialFolder.Templates: + return Path.Combine(home, "Templates"); + + case SpecialFolder.MyVideos: + return Path.Combine(home, "Videos"); + + case SpecialFolder.CommonTemplates: + return "/usr/share/templates"; + + case SpecialFolder.Fonts: + return Path.Combine(home, ".fonts"); + + case SpecialFolder.UserProfile: + return GetEnvironmentVariable("HOME"); + + case SpecialFolder.CommonApplicationData: + return "/usr/share"; + + default: + return string.Empty; + } + } + } +} diff --git a/src/mono/System.Private.CoreLib/src/System/Environment.Unix.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Environment.Unix.Mono.cs index 1b75ae0abbc2ba..5858d78f4c9727 100644 --- a/src/mono/System.Private.CoreLib/src/System/Environment.Unix.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Environment.Unix.Mono.cs @@ -5,8 +5,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; -using Mono; namespace System { @@ -20,7 +20,7 @@ public partial class Environment if (s_environment == null) { - return InternalGetEnvironmentVariable(variable); + return Marshal.PtrToStringAnsi(Interop.Sys.GetEnv(variable)); } variable = TrimStringOnFirstZero(variable); @@ -31,23 +31,15 @@ public partial class Environment } } - private static string InternalGetEnvironmentVariable(string name) - { - using (SafeStringMarshal handle = RuntimeMarshal.MarshalString(name)) - { - return internalGetEnvironmentVariable_native(handle.Value); - } - } - private static unsafe void SetEnvironmentVariableCore(string variable, string? value) { Debug.Assert(variable != null); EnsureEnvironmentCached(); + variable = TrimStringOnFirstZero(variable); + value = value == null ? null : TrimStringOnFirstZero(value); lock (s_environment!) { - variable = TrimStringOnFirstZero(variable); - value = value == null ? null : TrimStringOnFirstZero(value); if (string.IsNullOrEmpty(value)) { s_environment.Remove(variable); @@ -97,22 +89,75 @@ private static Dictionary GetSystemEnvironmentVariables() { var results = new Dictionary(); - foreach (string name in GetEnvironmentVariableNames()) + IntPtr block = Interop.Sys.GetEnviron(); + if (block != IntPtr.Zero) { - if (name != null) + try + { + IntPtr blockIterator = block; + + // Per man page, environment variables come back as an array of pointers to strings + // Parse each pointer of strings individually + while (ParseEntry(blockIterator, out string? key, out string? value)) + { + if (key != null && value != null) + { + try + { + // Add may throw if the environment block was corrupted leading to duplicate entries. + // We allow such throws and eat them (rather than proactively checking for duplication) + // to provide a non-fatal notification about the corruption. + results.Add(key, value); + } + catch (ArgumentException) { } + } + + // Increment to next environment variable entry + blockIterator += IntPtr.Size; + } + } + finally { - results.Add(name, InternalGetEnvironmentVariable(name)); + Interop.Sys.FreeEnviron(block); } } return results; - } - - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern string internalGetEnvironmentVariable_native(IntPtr variable); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern string[] GetEnvironmentVariableNames(); + // Use a local, unsafe function since we cannot use `yield return` inside of an `unsafe` block + static unsafe bool ParseEntry(IntPtr current, out string? key, out string? value) + { + // Setup + key = null; + value = null; + + // Point to current entry + byte* entry = *(byte**)current; + + // Per man page, "The last pointer in this array has the value NULL" + // Therefore, if entry is null then we're at the end and can bail + if (entry == null) + return false; + + // Parse each byte of the entry until we hit either the separator '=' or '\0'. + // This finds the split point for creating key/value strings below. + // On some old OS, the environment block can be corrupted. + // Some will not have '=', so we need to check for '\0'. + byte* splitpoint = entry; + while (*splitpoint != '=' && *splitpoint != '\0') + splitpoint++; + + // Skip over entries starting with '=' and entries with no value (just a null-terminating char '\0') + if (splitpoint == entry || *splitpoint == '\0') + return true; + + // The key is the bytes from start (0) until our splitpoint + key = new string((sbyte*)entry, 0, checked((int)(splitpoint - entry))); + // The value is the rest of the bytes starting after the splitpoint + value = new string((sbyte*)(splitpoint + 1)); + + return true; + } + } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Environment.iOS.cs b/src/mono/System.Private.CoreLib/src/System/Environment.iOS.cs index 1a95bdc408f1c2..99d5b3305fbcf5 100644 --- a/src/mono/System.Private.CoreLib/src/System/Environment.iOS.cs +++ b/src/mono/System.Private.CoreLib/src/System/Environment.iOS.cs @@ -36,18 +36,14 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio { switch (folder) { - // TODO: fix for tvOS (https://github.com/dotnet/runtime/issues/34007) - // The "normal" NSDocumentDirectory is a read-only directory on tvOS - // and that breaks a lot of assumptions in the runtime and the BCL - case SpecialFolder.Personal: case SpecialFolder.LocalApplicationData: - return Interop.Sys.SearchPath(NSSearchPathDirectory.NSDocumentDirectory); + return CombineDocumentDirectory(string.Empty); case SpecialFolder.ApplicationData: // note: at first glance that looked like a good place to return NSLibraryDirectory // but it would break isolated storage for existing applications - return CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, ".config"); + return CombineDocumentDirectory(".config"); case SpecialFolder.Resources: return Interop.Sys.SearchPath(NSSearchPathDirectory.NSLibraryDirectory); // older (8.2 and previous) would return String.Empty @@ -63,7 +59,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio return Path.Combine(GetFolderPathCore(SpecialFolder.Personal, SpecialFolderOption.None), "Pictures"); case SpecialFolder.Templates: - return CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, "Templates"); + return CombineDocumentDirectory("Templates"); case SpecialFolder.MyVideos: return Path.Combine(GetFolderPathCore(SpecialFolder.Personal, SpecialFolderOption.None), "Videos"); @@ -72,7 +68,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio return "/usr/share/templates"; case SpecialFolder.Fonts: - return CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, ".fonts"); + return CombineDocumentDirectory(".fonts"); case SpecialFolder.Favorites: return CombineSearchPath(NSSearchPathDirectory.NSLibraryDirectory, "Favorites"); @@ -84,7 +80,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio return Interop.Sys.SearchPath(NSSearchPathDirectory.NSCachesDirectory); case SpecialFolder.UserProfile: - return InternalGetEnvironmentVariable("HOME"); + return GetEnvironmentVariable("HOME"); case SpecialFolder.CommonApplicationData: return "/usr/share"; @@ -100,6 +96,24 @@ static string CombineSearchPath(NSSearchPathDirectory searchPath, string subdire Path.Combine(path, subdirectory) : string.Empty; } + + static string CombineDocumentDirectory(string subdirectory) + { +#if TARGET_TVOS + string? path = CombineSearchPath(NSSearchPathDirectory.NSLibraryDirectory, Path.Combine("Caches", "Documents")); + // Special version of CombineSearchPath which creates the path if needed. + // This isn't needed for "real" search paths which always exist, but on tvOS + // the base path is really a subdirectory we define rather than an OS directory. + // In order to not treat Directory.Exists(SpecialFolder.ApplicationData) differently + // on tvOS, guarantee that it exists by creating it here + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + path = Path.Combine(path, subdirectory); +#else + string? path = CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, subdirectory); +#endif + return path; + } } } } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs index 0c1d75229cf95f..919015e8567e39 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.Mono.cs @@ -185,6 +185,7 @@ public sealed partial class AssemblyBuilder : Assembly private CustomAttributeBuilder[]? cattrs; private string? version; private string? culture; + private byte[]? public_key_token; private Module[]? loaded_modules; private uint access; #endregion @@ -221,6 +222,7 @@ private AssemblyBuilder(AssemblyName n, AssemblyBuilderAccess access) { version = v.ToString(); } + public_key_token = n.GetPublicKeyToken(); basic_init(this); @@ -396,7 +398,7 @@ public override bool IsDefined(Type attributeType, bool inherit) => public override object[] GetCustomAttributes(Type attributeType, bool inherit) => CustomAttribute.GetCustomAttributes(this, attributeType, inherit); - public override IList GetCustomAttributesData() => CustomAttributeData.GetCustomAttributes(this); + public override IList GetCustomAttributesData() => CustomAttribute.GetCustomAttributesData(this); } } #endif diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.Mono.cs index 7f26920c5e52d8..a34ea7064705d6 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.Mono.cs @@ -123,7 +123,7 @@ private static bool IsValidType(Type t) // depends on this Enum.GetUnderlyingType(t); } - if (t.IsClass && !(t.IsArray || t == typeof(object) || t == typeof(Type) || t == typeof(string) || t.Assembly.GetName().Name == "mscorlib")) + if (t.IsClass && !(t.IsArray || t == typeof(object) || typeof(Type).IsAssignableFrom(t) || t == typeof(string) || t.Assembly.GetName().Name == "mscorlib")) return false; if (t.IsValueType && !(t.IsPrimitive || t.IsEnum || ((t.Assembly is AssemblyBuilder) && t.Assembly.GetName().Name == "mscorlib"))) return false; @@ -149,7 +149,7 @@ private static bool IsValidValue(Type type, object? value) { if (type.IsValueType && value == null) return false; - if (type.IsArray && type.GetElementType()!.IsValueType) + if (type.IsArray && type.GetElementType()!.IsValueType && value != null) { foreach (object? v in (Array)value!) { diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs index 2c8a240f79b595..1e471e8b26805b 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs @@ -952,7 +952,7 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit) public override IList GetCustomAttributesData() { - return CustomAttributeData.GetCustomAttributes(this); + return CustomAttribute.GetCustomAttributesData(this); } [RequiresUnreferencedCode("Fields might be removed")] diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs index 2ec69c7393648d..f646ccb652f0b3 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.Mono.cs @@ -80,6 +80,7 @@ internal static Assembly[] GetLoadedAssemblies() // We only support looking up load context for runtime assemblies. if (rtAsm != null) { + var _ = Default; // ensure the default ALC is initialized. RuntimeAssembly runtimeAssembly = rtAsm; IntPtr ptrAssemblyLoadContext = GetLoadContextForAssembly(runtimeAssembly); loadContextForAssembly = GetAssemblyLoadContext(ptrAssemblyLoadContext); diff --git a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 2d0a4b925096e4..f6d349d99ba261 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1336,8 +1336,9 @@ public override Type MakeGenericType(Type[] instantiation) for (int iCopy = 0; iCopy < instantiation.Length; iCopy++) instantiationCopy[iCopy] = instantiation[iCopy]; instantiation = instantiationCopy; - - throw new NotImplementedException(); + if (!RuntimeFeature.IsDynamicCodeSupported) + throw new PlatformNotSupportedException(); + return System.Reflection.Emit.TypeBuilderInstantiation.MakeGenericType(this, instantiation); } instantiationRuntimeType[i] = rtInstantiationElem; diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs index 5ad4ea2e23cead..4187cfcb829089 100644 --- a/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Threading/TimerQueue.Browser.Mono.cs @@ -17,7 +17,9 @@ internal partial class TimerQueue { private static List? s_scheduledTimers; private static List? s_scheduledTimersToFire; + private static long s_shortestDueTimeMs = long.MaxValue; + // this means that it's in the s_scheduledTimers collection, not that it's the one which would run on the next TimeoutCallback private bool _isScheduled; private long _scheduledDueTimeMs; @@ -27,24 +29,25 @@ private TimerQueue(int id) [DynamicDependency("TimeoutCallback")] // The id argument is unused in netcore + // This replaces the current pending setTimeout with shorter one [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void SetTimeout(int timeout, int id); // Called by mini-wasm.c:mono_set_timeout_exec private static void TimeoutCallback() { - int shortestWaitDurationMs = PumpTimerQueue(); + // always only have one scheduled at a time + s_shortestDueTimeMs = long.MaxValue; - if (shortestWaitDurationMs != int.MaxValue) - { - SetTimeout((int)shortestWaitDurationMs, 0); - } + long currentTimeMs = TickCount64; + ReplaceNextSetTimeout(PumpTimerQueue(currentTimeMs), currentTimeMs); } + // this is called with shortest of timers scheduled on the particular TimerQueue private bool SetTimer(uint actualDuration) { Debug.Assert((int)actualDuration >= 0); - long dueTimeMs = TickCount64 + (int)actualDuration; + long currentTimeMs = TickCount64; if (!_isScheduled) { s_scheduledTimers ??= new List(Instances.Length); @@ -52,24 +55,65 @@ private bool SetTimer(uint actualDuration) s_scheduledTimers.Add(this); _isScheduled = true; } - _scheduledDueTimeMs = dueTimeMs; - SetTimeout((int)actualDuration, 0); + + _scheduledDueTimeMs = currentTimeMs + (int)actualDuration; + + ReplaceNextSetTimeout(ShortestDueTime(), currentTimeMs); return true; } - private static int PumpTimerQueue() + // shortest time of all TimerQueues + private static void ReplaceNextSetTimeout(long shortestDueTimeMs, long currentTimeMs) { - if (s_scheduledTimersToFire == null) + if (shortestDueTimeMs == int.MaxValue) + { + return; + } + + // this also covers s_shortestDueTimeMs = long.MaxValue when none is scheduled + if (s_shortestDueTimeMs > shortestDueTimeMs) + { + s_shortestDueTimeMs = shortestDueTimeMs; + int shortestWait = Math.Max((int)(shortestDueTimeMs - currentTimeMs), 0); + // this would cancel the previous schedule and create shorter one + // it is expensive call + SetTimeout(shortestWait, 0); + } + } + + private static long ShortestDueTime() + { + if (s_scheduledTimers == null) { return int.MaxValue; } + long shortestDueTimeMs = long.MaxValue; + var timers = s_scheduledTimers!; + for (int i = timers.Count - 1; i >= 0; --i) + { + TimerQueue timer = timers[i]; + if (timer._scheduledDueTimeMs < shortestDueTimeMs) + { + shortestDueTimeMs = timer._scheduledDueTimeMs; + } + } + + return shortestDueTimeMs; + } + + private static long PumpTimerQueue(long currentTimeMs) + { + if (s_scheduledTimersToFire == null) + { + return ShortestDueTime(); + } + List timersToFire = s_scheduledTimersToFire!; List timers; timers = s_scheduledTimers!; - long currentTimeMs = TickCount64; - int shortestWaitDurationMs = int.MaxValue; + long shortestDueTimeMs = int.MaxValue; for (int i = timers.Count - 1; i >= 0; --i) { TimerQueue timer = timers[i]; @@ -88,9 +132,9 @@ private static int PumpTimerQueue() continue; } - if (waitDurationMs < shortestWaitDurationMs) + if (timer._scheduledDueTimeMs < shortestDueTimeMs) { - shortestWaitDurationMs = (int)waitDurationMs; + shortestDueTimeMs = timer._scheduledDueTimeMs; } } @@ -103,7 +147,7 @@ private static int PumpTimerQueue() timersToFire.Clear(); } - return shortestWaitDurationMs; + return shortestDueTimeMs; } } } diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in index 6e6fc568b8b3b1..439c82ad67b70d 100644 --- a/src/mono/cmake/config.h.in +++ b/src/mono/cmake/config.h.in @@ -620,6 +620,9 @@ /* Have getifaddrs */ #cmakedefine HAVE_GETIFADDRS 1 +/* Have struct ifaddrs */ +#cmakedefine HAVE_IFADDRS 1 + /* Have access */ #cmakedefine HAVE_ACCESS 1 diff --git a/src/mono/cmake/configure.cmake b/src/mono/cmake/configure.cmake index b3d3f47c894e0b..d27fc5201202a1 100644 --- a/src/mono/cmake/configure.cmake +++ b/src/mono/cmake/configure.cmake @@ -6,6 +6,7 @@ include(CheckTypeSize) include(CheckStructHasMember) include(CheckSymbolExists) include(CheckCCompilerFlag) +include(CheckCSourceCompiles) # Apple platforms like macOS/iOS allow targeting older operating system versions with a single SDK, # the mere presence of a symbol in the SDK doesn't tell us whether the deployment target really supports it. @@ -79,6 +80,21 @@ ac_check_funcs ( gethrtime read_real_time gethostbyname gethostbyname2 getnameinfo getifaddrs access inet_ntop Qp2getifaddrs) +check_c_source_compiles( + " + #include + int main(void) + { + #if defined(ZLIB_VERNUM) && (ZLIB_VERNUM >= 0x1230) + #else + #error No good zlib found + #endif + return 0; + } + " + HAVE_SYS_ZLIB) + + if(NOT HOST_DARWIN) # getentropy was introduced in macOS 10.12 / iOS 10.0 ac_check_funcs (getentropy) diff --git a/src/mono/cmake/defines-todo.cmake b/src/mono/cmake/defines-todo.cmake index 55c5b6f85bb625..5f48e9d70b4fd3 100644 --- a/src/mono/cmake/defines-todo.cmake +++ b/src/mono/cmake/defines-todo.cmake @@ -25,7 +25,6 @@ #option (NEED_LINK_UNLINK "Define if Unix sockets cannot be created in an anonymous namespace") #option (HAVE_CLASSIC_WINAPI_SUPPORT "Use classic Windows API support") #option (HAVE_UWP_WINAPI_SUPPORT "Don't use UWP Windows API support") -#option (HAVE_SYS_ZLIB "Use OS-provided zlib") #option (MONO_XEN_OPT "Xen-specific behaviour") #option (MONO_SMALL_CONFIG "Reduce runtime requirements (and capabilities)") #option (AC_APPLE_UNIVERSAL_BUILD "Define if building universal (internal helper macro)") diff --git a/src/mono/mono.proj b/src/mono/mono.proj index 9b4d254d42598a..fb98ffc1896906 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -36,6 +36,8 @@ $(LibPrefix)$(MonoLibName)$(StaticLibExt) $(MonoStaticLibFileName) $(MonoSharedLibFileName) + mono-aot-cross$(ExeExt) + mono-aot-cross.pdb $(Configuration) $(Configuration) $([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'tests', 'coreclr', '$(TargetOS).$(Platform).$(CoreClrTestConfig)', 'Tests', 'Core_Root')) @@ -504,6 +506,7 @@ <_Objcopy>objcopy <_Objcopy Condition="'$(Platform)' == 'arm'">arm-linux-$(_LinuxAbi)eabi$(_LinuxFloatAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 'arm64'">aarch64-linux-$(_LinuxAbi)-$(_Objcopy) + <_Objcopy Condition="'$(Platform)' == 's390x'">s390x-linux-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 'x64'">x86_64-linux-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(Platform)' == 'x86'">i686-linux-$(_LinuxAbi)-$(_Objcopy) <_Objcopy Condition="'$(TargetsAndroid)' == 'true'">$(ANDROID_NDK_ROOT)/toolchains/llvm/prebuilt/$(MonoToolchainPrebuiltOS)/bin/$(_Objcopy) @@ -672,6 +675,8 @@ + + @@ -720,13 +725,18 @@ + + _version.h + version.c + + + Properties="NativeVersionFile=$(MonoObjDir)$(NativeVersionFile);RuntimeVersionFile=$(MonoObjDir)runtime_version.h" /> + Properties="NativeVersionFile=$(MonoObjCrossDir)$(NativeVersionFile);RuntimeVersionFile=$(MonoObjCrossDir)runtime_version.h" /> @@ -745,7 +755,8 @@ <_MonoIncludeIcuFiles Condition="'$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsMacCatalyst)' == 'true'">true - <_MonoAotCrossFilePath>$(MonoObjCrossDir)out\bin\mono-sgen$(ExeExt) + <_MonoAotCrossFilePath>$(MonoObjCrossDir)out\bin\$(MonoAotCrossFileName) + <_MonoAotCrossPdbFilePath>$(MonoObjCrossDir)out\bin\$(MonoAotCrossPdbFileName) @@ -774,7 +785,10 @@ $(RuntimeBinDir)%(_MonoRuntimeComponentsSharedFilePath.Filename)%(_MonoRuntimeComponentsSharedFilePath.Extension) <_MonoRuntimeArtifacts Include="$(_MonoAotCrossFilePath)"> - $(RuntimeBinDir)cross\$(PackageRID)\mono-aot-cross$(ExeExt) + $(RuntimeBinDir)cross\$(PackageRID)\$(MonoAotCrossFileName) + + <_MonoRuntimeArtifacts Include="$(_MonoAotCrossPdbFilePath)" Condition="Exists('$(_MonoAotCrossPdbFilePath)')"> + $(RuntimeBinDir)cross\$(PackageRID)\$(MonoAotCrossPdbFileName) <_MonoRuntimeArtifacts Condition="'$(MonoBundleLLVMOptimizer)' == 'true'" Include="$(MonoLLVMDir)\bin\llc$(ExeExt)"> $(RuntimeBinDir)\llc$(ExeExt) diff --git a/src/mono/mono/component/debugger-agent.c b/src/mono/mono/component/debugger-agent.c index 2cff5c0dec1445..35b06bfbd5c143 100644 --- a/src/mono/mono/component/debugger-agent.c +++ b/src/mono/mono/component/debugger-agent.c @@ -357,7 +357,9 @@ static int objref_id = 0; static int event_request_id = 0; +#ifndef TARGET_WASM static int frame_id = 0; +#endif static GPtrArray *event_requests; @@ -3026,7 +3028,7 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls, gboolean f { ComputeFramesUserData user_data; GSList *tmp; - int i, findex, new_frame_count; + int findex, new_frame_count; StackFrame **new_frames, *f; MonoUnwindOptions opts = (MonoUnwindOptions)(MONO_UNWIND_DEFAULT | MONO_UNWIND_REG_LOCATIONS); @@ -3085,6 +3087,8 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls, gboolean f for (tmp = user_data.frames; tmp; tmp = tmp->next) { f = (StackFrame *)tmp->data; +#ifndef TARGET_WASM + int i; /* * Reuse the id for already existing stack frames, so invokes don't invalidate * the still valid stack frames. @@ -3098,7 +3102,9 @@ compute_frame_info (MonoInternalThread *thread, DebuggerTlsData *tls, gboolean f if (i >= tls->frame_count) f->id = mono_atomic_inc_i32 (&frame_id); - +#else //keep the same behavior that we have for wasm before start using debugger-agent + f->id = findex+1; +#endif new_frames [findex ++] = f; } @@ -5551,7 +5557,8 @@ decode_value_internal (MonoType *t, int type, MonoDomain *domain, guint8 *addr, */ buf2 = buf; is_enum = decode_byte (buf, &buf, limit); - decode_byte (buf, &buf, limit); //ignore is boxed + if (CHECK_PROTOCOL_VERSION(2, 61)) + decode_byte (buf, &buf, limit); //ignore is boxed klass = decode_typeid (buf, &buf, limit, &d, &err); if (err != ERR_NONE) return err; @@ -8572,7 +8579,7 @@ method_commands_internal (int command, MonoMethod *method, MonoDomain *domain, g return ERR_INVALID_ARGUMENT; } - locals = mono_debug_lookup_locals (method, FALSE); + locals = mono_debug_lookup_locals (method); if (!locals) { if (CHECK_PROTOCOL_VERSION (2, 43)) { /* Scopes */ @@ -9289,13 +9296,14 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) pos = - pos - 1; cmd_stack_frame_get_parameter (frame, sig, pos, buf, jit); } else { - MonoDebugLocalsInfo *locals; - - locals = mono_debug_lookup_locals (frame->de.method, TRUE); - if (locals) { - g_assert (pos < locals->num_locals); - pos = locals->locals [pos].index; - mono_debug_free_locals (locals); + if (!CHECK_PROTOCOL_VERSION (2, 59)) { //from newer protocol versions it's sent the pdb index + MonoDebugLocalsInfo *locals; + locals = mono_debug_lookup_locals (frame->de.method); + if (locals) { + g_assert (pos < locals->num_locals); + pos = locals->locals [pos].index; + mono_debug_free_locals (locals); + } } PRINT_DEBUG_MSG (4, "[dbg] send local %d.\n", pos); @@ -9343,13 +9351,14 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf) var = &jit->params [pos]; is_arg = TRUE; } else { - MonoDebugLocalsInfo *locals; - - locals = mono_debug_lookup_locals (frame->de.method, TRUE); - if (locals) { - g_assert (pos < locals->num_locals); - pos = locals->locals [pos].index; - mono_debug_free_locals (locals); + if (!CHECK_PROTOCOL_VERSION (2, 59)) { //from newer protocol versions it's sent the pdb index + MonoDebugLocalsInfo *locals; + locals = mono_debug_lookup_locals (frame->de.method); + if (locals) { + g_assert (pos < locals->num_locals); + pos = locals->locals [pos].index; + mono_debug_free_locals (locals); + } } g_assert (pos >= 0 && pos < jit->num_locals); diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c index 80374aeef906bc..d43cca86b251a6 100644 --- a/src/mono/mono/component/hot_reload.c +++ b/src/mono/mono/component/hot_reload.c @@ -793,6 +793,13 @@ hot_reload_effective_table_slow (const MonoTableInfo **t, int *idx) if (G_LIKELY (*idx < table_info_get_rows (*t) && !any_modified)) return; + /* FIXME: when adding methods this won't work anymore. We will need to update the delta + * images' suppressed columns (see the Note in pass2 about + * CMiniMdRW::m_SuppressedDeltaColumns) with the baseline values. */ + /* The only column from the updates that matters the RVA, which is looked up elsewhere. */ + if (tbl_index == MONO_TABLE_METHOD) + return; + GList *list = info->delta_image; MonoImage *dmeta; int ridx; @@ -1272,6 +1279,29 @@ apply_enclog_pass2 (MonoImage *image_base, BaselineInfo *base_info, uint32_t gen MonoTableInfo *table_enclog = &image_dmeta->tables [MONO_TABLE_ENCLOG]; int rows = table_info_get_rows (table_enclog); + /* NOTE: Suppressed colums + * + * Certain column values in some tables in the deltas are not meant to be applied over the + * previous generation. See CMiniMdRW::m_SuppressedDeltaColumns in CoreCLR. For example the + * MONO_METHOD_PARAMLIST column in MONO_TABLE_METHOD is always 0 in an update - for modified + * rows the previous value must be carried over. For added rows, it is supposed to be + * initialized to the end of the param table and updated with the "Param create" func code + * in subsequent EnCLog records. + * + * For mono's immutable model (where we don't change the baseline image data), we will need + * to mutate the delta image tables to incorporate the suppressed column values from the + * previous generation. + * + * For Baseline capabilities, the only suppressed column is MONO_METHOD_PARAMLIST - which we + * can ignore because we don't do anything with param updates and the only column we care + * about is MONO_METHOD_RVA which gets special case treatment with set_update_method(). + * + * But when we implement additional capabilities (for example UpdateParameters), we will + * need to start mutating the delta image tables to pick up the suppressed column values. + * Fortunately whether we get the delta from the debugger or from the runtime API, we always + * have it in writable memory (and not mmap-ed pages), so we can rewrite the table values. + */ + gboolean assemblyref_updated = FALSE; for (int i = 0; i < rows ; ++i) { guint32 cols [MONO_ENCLOG_SIZE]; diff --git a/src/mono/mono/component/mini-wasm-debugger.c b/src/mono/mono/component/mini-wasm-debugger.c index f70738d7cb0c15..3c385102979e66 100644 --- a/src/mono/mono/component/mini-wasm-debugger.c +++ b/src/mono/mono/component/mini-wasm-debugger.c @@ -370,6 +370,12 @@ mono_wasm_set_is_debugger_attached (gboolean is_attached) EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, int command, guint8* data, unsigned int size, int valtype, char* newvalue) { + if (!debugger_enabled) { + EM_ASM ({ + MONO.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); + }, 0, id, 0, 0); + return TRUE; + } MdbgProtBuffer bufWithParms; buffer_init (&bufWithParms, 128); m_dbgprot_buffer_add_data (&bufWithParms, data, size); @@ -387,6 +393,12 @@ mono_wasm_send_dbg_command_with_parms (int id, MdbgProtCommandSet command_set, i EMSCRIPTEN_KEEPALIVE gboolean mono_wasm_send_dbg_command (int id, MdbgProtCommandSet command_set, int command, guint8* data, unsigned int size) { + if (!debugger_enabled) { + EM_ASM ({ + MONO.mono_wasm_add_dbg_command_received ($0, $1, $2, $3); + }, 0, id, 0, 0); + return TRUE; + } ss_calculate_framecount (NULL, NULL, TRUE, NULL, NULL); MdbgProtBuffer buf; buffer_init (&buf, 128); diff --git a/src/mono/mono/eglib/gfile-posix.c b/src/mono/mono/eglib/gfile-posix.c index 5bda34cdfc8291..f46f8098f6bcf8 100644 --- a/src/mono/mono/eglib/gfile-posix.c +++ b/src/mono/mono/eglib/gfile-posix.c @@ -161,26 +161,3 @@ g_file_open_tmp (const gchar *tmpl, gchar **name_used, GError **gerror) } return fd; } - -gchar * -g_get_current_dir (void) -{ - int s = 32; - char *buffer = NULL, *r; - gboolean fail; - - do { - buffer = g_realloc (buffer, s); - r = getcwd (buffer, s); - fail = (r == NULL && errno == ERANGE); - if (fail) { - s <<= 1; - } - } while (fail); - - /* On amd64 sometimes the bottom 32-bits of r == the bottom 32-bits of buffer - * but the top 32-bits of r have overflown to 0xffffffff (seriously, getcwd - * so we return the buffer here since it has a pointer to the valid string - */ - return buffer; -} diff --git a/src/mono/mono/eglib/gmisc-unix.c b/src/mono/mono/eglib/gmisc-unix.c index 2a3afc002596ae..2630d515fda5f8 100644 --- a/src/mono/mono/eglib/gmisc-unix.c +++ b/src/mono/mono/eglib/gmisc-unix.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -201,3 +202,25 @@ g_get_tmp_dir (void) return tmp_dir; } +gchar * +g_get_current_dir (void) +{ + int s = 32; + char *buffer = NULL, *r; + gboolean fail; + + do { + buffer = g_realloc (buffer, s); + r = getcwd (buffer, s); + fail = (r == NULL && errno == ERANGE); + if (fail) { + s <<= 1; + } + } while (fail); + + /* On amd64 sometimes the bottom 32-bits of r == the bottom 32-bits of buffer + * but the top 32-bits of r have overflown to 0xffffffff (seriously, getcwd + * so we return the buffer here since it has a pointer to the valid string + */ + return buffer; +} diff --git a/src/mono/mono/eglib/gmisc-win32.c b/src/mono/mono/eglib/gmisc-win32.c index f5589cb63d5320..82860a575ed12d 100644 --- a/src/mono/mono/eglib/gmisc-win32.c +++ b/src/mono/mono/eglib/gmisc-win32.c @@ -232,3 +232,35 @@ g_get_tmp_dir (void) } return tmp_dir; } + +gchar * +g_get_current_dir (void) +{ + gunichar2 *buffer = NULL; + gchar* val = NULL; + gint32 retval, buffer_size = MAX_PATH; + + buffer = g_new (gunichar2, buffer_size); + retval = GetCurrentDirectoryW (buffer_size, buffer); + + if (retval != 0) { + // the size might be larger than MAX_PATH + // https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd + if (retval > buffer_size) { + buffer_size = retval; + buffer = g_realloc (buffer, buffer_size*sizeof(gunichar2)); + retval = GetCurrentDirectoryW (buffer_size, buffer); + } + + val = u16to8 (buffer); + } else { + if (GetLastError () != ERROR_ENVVAR_NOT_FOUND) { + val = g_malloc (1); + *val = 0; + } + } + + g_free (buffer); + + return val; +} diff --git a/src/mono/mono/eventpipe/ds-rt-mono.h b/src/mono/mono/eventpipe/ds-rt-mono.h index 1785d6e51037c5..d3ed4f02b1b229 100644 --- a/src/mono/mono/eventpipe/ds-rt-mono.h +++ b/src/mono/mono/eventpipe/ds-rt-mono.h @@ -172,7 +172,7 @@ ds_rt_config_value_get_default_port_suspend (void) static inline ds_ipc_result_t -ds_rt_generate_core_dump (DiagnosticsGenerateCoreDumpCommandPayload *payload) +ds_rt_generate_core_dump (DiagnosticsDumpCommandId commandId, DiagnosticsGenerateCoreDumpCommandPayload *payload) { // TODO: Implement. return DS_IPC_E_NOTSUPPORTED; diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index acdaf8f1a5078d..fba1368444c6da 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -2553,6 +2553,16 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads ( // as second, re-classify current callstack to be executing managed code. data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED; } + if (data->stack_walk_data.top_frame && ep_stack_contents_get_length (&data->stack_contents) == 0) { + // If no managed frames (including helper frames) are located on stack, mark sample as beginning in external code. + // This can happen on attached embedding threads returning to native code between runtime invokes. + // Make sure sample is still written into EventPipe for all attached threads even if they are currently not having + // any managed frames on stack. Prevents some tools applying thread time heuristics to prolong duration of last sample + // when embedding thread returns to native code. It also opens ability to visualize number of samples in unmanaged code + // on attached threads when executing outside of runtime. If tooling is not interested in these sample events, they are easy + // to identify and filter out. + data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL; + } sampled_thread_count++; } @@ -2570,7 +2580,7 @@ ep_rt_mono_sample_profiler_write_sampling_event_for_threads ( THREAD_INFO_TYPE adapter = { { 0 } }; for (uint32_t i = 0; i < sampled_thread_count; ++i) { EventPipeSampleProfileStackWalkData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileStackWalkData, i); - if (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length(&data->stack_contents) > 0) { + if ((data->stack_walk_data.top_frame && data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL) || (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length (&data->stack_contents) > 0)) { // Check if we have an async frame, if so we will need to make sure all frames are registered in regular jit info table. // TODO: An async frame can contain wrapper methods (no way to check during stackwalk), we could skip writing profile event // for this specific stackwalk or we could cleanup stack_frames before writing profile event. @@ -2943,6 +2953,8 @@ get_module_event_data ( module_data->module_flags |= MODULE_FLAGS_NATIVE_MODULE; module_data->module_il_path = image && image->filename ? image->filename : ""; + module_data->module_il_pdb_path = ""; + module_data->module_il_pdb_age = 0; if (image && image->image_info) { MonoPEDirEntry *debug_dir_entry = (MonoPEDirEntry *)&image->image_info->cli_header.datadir.pe_debug; @@ -2984,6 +2996,7 @@ ep_rt_mono_write_event_module_load (MonoImage *image) if (image) { ModuleEventData module_data; + memset (&module_data, 0, sizeof (module_data)); if (get_module_event_data (image, &module_data)) { FireEtwModuleLoad_V2 ( module_data.module_id, @@ -3027,6 +3040,7 @@ ep_rt_mono_write_event_module_unload (MonoImage *image) if (image) { ModuleEventData module_data; + memset (&module_data, 0, sizeof (module_data)); if (get_module_event_data (image, &module_data)) { FireEtwModuleUnload_V2 ( module_data.module_id, @@ -3085,6 +3099,7 @@ ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly) if (assembly) { AssemblyEventData assembly_data; + memset (&assembly_data, 0, sizeof (assembly_data)); if (get_assembly_event_data (assembly, &assembly_data)) { FireEtwAssemblyLoad_V1 ( assembly_data.assembly_id, @@ -3111,6 +3126,7 @@ ep_rt_mono_write_event_assembly_unload (MonoAssembly *assembly) if (assembly) { AssemblyEventData assembly_data; + memset (&assembly_data, 0, sizeof (assembly_data)); if (get_assembly_event_data (assembly, &assembly_data)) { FireEtwAssemblyUnload_V1 ( assembly_data.assembly_id, @@ -5463,6 +5479,7 @@ mono_profiler_module_loaded ( if (image) { ModuleEventData module_data; + memset (&module_data, 0, sizeof (module_data)); if (get_module_event_data (image, &module_data)) module_path = (const ep_char8_t *)module_data.module_il_path; module_guid = (const ep_char8_t *)mono_image_get_guid (image); @@ -5514,6 +5531,7 @@ mono_profiler_module_unloaded ( if (image) { ModuleEventData module_data; + memset (&module_data, 0, sizeof (module_data)); if (get_module_event_data (image, &module_data)) module_path = (const ep_char8_t *)module_data.module_il_path; module_guid = (const ep_char8_t *)mono_image_get_guid (image); diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h index b42aa108f7c29a..3caaa0174c06fe 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-mono.h @@ -602,7 +602,11 @@ inline size_t ep_rt_atomic_compare_exchange_size_t (volatile size_t *target, size_t expected, size_t value) { +#if SIZEOF_SIZE_T == 8 + return (size_t)(mono_atomic_cas_i64((volatile gint64*)(target), (gint64)(value), (gint64)(expected))); +#else return (size_t)(mono_atomic_cas_i32 ((volatile gint32 *)(target), (gint32)(value), (gint32)(expected))); +#endif } /* @@ -1855,7 +1859,15 @@ inline const ep_char8_t * ep_rt_entrypoint_assembly_name_get_utf8 (void) { - return (const ep_char8_t *)m_image_get_assembly_name (mono_assembly_get_main ()->image); + MonoAssembly *main_assembly = mono_assembly_get_main (); + if (!main_assembly || !main_assembly->image) + return ""; + + const char *assembly_name = m_image_get_assembly_name (main_assembly->image); + if (!assembly_name) + return ""; + + return (const ep_char8_t*)assembly_name; } static diff --git a/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c b/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c index b60af234fe136b..32acf62243719a 100644 --- a/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c +++ b/src/mono/mono/eventpipe/test/ep-provider-callback-dataqueue-tests.c @@ -46,23 +46,26 @@ test_provider_callback_data_queue (void) EventPipeProviderCallbackDataQueue callback_data_queue; EventPipeProviderCallbackDataQueue *provider_callback_data_queue = ep_provider_callback_data_queue_init (&callback_data_queue); - EventPipeProviderCallbackData enqueue_callback_data; - EventPipeProviderCallbackData *provider_enqueue_callback_data = ep_provider_callback_data_init ( - &enqueue_callback_data, - "", - provider_callback, - NULL, - 1, - EP_EVENT_LEVEL_LOGALWAYS, - true); - - for (uint32_t i = 0; i < 1000; ++i) + for (uint32_t i = 0; i < 1000; ++i) { + EventPipeProviderCallbackData enqueue_callback_data; + EventPipeProviderCallbackData *provider_enqueue_callback_data = ep_provider_callback_data_init ( + &enqueue_callback_data, + "", + provider_callback, + NULL, + 1, + EP_EVENT_LEVEL_LOGALWAYS, + true); ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, provider_enqueue_callback_data); + ep_provider_callback_data_fini (provider_enqueue_callback_data); + } EventPipeProviderCallbackData dequeue_callback_data; uint32_t deque_counter = 0; - while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &dequeue_callback_data)) + while (ep_provider_callback_data_queue_try_dequeue(provider_callback_data_queue, &dequeue_callback_data)) { deque_counter++; + ep_provider_callback_data_fini (&dequeue_callback_data); + } if (deque_counter != 1000) { result = FAILED ("Unexpected number of provider callback invokes"); diff --git a/src/mono/mono/eventpipe/test/ep-tests.c b/src/mono/mono/eventpipe/test/ep-tests.c index 5ff65d1497a2c2..e9e30c39833215 100644 --- a/src/mono/mono/eventpipe/test/ep-tests.c +++ b/src/mono/mono/eventpipe/test/ep-tests.c @@ -620,7 +620,7 @@ test_create_delete_provider_with_callback (void) EventPipeProvider *test_provider = NULL; EventPipeProviderConfiguration provider_config; - EventPipeProviderConfiguration *current_provider_config =ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOGALWAYS, ""); + EventPipeProviderConfiguration *current_provider_config = ep_provider_config_init (&provider_config, TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOGALWAYS, ""); ep_raise_error_if_nok (current_provider_config != NULL); test_location = 1; diff --git a/src/mono/mono/metadata/custom-attrs.c b/src/mono/mono/metadata/custom-attrs.c index 48571da6a085ea..29c64c48f3fafc 100644 --- a/src/mono/mono/metadata/custom-attrs.c +++ b/src/mono/mono/metadata/custom-attrs.c @@ -397,7 +397,11 @@ MONO_RESTORE_WARNING // to decode some attributes in assemblies that Windows .NET Framework // and CoreCLR both manage to decode. // See https://simonsapin.github.io/wtf-8/ for a description of wtf-8. - *out_obj = (MonoObject*)mono_string_new_wtf8_len_checked (p, slen, error); + // Always use string.Empty for empty strings + if (slen == 0) + *out_obj = (MonoObject*)mono_string_empty_internal (mono_domain_get ()); + else + *out_obj = (MonoObject*)mono_string_new_wtf8_len_checked (p, slen, error); return NULL; } case MONO_TYPE_CLASS: { diff --git a/src/mono/mono/metadata/icall-def-netcore.h b/src/mono/mono/metadata/icall-def-netcore.h index 8e026693a109ee..02dfa0ed3cbe0e 100644 --- a/src/mono/mono/metadata/icall-def-netcore.h +++ b/src/mono/mono/metadata/icall-def-netcore.h @@ -98,12 +98,10 @@ ICALL_TYPE(ENV, "System.Environment", ENV_1) NOHANDLES(ICALL(ENV_1, "Exit", ves_icall_System_Environment_Exit)) HANDLES(ENV_1a, "FailFast", ves_icall_System_Environment_FailFast, void, 3, (MonoString, MonoException, MonoString)) HANDLES(ENV_2, "GetCommandLineArgs", ves_icall_System_Environment_GetCommandLineArgs, MonoArray, 0, ()) -HANDLES(ENV_3, "GetEnvironmentVariableNames", ves_icall_System_Environment_GetEnvironmentVariableNames, MonoArray, 0, ()) NOHANDLES(ICALL(ENV_4, "GetProcessorCount", ves_icall_System_Environment_get_ProcessorCount)) NOHANDLES(ICALL(ENV_9, "get_ExitCode", mono_environment_exitcode_get)) NOHANDLES(ICALL(ENV_15, "get_TickCount", ves_icall_System_Environment_get_TickCount)) NOHANDLES(ICALL(ENV_15a, "get_TickCount64", ves_icall_System_Environment_get_TickCount64)) -HANDLES(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Environment_GetEnvironmentVariable_native, MonoString, 1, (const_char_ptr)) NOHANDLES(ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set)) ICALL_TYPE(GC, "System.GC", GC_13) diff --git a/src/mono/mono/metadata/icall-internals.h b/src/mono/mono/metadata/icall-internals.h index 082a57b64cf808..45a51a2224b174 100644 --- a/src/mono/mono/metadata/icall-internals.h +++ b/src/mono/mono/metadata/icall-internals.h @@ -35,12 +35,6 @@ mono_icall_get_new_line (MonoError *error); MonoBoolean mono_icall_is_64bit_os (void); -MonoArrayHandle -mono_icall_get_environment_variable_names (MonoError *error); - -void -mono_icall_set_environment_variable (MonoString *name, MonoString *value); - MonoStringHandle mono_icall_get_windows_folder_path (int folder, MonoError *error); diff --git a/src/mono/mono/metadata/icall-windows.c b/src/mono/mono/metadata/icall-windows.c index e288e2d2447174..0b5adb2488679f 100644 --- a/src/mono/mono/metadata/icall-windows.c +++ b/src/mono/mono/metadata/icall-windows.c @@ -88,64 +88,6 @@ mono_icall_is_64bit_os (void) #endif } -MonoArrayHandle -mono_icall_get_environment_variable_names (MonoError *error) -{ - MonoArrayHandle names; - MonoStringHandle str; - WCHAR* env_strings; - WCHAR* env_string; - WCHAR* equal_str; - int n = 0; - - env_strings = GetEnvironmentStrings(); - - if (env_strings) { - env_string = env_strings; - while (*env_string != '\0') { - /* weird case that MS seems to skip */ - if (*env_string != '=') - n++; - while (*env_string != '\0') - env_string++; - env_string++; - } - } - - names = mono_array_new_handle (mono_defaults.string_class, n, error); - return_val_if_nok (error, NULL_HANDLE_ARRAY); - - if (env_strings) { - n = 0; - str = MONO_HANDLE_NEW (MonoString, NULL); - env_string = env_strings; - while (*env_string != '\0') { - /* weird case that MS seems to skip */ - if (*env_string != '=') { - equal_str = wcschr(env_string, '='); - g_assert(equal_str); - MonoString *s = mono_string_new_utf16_checked (env_string, (gint32)(equal_str - env_string), error); - goto_if_nok (error, cleanup); - MONO_HANDLE_ASSIGN_RAW (str, s); - - mono_array_handle_setref (names, n, str); - n++; - } - while (*env_string != '\0') - env_string++; - env_string++; - } - - } - -cleanup: - if (env_strings) - FreeEnvironmentStrings (env_strings); - if (!is_ok (error)) - return NULL_HANDLE_ARRAY; - return names; -} - #if HAVE_API_SUPPORT_WIN32_SH_GET_FOLDER_PATH #include MonoStringHandle diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 7dd21b9b538c6c..e471252ea6195b 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -6519,52 +6519,6 @@ ves_icall_System_Environment_GetIs64BitOperatingSystem (void) return mono_icall_is_64bit_os (); } -MonoStringHandle -ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error) -{ - gchar *value; - - if (utf8_name == NULL) - return NULL_HANDLE_STRING; - - value = g_getenv (utf8_name); - - if (value == 0) - return NULL_HANDLE_STRING; - - MonoStringHandle res = mono_string_new_handle (value, error); - g_free (value); - return res; -} - -/* - * There is no standard way to get at environ. - */ -#ifndef _MSC_VER -#ifndef __MINGW32_VERSION -#if defined(__APPLE__) -#if defined (TARGET_OSX) -/* Apple defines this in crt_externs.h but doesn't provide that header for - * arm-apple-darwin9. We'll manually define the symbol on Apple as it does - * in fact exist on all implementations (so far) - */ -G_BEGIN_DECLS -gchar ***_NSGetEnviron(void); -G_END_DECLS -#define environ (*_NSGetEnviron()) -#else -static char *mono_environ[1] = { NULL }; -#define environ mono_environ -#endif /* defined (TARGET_OSX) */ -#else -G_BEGIN_DECLS -extern -char **environ; -G_END_DECLS -#endif -#endif -#endif - MonoArrayHandle ves_icall_System_Environment_GetCommandLineArgs (MonoError *error) { @@ -6572,51 +6526,6 @@ ves_icall_System_Environment_GetCommandLineArgs (MonoError *error) return result; } -#ifndef HOST_WIN32 -static MonoArrayHandle -mono_icall_get_environment_variable_names (MonoError *error) -{ - MonoArrayHandle names; - MonoStringHandle str; - gchar **e, **parts; - int n; - - n = 0; - for (e = environ; *e != 0; ++ e) - ++ n; - - names = mono_array_new_handle (mono_defaults.string_class, n, error); - return_val_if_nok (error, NULL_HANDLE_ARRAY); - - str = MONO_HANDLE_NEW (MonoString, NULL); - n = 0; - for (e = environ; *e != 0; ++ e) { - parts = g_strsplit (*e, "=", 2); - if (*parts != 0) { - MonoString *s = mono_string_new_checked (*parts, error); - MONO_HANDLE_ASSIGN_RAW (str, s); - if (!is_ok (error)) { - g_strfreev (parts); - return NULL_HANDLE_ARRAY; - } - mono_array_handle_setref (names, n, str); - } - - g_strfreev (parts); - - ++ n; - } - - return names; -} -#endif /* !HOST_WIN32 */ - -MonoArrayHandle -ves_icall_System_Environment_GetEnvironmentVariableNames (MonoError *error) -{ - return mono_icall_get_environment_variable_names (error); -} - void ves_icall_System_Environment_Exit (int result) { diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 0a9d8f8ff1abd0..ede9551b57459d 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -1,7 +1,7 @@ /** * \file * Routines for marshaling complex types in P/Invoke methods. - * + * * Author: * Paolo Molaro (lupus@ximian.com) * @@ -76,7 +76,7 @@ enum { }; #undef OPDEF -/* +/* * This mutex protects the various marshalling related caches in MonoImage * and a few other data structures static to this file. * @@ -145,7 +145,7 @@ mono_signature_no_pinvoke (MonoMethod *method) sig = mono_metadata_signature_dup_full (get_method_image (method), sig); sig->pinvoke = FALSE; } - + return sig; } @@ -348,7 +348,7 @@ mono_delegate_to_ftnptr_impl (MonoDelegateHandle delegate, MonoError *error) return result; } -/* +/* * this hash table maps from a delegate trampoline object to a weak reference * of the delegate. As an optimizations with a non-moving GC we store the * object pointer itself, otherwise we use a GC handle. @@ -360,7 +360,7 @@ delegate_hash_table_new (void) { return g_hash_table_new (NULL, NULL); } -static void +static void delegate_hash_table_remove (MonoDelegate *d) { MonoGCHandle gchandle = NULL; @@ -429,7 +429,7 @@ parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piin /* The attribute is only available in Net 2.0 */ if (mono_class_try_get_unmanaged_function_pointer_attribute_class ()) { - /* + /* * The pinvoke attributes are stored in a real custom attribute so we have to * construct it. */ @@ -652,7 +652,7 @@ mono_array_to_lparray_impl (MonoArrayHandle array_handle, MonoError *error) break; case MONO_TYPE_GENERICINST: case MONO_TYPE_OBJECT: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: case MONO_TYPE_STRING: default: @@ -1138,7 +1138,7 @@ mono_type_to_ldind (MonoType *type) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return CEE_LDIND_REF; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -1192,7 +1192,7 @@ mono_type_to_stind (MonoType *type) case MONO_TYPE_STRING: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: - case MONO_TYPE_ARRAY: + case MONO_TYPE_ARRAY: return CEE_STIND_REF; case MONO_TYPE_I8: case MONO_TYPE_U8: @@ -1389,7 +1389,7 @@ mono_marshal_get_ptr_to_stringbuilder_conv (MonoMethodPInvoke *piinfo, MonoMarsh } /* - * Return whenever a field of a native structure or an array member needs to + * Return whenever a field of a native structure or an array member needs to * be freed. */ gboolean @@ -1426,7 +1426,7 @@ get_cache (GHashTable **var, GHashFunc hash_func, GCompareFunc equal_func) if (!(*var)) { mono_marshal_lock (); if (!(*var)) { - GHashTable *cache = + GHashTable *cache = g_hash_table_new (hash_func, equal_func); mono_memory_barrier (); *var = cache; @@ -1503,7 +1503,7 @@ mono_mb_create_and_cache_full (GHashTable *cache, gpointer key, } return res; -} +} MonoMethod* mono_mb_create_and_cache (GHashTable *cache, gpointer key, @@ -1616,14 +1616,14 @@ get_wrapper_target_class (MonoImage *image) /* * Notes: * - can't put all wrappers into an mscorlib class, because they reference - * metadata (signature) so they should be put into the same image as the + * metadata (signature) so they should be put into the same image as the * method they wrap, so they are unloaded together. - * - putting them into a class with a type initalizer could cause the - * initializer to be executed which can be a problem if the wrappers are + * - putting them into a class with a type initalizer could cause the + * initializer to be executed which can be a problem if the wrappers are * shared. - * - putting them into an inflated class can cause problems if the the + * - putting them into an inflated class can cause problems if the the * class is deleted because it references an image which is unloaded. - * To avoid these problems, we put the wrappers into the class of + * To avoid these problems, we put the wrappers into the class of * the image. */ if (image_is_dynamic (image)) { @@ -1818,7 +1818,7 @@ mono_marshal_get_delegate_begin_invoke (MonoMethod *method) return res; } else { cache = get_cache (&get_method_image (method)->wrapper_caches.delegate_begin_invoke_cache, - (GHashFunc)mono_signature_hash, + (GHashFunc)mono_signature_hash, (GCompareFunc)mono_metadata_signature_equal); if ((res = mono_marshal_find_in_cache (cache, sig))) return res; @@ -1896,7 +1896,7 @@ mono_marshal_get_delegate_end_invoke (MonoMethod *method) return res; } else { cache = get_cache (&get_method_image (method)->wrapper_caches.delegate_end_invoke_cache, - (GHashFunc)mono_signature_hash, + (GHashFunc)mono_signature_hash, (GCompareFunc)mono_metadata_signature_equal); if ((res = mono_marshal_find_in_cache (cache, sig))) return res; @@ -1991,8 +1991,8 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt invoke_sig = sig = mono_signature_no_pinvoke (method); /* - * If the delegate target is null, and the target method is not static, a virtual - * call is made to that method with the first delegate argument as this. This is + * If the delegate target is null, and the target method is not static, a virtual + * call is made to that method with the first delegate argument as this. This is * a non-documented .NET feature. */ if (callvirt) { @@ -2056,7 +2056,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt cache_ptr = &mono_method_get_wrapper_cache (target_method)->delegate_bound_static_invoke_cache; cache = get_cache (cache_ptr, - (GHashFunc)mono_signature_hash, + (GHashFunc)mono_signature_hash, (GCompareFunc)mono_metadata_signature_equal); /* * The wrapper is based on sig+invoke_sig, but sig can be derived from invoke_sig. @@ -2085,7 +2085,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt // Inflated methods should not be in this cache because it's not stored on the imageset. g_assert (!method->is_inflated); cache = get_cache (&get_method_image (method)->wrapper_caches.delegate_invoke_cache, - (GHashFunc)mono_signature_hash, + (GHashFunc)mono_signature_hash, (GCompareFunc)mono_metadata_signature_equal); res = mono_marshal_find_in_cache (cache, sig); if (res) @@ -2147,7 +2147,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt /* mono_method_print_code (res); */ - return res; + return res; } /** @@ -2377,7 +2377,7 @@ wrapper_cache_signature_key_equal (MonoWrapperSignatureCacheKey *key1, MonoWrapp * * We also catch exceptions if \p exc is not NULL. * If \p virtual is TRUE, then \p method is invoked virtually on \p this. This is useful since - * it means that the compiled code for \p method does not have to be looked up + * it means that the compiled code for \p method does not have to be looked up * before calling the runtime invoke wrapper. In this case, the wrapper ignores * its \p method argument. */ @@ -2559,7 +2559,7 @@ mono_marshal_get_runtime_invoke_full (MonoMethod *method, gboolean virtual_, gbo mono_mb_free (mb); - return res; + return res; } MonoMethod * @@ -2597,7 +2597,7 @@ mono_marshal_get_runtime_invoke (MonoMethod *method, gboolean virtual_) * dynamically. * The signature of the returned method is given by RuntimeInvokeDynamicFunction: * void runtime_invoke (void *args, MonoObject **exc, void *compiled_method) - * ARGS should point to an architecture specific structure containing + * ARGS should point to an architecture specific structure containing * the arguments and space for the return value. * The other arguments are the same as for runtime_invoke (), except that * ARGS should contain the this argument too. @@ -2759,7 +2759,7 @@ mono_marshal_get_icall_wrapper (MonoJitICallInfo *callinfo, gboolean check_excep WrapperInfo *info; gconstpointer const func = callinfo->func; - + GHashTable *cache = get_cache (& m_class_get_image (mono_defaults.object_class)->icall_wrapper_cache, mono_aligned_addr_hash, NULL); if ((res = mono_marshal_find_in_cache (cache, (gpointer) func))) return res; @@ -2961,8 +2961,8 @@ mono_marshal_boolean_managed_conv_in_get_conv_arg_class (MonoMarshalSpec *spec, } int -mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, - MonoMarshalSpec *spec, int conv_arg, +mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, + MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action) { /* Ensure that we have marshalling info for this param */ @@ -2973,12 +2973,12 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, if (spec && spec->native == MONO_NATIVE_ASANY) return get_marshal_cb ()->emit_marshal_asany (m, argnum, t, spec, conv_arg, conv_arg_type, action); - + switch (t->type) { case MONO_TYPE_VALUETYPE: if (t->data.klass == mono_class_try_get_handleref_class ()) return get_marshal_cb ()->emit_marshal_handleref (m, argnum, t, spec, conv_arg, conv_arg_type, action); - + return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action); case MONO_TYPE_STRING: return get_marshal_cb ()->emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action); @@ -2995,8 +2995,8 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, spec->native == MONO_NATIVE_INTERFACE)) || (t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass))) return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action); - if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) && - (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) && + if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) && + (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) && ((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH))) return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action); #endif @@ -3004,7 +3004,7 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t, if (mono_class_try_get_safehandle_class () != NULL && t->data.klass && mono_class_is_subclass_of_internal (t->data.klass, mono_class_try_get_safehandle_class (), FALSE)) return get_marshal_cb ()->emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action); - + return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action); case MONO_TYPE_ARRAY: case MONO_TYPE_SZARRAY: @@ -3439,7 +3439,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, * wrapper. */ MonoMethod * -mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig, +mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func) { MonoMethodSignature *csig; @@ -3589,17 +3589,17 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth #endif GHashTable *cache = get_cache (&image->wrapper_caches.native_func_wrapper_indirect_cache, - (GHashFunc)mono_signature_hash, + (GHashFunc)mono_signature_hash, (GCompareFunc)mono_metadata_signature_equal); - + MonoMethod *res; if ((res = mono_marshal_find_in_cache (cache, sig))) return res; - + #if 0 fprintf (stderr, "generating wrapper for signature %s\n", mono_signature_full_name (sig)); #endif - + /* FIXME: better wrapper name */ char * name = g_strdup_printf ("wrapper_native_indirect_%p", sig); MonoMethodBuilder *mb = mono_mb_new (caller_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE); @@ -3689,7 +3689,7 @@ method_signature_is_blittable (MonoMethodSignature *sig) /** * mono_marshal_get_managed_wrapper: - * Generates IL code to call managed methods from unmanaged code + * Generates IL code to call managed methods from unmanaged code * If \p target_handle is \c 0, the wrapper info will be a \c WrapperInfo structure. * * If \p delegate_klass is \c NULL, we're creating a wrapper for a function pointer to a method marked with @@ -3715,7 +3715,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, return NULL; } - /* + /* * FIXME: Should cache the method+delegate type pair, since the same method * could be called with different delegates, thus different marshalling * options. @@ -3785,7 +3785,7 @@ mono_marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, MonoCustomAttrInfo *cinfo; MonoCustomAttrEntry *attr; - /* + /* * The pinvoke attributes are stored in a real custom attribute. Obtain the * contents of the attribute without constructing it, as that might not be * possible when running in cross-compiling mode. @@ -4296,7 +4296,7 @@ mono_marshal_get_synchronized_wrapper (MonoMethod *method) } mono_mb_free (mb); - return res; + return res; } /** @@ -4320,7 +4320,7 @@ mono_marshal_get_unbox_wrapper (MonoMethod *method) mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_UNBOX); g_assert (sig->hasthis); - + get_marshal_cb ()->emit_unbox_wrapper (mb, method); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE); @@ -4332,7 +4332,7 @@ mono_marshal_get_unbox_wrapper (MonoMethod *method) /* mono_method_print_code (res); */ - return res; + return res; } static gboolean @@ -4493,7 +4493,7 @@ mono_marshal_get_stelemref (void) WrapperInfo *info; MONO_STATIC_POINTER_INIT (MonoMethod, ret) - + mb = mono_mb_new (mono_defaults.object_class, "stelemref", MONO_WRAPPER_STELEMREF); sig = mono_metadata_signature_alloc (mono_defaults.corlib, 3); @@ -4533,9 +4533,9 @@ mono_marshal_get_gsharedvt_in_wrapper (void) MonoMethodSignature *sig; MonoMethodBuilder *mb; WrapperInfo *info; - + mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_in", MONO_WRAPPER_OTHER); - + sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0); sig->ret = mono_get_void_type (); @@ -4566,9 +4566,9 @@ mono_marshal_get_gsharedvt_out_wrapper (void) MonoMethodSignature *sig; MonoMethodBuilder *mb; WrapperInfo *info; - + mb = mono_mb_new (mono_defaults.object_class, "gsharedvt_out", MONO_WRAPPER_OTHER); - + sig = mono_metadata_signature_alloc (mono_defaults.corlib, 0); sig->ret = mono_get_void_type (); @@ -4646,7 +4646,7 @@ mono_marshal_get_array_address (int rank, int elem_size) name = g_strdup_printf ("ElementAddr_%d", elem_size); mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_MANAGED); g_free (name); - + get_marshal_cb ()->emit_array_address (mb, rank, elem_size); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_ELEMENT_ADDR); @@ -4738,7 +4738,7 @@ mono_marshal_get_array_accessor_wrapper (MonoMethod *method) } mono_mb_free (mb); - return res; + return res; } #ifndef HOST_WIN32 @@ -4802,7 +4802,7 @@ mono_marshal_free (gpointer ptr) * mono_marshal_free_array: */ void -mono_marshal_free_array (gpointer *ptr, int size) +mono_marshal_free_array (gpointer *ptr, int size) { int i; @@ -5070,9 +5070,9 @@ mono_struct_delete_old (MonoClass *klass, char *ptr) if (ftype->attrs & FIELD_ATTRIBUTE_STATIC) continue; - mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, + mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, m_class_is_unicode (klass), &conv); - + cpos = ptr + info->fields [i].offset; switch (conv) { @@ -5087,7 +5087,7 @@ mono_struct_delete_old (MonoClass *klass, char *ptr) break; case MONO_MARSHAL_CONV_STR_LPTSTR: #ifdef TARGET_WIN32 - /* We assume this field points inside a MonoString + /* We assume this field points inside a MonoString * on Win32 */ break; #endif @@ -5259,7 +5259,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_IsPinnableType (MonoReflectionT if (m_class_get_rank (klass)) { MonoClass *eklass = m_class_get_element_class (klass); if (m_class_is_primitive (eklass)) - return TRUE; + return TRUE; return eklass != mono_defaults.object_class && m_class_is_blittable (eklass); } else return m_class_is_blittable (klass); @@ -5283,7 +5283,7 @@ mono_marshal_is_loading_type_info (MonoClass *klass) * mono_marshal_load_type_info: * * Initialize \c klass::marshal_info using information from metadata. This function can - * recursively call itself, and the caller is responsible to avoid that by calling + * recursively call itself, and the caller is responsible to avoid that by calling * \c mono_marshal_is_loading_type_info beforehand. * * LOCKING: Acquires the loader lock. @@ -5320,7 +5320,7 @@ mono_marshal_load_type_info (MonoClass* klass) loads_list = (GSList *)mono_native_tls_get_value (load_type_info_tls_id); loads_list = g_slist_prepend (loads_list, klass); mono_native_tls_set_value (load_type_info_tls_id, loads_list); - + iter = NULL; while ((field = mono_class_get_fields_internal (klass, &iter))) { if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) @@ -5334,7 +5334,7 @@ mono_marshal_load_type_info (MonoClass* klass) info = (MonoMarshalType *)mono_image_alloc0 (m_class_get_image (klass), MONO_SIZEOF_MARSHAL_TYPE + sizeof (MonoMarshalField) * count); info->num_fields = count; - + /* Try to find a size for this type in metadata */ mono_metadata_packing_from_typedef (m_class_get_image (klass), m_class_get_type_token (klass), NULL, &native_size); @@ -5352,14 +5352,14 @@ mono_marshal_load_type_info (MonoClass* klass) while ((field = mono_class_get_fields_internal (klass, &iter))) { int size; guint32 align; - + if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) continue; if (mono_field_is_deleted (field)) continue; if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL) - mono_metadata_field_info_with_mempool (m_class_get_image (klass), mono_metadata_token_index (mono_class_get_field_token (field)) - 1, + mono_metadata_field_info_with_mempool (m_class_get_image (klass), mono_metadata_token_index (mono_class_get_field_token (field)) - 1, NULL, NULL, &info->fields [j].mspec); info->fields [j].field = field; @@ -5373,7 +5373,7 @@ mono_marshal_load_type_info (MonoClass* klass) switch (layout) { case TYPE_ATTRIBUTE_AUTO_LAYOUT: case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT: - size = mono_marshal_type_size (field->type, info->fields [j].mspec, + size = mono_marshal_type_size (field->type, info->fields [j].mspec, &align, TRUE, m_class_is_unicode (klass)); align = m_class_get_packing_size (klass) ? MIN (m_class_get_packing_size (klass), align): align; min_align = MAX (align, min_align); @@ -5383,13 +5383,13 @@ mono_marshal_load_type_info (MonoClass* klass) info->native_size = info->fields [j].offset + size; break; case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: - size = mono_marshal_type_size (field->type, info->fields [j].mspec, + size = mono_marshal_type_size (field->type, info->fields [j].mspec, &align, TRUE, m_class_is_unicode (klass)); min_align = MAX (align, min_align); info->fields [j].offset = field->offset - MONO_ABI_SIZEOF (MonoObject); info->native_size = MAX (info->native_size, info->fields [j].offset + size); break; - } + } j++; } @@ -5448,9 +5448,9 @@ mono_marshal_load_type_info (MonoClass* klass) /** * mono_class_native_size: - * \param klass a class - * \returns the native size of an object instance (when marshaled - * to unmanaged code) + * \param klass a class + * \returns the native size of an object instance (when marshaled + * to unmanaged code) */ gint32 mono_class_native_size (MonoClass *klass, guint32 *align) @@ -5531,7 +5531,7 @@ mono_type_native_stack_size (MonoType *t, guint32 *align) if (!mono_type_generic_inst_is_valuetype (t)) { *align = TARGET_SIZEOF_VOID_P; return TARGET_SIZEOF_VOID_P; - } + } /* Fall through */ case MONO_TYPE_TYPEDBYREF: case MONO_TYPE_VALUETYPE: { @@ -5544,7 +5544,7 @@ mono_type_native_stack_size (MonoType *t, guint32 *align) size = mono_class_native_size (klass, align); *align = *align + 3; *align &= ~3; - + size += 3; size &= ~3; @@ -5615,19 +5615,12 @@ mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align, case MONO_NATIVE_LPSTRUCT: *align = MONO_ABI_ALIGNOF (gpointer); return TARGET_SIZEOF_VOID_P; - case MONO_NATIVE_STRUCT: + case MONO_NATIVE_STRUCT: klass = mono_class_from_mono_type_internal (type); if (klass == mono_defaults.object_class && (mspec && mspec->native == MONO_NATIVE_STRUCT)) { *align = 16; return 16; - } else if (strcmp (m_class_get_name_space (klass), "System") == 0 && - strcmp (m_class_get_name (klass), "Decimal") == 0) { - - // Special case: Managed Decimal consists of 4 int32 fields, the alignment should be 8 on x64 to follow - // https://github.com/dotnet/coreclr/blob/4450e5ca663b9e66c20e6f9751c941efa3716fde/src/vm/methodtablebuilder.cpp#L9753 - *align = MONO_ABI_ALIGNOF (gpointer); - return mono_class_native_size (klass, NULL); } padded_size = mono_class_native_size (klass, align); if (padded_size == 0) @@ -5659,7 +5652,7 @@ mono_marshal_type_size (MonoType *type, MonoMarshalSpec *mspec, guint32 *align, case MONO_NATIVE_CURRENCY: case MONO_NATIVE_VBBYREFSTR: default: - g_error ("native type %02x not implemented", native_type); + g_error ("native type %02x not implemented", native_type); break; } g_assert_not_reached (); @@ -5732,7 +5725,7 @@ mono_marshal_asany_impl (MonoObjectHandle o, MonoMarshalNative string_encoding, return res; } case MONO_TYPE_SZARRAY: { - //TODO: Implement structs and in-params for all value types + //TODO: Implement structs and in-params for all value types MonoClass *klass = t->data.klass; MonoClass *eklass = m_class_get_element_class (klass); MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o); @@ -6040,7 +6033,7 @@ mono_marshal_free_dynamic_wrappers (MonoMethod *method) /* This could be called during shutdown */ if (marshal_mutex_initialized) mono_marshal_lock (); - /* + /* * FIXME: We currently leak the wrappers. Freeing them would be tricky as * they could be shared with other methods ? */ diff --git a/src/mono/mono/metadata/mono-debug.c b/src/mono/mono/metadata/mono-debug.c index b9bea0e78f5d06..03626981f441d0 100644 --- a/src/mono/mono/metadata/mono-debug.c +++ b/src/mono/mono/metadata/mono-debug.c @@ -867,7 +867,7 @@ mono_debug_method_lookup_location (MonoDebugMethodInfo *minfo, int il_offset) * The result should be freed using mono_debug_free_locals (). */ MonoDebugLocalsInfo* -mono_debug_lookup_locals (MonoMethod *method, mono_bool ignore_pdb) +mono_debug_lookup_locals (MonoMethod *method) { MonoDebugMethodInfo *minfo; MonoDebugLocalsInfo *res; @@ -893,18 +893,16 @@ mono_debug_lookup_locals (MonoMethod *method, mono_bool ignore_pdb) return NULL; } - if (ignore_pdb) - res = mono_debug_symfile_lookup_locals (minfo); - else { - if (minfo->handle->ppdb) { - res = mono_ppdb_lookup_locals (minfo); - } else { - if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) - res = NULL; - else - res = mono_debug_symfile_lookup_locals (minfo); - } + + if (minfo->handle->ppdb) { + res = mono_ppdb_lookup_locals (minfo); + } else { + if (!minfo->handle->symfile || !mono_debug_symfile_is_loaded (minfo->handle->symfile)) + res = NULL; + else + res = mono_debug_symfile_lookup_locals (minfo); } + mono_debugger_unlock (); return res; diff --git a/src/mono/mono/metadata/mono-debug.h b/src/mono/mono/metadata/mono-debug.h index 2ddbce09947153..2fe6a3394afda1 100644 --- a/src/mono/mono/metadata/mono-debug.h +++ b/src/mono/mono/metadata/mono-debug.h @@ -189,7 +189,7 @@ MONO_API void mono_debug_add_delegate_trampoline (void* code, int size); MONO_API MonoDebugLocalsInfo* -mono_debug_lookup_locals (MonoMethod *method, mono_bool ignore_pdb); +mono_debug_lookup_locals (MonoMethod *method); MONO_API MonoDebugMethodAsyncInfo* mono_debug_lookup_method_async_debug_info (MonoMethod *method); diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c index dd67477d092d4c..f01b9efbae5ddb 100644 --- a/src/mono/mono/metadata/native-library.c +++ b/src/mono/mono/metadata/native-library.c @@ -951,6 +951,7 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou const char *new_import = NULL; const char *orig_scope = NULL; const char *new_scope = NULL; + const char *error_scope = NULL; char *error_msg = NULL; MonoDl *module = NULL; gpointer addr = NULL; @@ -997,6 +998,8 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou new_import = g_strdup (orig_import); #endif + error_scope = new_scope; + /* If qcalls are disabled, we fall back to the normal pinvoke code for them */ #ifndef DISABLE_QCALLS if (strcmp (new_scope, "QCall") == 0) { @@ -1051,10 +1054,10 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou if (!module) { mono_trace (G_LOG_LEVEL_WARNING, MONO_TRACE_DLLIMPORT, "DllImport unable to load library '%s'.", - new_scope); + error_scope); status_out->err_code = LOOKUP_PINVOKE_ERR_NO_LIB; - status_out->err_arg = g_strdup (new_scope); + status_out->err_arg = g_strdup (error_scope); goto exit; } @@ -1066,7 +1069,7 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou if (!addr) { #ifndef HOST_WIN32 if (strcmp (new_scope, "__Internal") == 0) { - g_free ((char *)new_scope); + g_assert (error_scope == new_scope); new_scope = g_strdup (MONO_LOADER_LIBRARY_NAME); goto retry_with_libcoreclr; } @@ -1078,6 +1081,9 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou piinfo->addr = addr; exit: + if (error_scope != new_scope) { + g_free ((char *)error_scope); + } g_free ((char *)new_import); g_free ((char *)new_scope); g_free (error_msg); diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index 9702920b3c26eb..8f47c92ee86cdf 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -1068,6 +1068,7 @@ typedef struct { MonoArray *cattrs; MonoString *version; MonoString *culture; + MonoArray *public_key_token; MonoArray *loaded_modules; guint32 access; } MonoReflectionAssemblyBuilder; diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index b4a19469544991..cbabe1f08fb1e2 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -397,6 +397,7 @@ mono_runtime_run_module_cctor (MonoImage *image, MonoError *error) MonoClass *module_klass; MonoVTable *module_vtable; + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_TYPE, "Running module .cctor for '%s'", image->name); module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, error); if (!module_klass) { return FALSE; @@ -522,6 +523,11 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) if (do_initialization) { MonoException *exc = NULL; + if (mono_trace_is_traced (G_LOG_LEVEL_DEBUG, MONO_TRACE_TYPE)) { + char* type_name = mono_type_full_name (m_class_get_byval_arg (klass)); + mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_TYPE, "Running class .cctor for %s from '%s'", type_name, m_class_get_image (klass)->name); + g_free (type_name); + } /* We are holding the per-vtable lock, do the actual initialization */ mono_threads_begin_abort_protected_block (); diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index 17e49231129ea6..c2c599d197a4f9 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -1263,6 +1263,13 @@ mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb, M assembly->assembly.aname.revision = 0; } + if (assemblyb->public_key_token) { + for (int i = 0; i < 8 && i < mono_array_length_internal (assemblyb->public_key_token); i++) { + guint8 byte = mono_array_get_internal (assemblyb->public_key_token, guint8, i); + sprintf ((char*)(assembly->assembly.aname.public_key_token + 2 * i), "%02x", byte); + } + } + /* SRE assemblies are loaded into the individual loading context, ie, * they only fire AssemblyResolve events, they don't cause probing for * referenced assemblies to happen. */ diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 3e9ca497336abf..54a5e44096a111 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -44,8 +44,10 @@ include(../eglib/CMakeLists.txt) include(../utils/CMakeLists.txt) include(../metadata/CMakeLists.txt) include(../sgen/CMakeLists.txt) -if(INTERNAL_ZLIB) # TODO: hook up HAVE_SYS_ZLIB instead +if(INTERNAL_ZLIB) include(../zlib/CMakeLists.txt) +elseif(HAVE_SYS_ZLIB) + set(Z_LIBS z) endif() include(../component/CMakeLists.txt) @@ -315,6 +317,8 @@ endif() if(HOST_WIN32) set(mini_sources "${mini_sources};${PROJECT_BINARY_DIR}/../../NativeVersion.rc") # this is generated by GenerateMonoVersionFile in mono.proj +elseif(NOT HOST_BROWSER) +set(mini_sources "${mini_sources};${PROJECT_BINARY_DIR}/../../version.c") # this is generated by GenerateMonoVersionFile in mono.proj endif() set(monosgen-sources "${metadata_sources};${utils_sources};${sgen_sources};${icu_shim_sources};${mini_sources};${zlib_sources}") @@ -352,7 +356,7 @@ if(NOT DISABLE_SHARED_LIBS) # to avoid a conflict we rename the import library with the .import.lib suffix set_target_properties(monosgen-shared PROPERTIES IMPORT_SUFFIX ".import.lib") endif() - target_link_libraries(monosgen-shared PRIVATE ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS}) + target_link_libraries(monosgen-shared PRIVATE ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS} ${Z_LIBS}) if(ICU_LDFLAGS) set_property(TARGET monosgen-shared APPEND_STRING PROPERTY LINK_FLAGS " ${ICU_LDFLAGS}") endif() @@ -402,7 +406,7 @@ if(NOT DISABLE_SHARED_LIBS) add_library(${frameworkconfig} SHARED $) target_compile_definitions(${frameworkconfig} PRIVATE -DMONO_DLL_EXPORT) target_sources(${frameworkconfig} PRIVATE $) - target_link_libraries(${frameworkconfig} PRIVATE ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS}) + target_link_libraries(${frameworkconfig} PRIVATE ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS} ${Z_LIBS}) if(ICU_LDFLAGS) set_property(TARGET ${frameworkconfig} APPEND_STRING PROPERTY LINK_FLAGS " ${ICU_LDFLAGS}") endif() @@ -473,7 +477,10 @@ if(NOT DISABLE_EXECUTABLES) set(sgen_sources "${sgen_sources};${PROJECT_BINARY_DIR}/../../NativeVersion.rc") endif() add_executable(mono-sgen "${sgen_sources}") - target_link_libraries(mono-sgen PRIVATE monosgen-static ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS}) + if(MONO_CROSS_COMPILE_EXECUTABLE_NAME) + set_target_properties(mono-sgen PROPERTIES OUTPUT_NAME mono-aot-cross) + endif() + target_link_libraries(mono-sgen PRIVATE monosgen-static ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS} ${Z_LIBS}) if(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS AND NOT DISABLE_LINK_STATIC_COMPONENTS) # if components are built statically, link them into runtime. target_sources(mono-sgen PRIVATE "${mono-components-objects}") @@ -492,4 +499,7 @@ if(NOT DISABLE_EXECUTABLES) set_property(TARGET mono-sgen APPEND_STRING PROPERTY LINK_FLAGS " ${ICU_LDFLAGS}") endif() install(TARGETS mono-sgen RUNTIME) + if(HOST_WIN32) + install(FILES $ DESTINATION bin OPTIONAL) + endif() endif() diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 369016e11892d6..34c1e7606d048e 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -1149,7 +1149,7 @@ arch_init (MonoAotCompile *acfg) if (strstr (acfg->aot_opts.mtriple, "ios")) { g_string_append (acfg->llc_args, " -mattr=+v7"); - g_string_append (acfg->llc_args, " -exception-model=dwarf -disable-fp-elim"); + g_string_append (acfg->llc_args, " -exception-model=dwarf -frame-pointer=all"); } } diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 3b753a44cb0d44..4d27652a69cb44 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -3534,7 +3534,17 @@ mono_aot_find_jit_info (MonoImage *image, gpointer addr) else code_len = amodule->llvm_code_end - code; } else { - code_len = (guint8*)methods [pos + 1] - (guint8*)methods [pos]; + guint8* code_end = (guint8*)methods [pos + 1]; + + if (code >= amodule->jit_code_start && code < amodule->jit_code_end && code_end > amodule->jit_code_end) { + code_end = amodule->jit_code_end; + } + + if (code >= amodule->llvm_code_start && code < amodule->llvm_code_end && code_end > amodule->llvm_code_end) { + code_end = amodule->llvm_code_end; + } + + code_len = code_end - code; } #endif diff --git a/src/mono/mono/mini/cpu-amd64.md b/src/mono/mono/mini/cpu-amd64.md index 48a1b9f0fbafae..8ee095962f51f1 100644 --- a/src/mono/mono/mini/cpu-amd64.md +++ b/src/mono/mono/mini/cpu-amd64.md @@ -284,7 +284,6 @@ float_cgt_membase: dest:i src1:f src2:b len:35 float_cgt_un_membase: dest:i src1:f src2:b len:48 float_clt_membase: dest:i src1:f src2:b len:35 float_clt_un_membase: dest:i src1:f src2:b len:42 -float_conv_to_u: dest:i src1:f len:46 # R4 opcodes r4_conv_to_i1: dest:i src1:f len:32 diff --git a/src/mono/mono/mini/cpu-arm.md b/src/mono/mono/mini/cpu-arm.md index b14cc6f3218128..cab9cd2c45bcd1 100644 --- a/src/mono/mono/mini/cpu-arm.md +++ b/src/mono/mono/mini/cpu-arm.md @@ -220,7 +220,6 @@ float_clt_un: dest:i src1:f src2:f len:20 float_cneq: dest:y src1:f src2:f len:20 float_cge: dest:y src1:f src2:f len:20 float_cle: dest:y src1:f src2:f len:20 -float_conv_to_u: dest:i src1:f len:36 # R4 opcodes rmove: dest:f src1:f len:4 diff --git a/src/mono/mono/mini/cpu-arm64.md b/src/mono/mono/mini/cpu-arm64.md index aff89052937a78..06e4fe0d5e9798 100644 --- a/src/mono/mono/mini/cpu-arm64.md +++ b/src/mono/mono/mini/cpu-arm64.md @@ -218,7 +218,6 @@ float_clt_un: dest:i src1:f src2:f len:20 float_cneq: dest:i src1:f src2:f len:20 float_cge: dest:i src1:f src2:f len:20 float_cle: dest:i src1:f src2:f len:20 -float_conv_to_u: dest:i src1:f len:36 setfret: src1:f len:12 # R4 opcodes diff --git a/src/mono/mono/mini/cpu-mips.md b/src/mono/mono/mini/cpu-mips.md index 96920a0747b52c..3757749fcdf676 100644 --- a/src/mono/mono/mini/cpu-mips.md +++ b/src/mono/mono/mini/cpu-mips.md @@ -383,7 +383,6 @@ float_cgt: dest:i src1:f src2:f len:20 float_cgt_un: dest:i src1:f src2:f len:20 float_clt: dest:i src1:f src2:f len:20 float_clt_un: dest:i src1:f src2:f len:20 -float_conv_to_u: dest:i src1:f len:36 call_handler: len:20 clob:c endfilter: src1:i len:16 aotconst: dest:i len:8 diff --git a/src/mono/mono/mini/cpu-ppc.md b/src/mono/mono/mini/cpu-ppc.md index 6ef33f2887220a..69e9e1beb525ff 100644 --- a/src/mono/mono/mini/cpu-ppc.md +++ b/src/mono/mono/mini/cpu-ppc.md @@ -200,7 +200,6 @@ float_cgt: dest:i src1:f src2:f len:16 float_cgt_un: dest:i src1:f src2:f len:20 float_clt: dest:i src1:f src2:f len:16 float_clt_un: dest:i src1:f src2:f len:20 -float_conv_to_u: dest:i src1:f len:36 float_cneq: dest:i src1:f src2:f len:16 float_cge: dest:i src1:f src2:f len:16 float_cle: dest:i src1:f src2:f len:16 diff --git a/src/mono/mono/mini/cpu-ppc64.md b/src/mono/mono/mini/cpu-ppc64.md index fc0e634baa460f..6ce9314bffe8e5 100644 --- a/src/mono/mono/mini/cpu-ppc64.md +++ b/src/mono/mono/mini/cpu-ppc64.md @@ -204,7 +204,6 @@ float_cgt: dest:i src1:f src2:f len:16 float_cgt_un: dest:i src1:f src2:f len:20 float_clt: dest:i src1:f src2:f len:16 float_clt_un: dest:i src1:f src2:f len:20 -float_conv_to_u: dest:i src1:f len:36 float_cneq: dest:i src1:f src2:f len:16 float_cge: dest:i src1:f src2:f len:16 float_cle: dest:i src1:f src2:f len:16 diff --git a/src/mono/mono/mini/cpu-s390x.md b/src/mono/mono/mini/cpu-s390x.md index f3196485c13a36..d4469bda39c972 100644 --- a/src/mono/mono/mini/cpu-s390x.md +++ b/src/mono/mono/mini/cpu-s390x.md @@ -128,7 +128,6 @@ float_conv_to_u1: dest:i src1:f len:72 float_conv_to_u2: dest:i src1:f len:72 float_conv_to_u4: dest:i src1:f len:72 float_conv_to_u8: dest:i src1:f len:72 -float_conv_to_u: dest:i src1:f len:36 float_div: dest:f src1:f src2:f len:24 float_div_un: dest:f src1:f src2:f len:30 float_mul: dest:f src1:f src2:f len:8 diff --git a/src/mono/mono/mini/cpu-sparc.md b/src/mono/mono/mini/cpu-sparc.md index 403a73c380ee80..64487cf52a328e 100644 --- a/src/mono/mono/mini/cpu-sparc.md +++ b/src/mono/mono/mini/cpu-sparc.md @@ -180,7 +180,6 @@ float_cgt: dest:i src1:f src2:f len:64 float_cgt_un: dest:i src1:f src2:f len:64 float_clt: dest:i src1:f src2:f len:64 float_clt_un: dest:i src1:f src2:f len:64 -float_conv_to_u: dest:i src1:f len:64 call_handler: len:64 clob:c aotconst: dest:i len:64 adc: dest:i src1:i src2:i len:4 diff --git a/src/mono/mono/mini/cpu-x86.md b/src/mono/mono/mini/cpu-x86.md index 25e44d16eea5b7..6132887bbd3450 100644 --- a/src/mono/mono/mini/cpu-x86.md +++ b/src/mono/mono/mini/cpu-x86.md @@ -266,7 +266,6 @@ float_clt_un: dest:y src1:f src2:f len:32 float_cneq: dest:y src1:f src2:f len:25 float_cge: dest:y src1:f src2:f len:37 float_cle: dest:y src1:f src2:f len:37 -float_conv_to_u: dest:i src1:f len:36 call_handler: len:11 clob:c aotconst: dest:i len:5 load_gotaddr: dest:i len:64 diff --git a/src/mono/mono/mini/dwarfwriter.c b/src/mono/mono/mini/dwarfwriter.c index 1bac0d946391e7..d23074199bc65c 100644 --- a/src/mono/mono/mini/dwarfwriter.c +++ b/src/mono/mono/mini/dwarfwriter.c @@ -1899,7 +1899,7 @@ mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod g_free (names); /* Locals */ - locals_info = mono_debug_lookup_locals (method, FALSE); + locals_info = mono_debug_lookup_locals (method); for (i = 0; i < header->num_locals; ++i) { MonoInst *ins = locals [i]; diff --git a/src/mono/mono/mini/image-writer.c b/src/mono/mono/mini/image-writer.c index cc81ac7b070dcd..db6fd89acad0be 100644 --- a/src/mono/mono/mini/image-writer.c +++ b/src/mono/mono/mini/image-writer.c @@ -77,7 +77,7 @@ #elif defined(TARGET_ASM_GAS) && defined(TARGET_WIN32) #define AS_INT16_DIRECTIVE ".word" #elif defined(TARGET_ASM_GAS) -#define AS_INT16_DIRECTIVE ".hword" +#define AS_INT16_DIRECTIVE ".short" #else #define AS_INT16_DIRECTIVE ".word" #endif diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 6db2f621167d95..9562b8aeffcf81 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -495,8 +495,12 @@ mono_interp_get_imethod (MonoMethod *method, MonoError *error) imethod->param_types [i] = mini_get_underlying_type (sig->params [i]); jit_mm_lock (jit_mm); - if (!mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method)) + InterpMethod *old_imethod; + if (!((old_imethod = mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method)))) mono_internal_hash_table_insert (&jit_mm->interp_code_hash, method, imethod); + else { + imethod = old_imethod; /* leak the newly allocated InterpMethod to the mempool */ + } jit_mm_unlock (jit_mm); imethod->prof_flags = mono_profiler_get_call_instrumentation_flags (imethod->method); @@ -4873,7 +4877,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_U4_R8) #ifdef MONO_ARCH_EMULATE_FCONV_TO_U4 - LOCAL_VAR (ip [1], gint32) = mono_fconv_u4_2 (LOCAL_VAR (ip [2], double)); + LOCAL_VAR (ip [1], gint32) = mono_fconv_u4 (LOCAL_VAR (ip [2], double)); #else LOCAL_VAR (ip [1], gint32) = (guint32) LOCAL_VAR (ip [2], double); #endif @@ -4929,7 +4933,7 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; MINT_IN_CASE(MINT_CONV_U8_R8) #ifdef MONO_ARCH_EMULATE_FCONV_TO_U8 - LOCAL_VAR (ip [1], gint64) = mono_fconv_u8_2 (LOCAL_VAR (ip [2], double)); + LOCAL_VAR (ip [1], gint64) = mono_fconv_u8 (LOCAL_VAR (ip [2], double)); #else LOCAL_VAR (ip [1], gint64) = (guint64) LOCAL_VAR (ip [2], double); #endif @@ -5414,6 +5418,16 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_LDSFLD_W) { + MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [READ32 (ip + 2)]; + INIT_VTABLE (vtable); + gpointer addr = frame->imethod->data_items [READ32 (ip + 4)]; + MonoClass *klass = frame->imethod->data_items [READ32 (ip + 6)]; + stackval_from_data (m_class_get_byval_arg (klass), (stackval*)(locals + ip [1]), addr, FALSE); + ip += 8; + MINT_IN_BREAK; + } + #define STSFLD(datatype, fieldtype) { \ MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [ip [2]]; \ INIT_VTABLE (vtable); \ @@ -5440,6 +5454,16 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_STSFLD_W) { + MonoVTable *vtable = (MonoVTable*) frame->imethod->data_items [READ32 (ip + 2)]; + INIT_VTABLE (vtable); + gpointer addr = frame->imethod->data_items [READ32 (ip + 4)]; + MonoClass *klass = frame->imethod->data_items [READ32 (ip + 6)]; + stackval_to_data (m_class_get_byval_arg (klass), (stackval*)(locals + ip [1]), addr, FALSE); + ip += 8; + MINT_IN_BREAK; + } + MINT_IN_CASE(MINT_STOBJ_VT) { MonoClass *c = (MonoClass*)frame->imethod->data_items [ip [3]]; mono_value_copy_internal (LOCAL_VAR (ip [1], gpointer), locals + ip [2], c); @@ -5472,33 +5496,29 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U8_R4) { float val = LOCAL_VAR (ip [2], float); - if (mono_isnan (val) || mono_trunc (val) != (guint64)val) + if (!mono_try_trunc_u64 (val, (guint64*)(locals + ip [1]))) THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], guint64) = (guint64)val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U8_R8) { double val = LOCAL_VAR (ip [2], double); - if (mono_isnan (val) || mono_trunc (val) != (guint64)val) + if (!mono_try_trunc_u64 (val, (guint64*)(locals + ip [1]))) THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], guint64) = (guint64)val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I8_R4) { float val = LOCAL_VAR (ip [2], float); - if (mono_isnan (val) || mono_trunc (val) != (gint64)val) + if (!mono_try_trunc_i64 (val, (gint64*)(locals + ip [1]))) THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint64) = (gint64)val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I8_R8) { double val = LOCAL_VAR (ip [2], double); - if (mono_isnan (val) || mono_trunc (val) != (gint64)val) + if (!mono_try_trunc_i64 (val, (gint64*)(locals + ip [1]))) THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint64) = (gint64)val; ip += 3; MINT_IN_BREAK; } @@ -5800,17 +5820,20 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I4_R4) { float val = LOCAL_VAR (ip [2], float); - if (mono_isnan (val) || mono_trunc (val) != (gint32)val) + double val_r8 = (double)val; + if (val_r8 > ((double)G_MININT32 - 1) && val_r8 < ((double)G_MAXINT32 + 1)) + LOCAL_VAR (ip [1], gint32) = (gint32) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (gint32) val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I4_R8) { double val = LOCAL_VAR (ip [2], double); - if (val < G_MININT32 || val > G_MAXINT32 || isnan (val)) + if (val > ((double)G_MININT32 - 1) && val < ((double)G_MAXINT32 + 1)) + LOCAL_VAR (ip [1], gint32) = (gint32) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (gint32)val; ip += 3; MINT_IN_BREAK; } @@ -5832,17 +5855,20 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U4_R4) { float val = LOCAL_VAR (ip [2], float); - if (mono_isnan (val) || mono_trunc (val) != (guint32)val) + double val_r8 = val; + if (val_r8 > -1.0 && val_r8 < ((double)G_MAXUINT32 + 1)) + LOCAL_VAR (ip [1], gint32) = (guint32)val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (guint32)val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U4_R8) { double val = LOCAL_VAR (ip [2], double); - if (val < 0 || val > G_MAXUINT32 || isnan (val)) + if (val > -1.0 && val < ((double)G_MAXUINT32 + 1)) + LOCAL_VAR (ip [1], gint32) = (guint32)val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (guint32) val; ip += 3; MINT_IN_BREAK; } @@ -5880,17 +5906,19 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I2_R4) { float val = LOCAL_VAR (ip [2], float); - if (val < G_MININT16 || val > G_MAXINT16 || isnan (val)) + if (val > (G_MININT16 - 1) && val < (G_MAXINT16 + 1)) + LOCAL_VAR (ip [1], gint32) = (gint16) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (gint16) val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I2_R8) { double val = LOCAL_VAR (ip [2], double); - if (val < G_MININT16 || val > G_MAXINT16 || isnan (val)) + if (val > (G_MININT16 - 1) && val < (G_MAXINT16 + 1)) + LOCAL_VAR (ip [1], gint32) = (gint16) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (gint16) val; ip += 3; MINT_IN_BREAK; } @@ -5912,17 +5940,19 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U2_R4) { float val = LOCAL_VAR (ip [2], float); - if (val < 0 || val > G_MAXUINT16 || isnan (val)) + if (val > -1.0f && val < (G_MAXUINT16 + 1)) + LOCAL_VAR (ip [1], gint32) = (guint16) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (guint16) val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U2_R8) { double val = LOCAL_VAR (ip [2], double); - if (val < 0 || val > G_MAXUINT16 || isnan (val)) + if (val > -1.0 && val < (G_MAXUINT16 + 1)) + LOCAL_VAR (ip [1], gint32) = (guint16) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (guint16) val; ip += 3; MINT_IN_BREAK; } @@ -5960,17 +5990,19 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I1_R4) { float val = LOCAL_VAR (ip [2], float); - if (val < G_MININT8 || val > G_MAXINT8 || isnan (val)) + if (val > (G_MININT8 - 1) && val < (G_MAXINT8 + 1)) + LOCAL_VAR (ip [1], gint32) = (gint8) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (gint8) val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_I1_R8) { double val = LOCAL_VAR (ip [2], double); - if (val < G_MININT8 || val > G_MAXINT8 || isnan (val)) + if (val > (G_MININT8 - 1) && val < (G_MAXINT8 + 1)) + LOCAL_VAR (ip [1], gint32) = (gint8) val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (gint8) val; ip += 3; MINT_IN_BREAK; } @@ -5992,17 +6024,19 @@ MINT_IN_CASE(MINT_BRTRUE_I8_SP) ZEROP_SP(gint64, !=); MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U1_R4) { float val = LOCAL_VAR (ip [2], float); - if (val < 0 || val > G_MAXUINT8 || isnan (val)) + if (val > -1.0f && val < (G_MAXUINT8 + 1)) + LOCAL_VAR (ip [1], gint32) = (guint8)val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (guint8) val; ip += 3; MINT_IN_BREAK; } MINT_IN_CASE(MINT_CONV_OVF_U1_R8) { double val = LOCAL_VAR (ip [2], double); - if (val < 0 || val > G_MAXUINT8 || isnan (val)) + if (val > -1.0 && val < (G_MAXUINT8 + 1)) + LOCAL_VAR (ip [1], gint32) = (guint8)val; + else THROW_EX (mono_get_exception_overflow (), ip); - LOCAL_VAR (ip [1], gint32) = (guint8) val; ip += 3; MINT_IN_BREAK; } @@ -7421,28 +7455,44 @@ interp_invalidate_transformed (void) } typedef struct { - InterpJitInfoFunc func; - gpointer user_data; -} InterpJitInfoFuncUserData; + MonoJitInfo **jit_info_array; + gint size; + gint next; +} InterpCopyJitInfoFuncUserData; static void -interp_call_jit_info_func (gpointer imethod, gpointer user_data) +interp_copy_jit_info_func (gpointer imethod, gpointer user_data) { - InterpJitInfoFuncUserData *data = (InterpJitInfoFuncUserData *)user_data; - data->func (((InterpMethod *)imethod)->jinfo, data->user_data); + InterpCopyJitInfoFuncUserData *data = (InterpCopyJitInfoFuncUserData*)user_data; + if (data->next < data->size) + data->jit_info_array [data->next++] = ((InterpMethod *)imethod)->jinfo; } static void interp_jit_info_foreach (InterpJitInfoFunc func, gpointer user_data) { - InterpJitInfoFuncUserData data = {func, user_data}; + InterpCopyJitInfoFuncUserData copy_jit_info_data; // FIXME: Enumerate all memory managers MonoJitMemoryManager *jit_mm = get_default_jit_mm (); - jit_mm_lock (jit_mm); - mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_call_jit_info_func, &data); - jit_mm_unlock (jit_mm); + // Can't keep memory manager lock while iterating and calling callback since it might take other locks + // causing poential deadlock situations. Instead, create copy of interpreter imethod jinfo pointers into + // plain array and use pointers from array when when running callbacks. + copy_jit_info_data.size = mono_atomic_load_i32 (&(jit_mm->interp_code_hash.num_entries)); + copy_jit_info_data.next = 0; + copy_jit_info_data.jit_info_array = (MonoJitInfo**) g_new (MonoJitInfo*, copy_jit_info_data.size); + if (copy_jit_info_data.jit_info_array) { + jit_mm_lock (jit_mm); + mono_internal_hash_table_apply (&jit_mm->interp_code_hash, interp_copy_jit_info_func, ©_jit_info_data); + jit_mm_unlock (jit_mm); + } + + if (copy_jit_info_data.jit_info_array) { + for (size_t i = 0; i < copy_jit_info_data.next; ++i) + func (copy_jit_info_data.jit_info_array [i], user_data); + g_free (copy_jit_info_data.jit_info_array); + } } static void diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 04ff11b2124c18..9ef942e9d1b25a 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -85,6 +85,7 @@ OPDEF(MINT_LDSFLD_R4, "ldsfld.r4", 4, 1, 0, MintOpUShortInt) OPDEF(MINT_LDSFLD_R8, "ldsfld.r8", 4, 1, 0, MintOpUShortInt) OPDEF(MINT_LDSFLD_O, "ldsfld.o", 4, 1, 0, MintOpUShortInt) OPDEF(MINT_LDSFLD_VT, "ldsfld.vt", 5, 1, 0, MintOpTwoShorts) +OPDEF(MINT_LDSFLD_W, "ldsfld.w", 8, 1, 0, MintOpTwoInts) OPDEF(MINT_STSFLD_I1, "stsfld.i1", 4, 0, 1, MintOpUShortInt) OPDEF(MINT_STSFLD_U1, "stsfld.u1", 4, 0, 1, MintOpUShortInt) @@ -96,6 +97,7 @@ OPDEF(MINT_STSFLD_R4, "stsfld.r4", 4, 0, 1, MintOpUShortInt) OPDEF(MINT_STSFLD_R8, "stsfld.r8", 4, 0, 1, MintOpUShortInt) OPDEF(MINT_STSFLD_O, "stsfld.o", 4, 0, 1, MintOpUShortInt) OPDEF(MINT_STSFLD_VT, "stsfld.vt", 5, 0, 1, MintOpTwoShorts) +OPDEF(MINT_STSFLD_W, "stsfld.w", 8, 0, 1, MintOpTwoInts) OPDEF(MINT_LDSFLDA, "ldsflda", 4, 1, 0, MintOpTwoShorts) OPDEF(MINT_LDTSFLDA, "ldtsflda", 4, 1, 0, MintOpInt) diff --git a/src/mono/mono/mini/interp/mintops.h b/src/mono/mono/mini/interp/mintops.h index 82c78ac9243bfa..6de5e8c4ec0a05 100644 --- a/src/mono/mono/mini/interp/mintops.h +++ b/src/mono/mono/mini/interp/mintops.h @@ -23,6 +23,7 @@ typedef enum MintOpFieldToken, MintOpClassToken, MintOpTwoShorts, + MintOpTwoInts, MintOpShortAndInt, MintOpShortAndShortBranch, MintOpPair2, diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 952cfa5dd0cbba..577b6a23b27e39 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1093,11 +1093,11 @@ store_local (TransformData *td, int local) td->last_ins->data [0] = td->locals [local].size; } -static guint16 -get_data_item_index (TransformData *td, void *ptr) +static guint32 +get_data_item_wide_index (TransformData *td, void *ptr) { gpointer p = g_hash_table_lookup (td->data_hash, ptr); - guint index; + guint32 index; if (p != NULL) return GPOINTER_TO_UINT (p) - 1; if (td->max_data_items == td->n_data_items) { @@ -1111,6 +1111,20 @@ get_data_item_index (TransformData *td, void *ptr) return index; } +static guint16 +get_data_item_index (TransformData *td, void *ptr) +{ + guint32 index = get_data_item_wide_index (td, ptr); + g_assertf (index <= G_MAXUINT16, "Interpreter data item index 0x%x for method '%s' overflows", index, td->method->name); + return (guint16)index; +} + +static gboolean +is_data_item_wide_index (guint32 data_item_index) +{ + return data_item_index > G_MAXUINT16; +} + static guint16 get_data_item_index_nonshared (TransformData *td, void *ptr) { @@ -1347,6 +1361,9 @@ dump_interp_ins_data (InterpInst *ins, gint32 ins_offset, const guint16 *data, g case MintOpTwoShorts: g_string_append_printf (str, " %u,%u", *(guint16*)data, *(guint16 *)(data + 1)); break; + case MintOpTwoInts: + g_string_append_printf (str, " %u,%u", (guint32)READ32(data), (guint32)READ32(data + 2)); + break; case MintOpShortAndInt: g_string_append_printf (str, " %u,%u", *(guint16*)data, (guint32)READ32(data + 1)); break; @@ -1439,25 +1456,27 @@ dump_interp_compacted_ins (const guint16 *ip, const guint16 *start) { int opcode = *ip; int ins_offset = ip - start; + GString *str = g_string_new (""); - g_print ("IR_%04x: %-14s", ins_offset, mono_interp_opname (opcode)); + g_string_append_printf (str, "IR_%04x: %-14s", ins_offset, mono_interp_opname (opcode)); ip++; if (mono_interp_op_dregs [opcode] > 0) - g_print (" [%d <-", *ip++); + g_string_append_printf (str, " [%d <-", *ip++); else - g_print (" [nil <-"); + g_string_append_printf (str, " [nil <-"); if (mono_interp_op_sregs [opcode] > 0) { for (int i = 0; i < mono_interp_op_sregs [opcode]; i++) - g_print (" %d", *ip++); - g_print ("],"); + g_string_append_printf (str, " %d", *ip++); + g_string_append_printf (str, "],"); } else { - g_print (" nil],"); + g_string_append_printf (str, " nil],"); } - char *ins = dump_interp_ins_data (NULL, ins_offset, ip, opcode); - g_print ("%s\n", ins); - g_free (ins); + char *ins_data = dump_interp_ins_data (NULL, ins_offset, ip, opcode); + g_print ("%s%s\n", str->str, ins_data); + g_string_free (str, TRUE); + g_free (ins_data); } static void @@ -1471,51 +1490,47 @@ dump_interp_code (const guint16 *start, const guint16* end) } static void -dump_interp_inst_no_newline (InterpInst *ins) +dump_interp_inst (InterpInst *ins) { int opcode = ins->opcode; - g_print ("IL_%04x: %-14s", ins->il_offset, mono_interp_opname (opcode)); + GString *str = g_string_new (""); + g_string_append_printf (str, "IL_%04x: %-14s", ins->il_offset, mono_interp_opname (opcode)); if (mono_interp_op_dregs [opcode] > 0) - g_print (" [%d <-", ins->dreg); + g_string_append_printf (str, " [%d <-", ins->dreg); else - g_print (" [nil <-"); + g_string_append_printf (str, " [nil <-"); if (mono_interp_op_sregs [opcode] > 0) { for (int i = 0; i < mono_interp_op_sregs [opcode]; i++) { if (ins->sregs [i] == MINT_CALL_ARGS_SREG) { - g_print (" c:"); + g_string_append_printf (str, " c:"); int *call_args = ins->info.call_args; if (call_args) { while (*call_args != -1) { - g_print (" %d", *call_args); + g_string_append_printf (str, " %d", *call_args); call_args++; } } } else { - g_print (" %d", ins->sregs [i]); + g_string_append_printf (str, " %d", ins->sregs [i]); } } - g_print ("],"); + g_string_append_printf (str, "],"); } else { - g_print (" nil],"); + g_string_append_printf (str, " nil],"); } if (opcode == MINT_LDLOCA_S) { // LDLOCA has special semantics, it has data in sregs [0], but it doesn't have any sregs - g_print (" %d", ins->sregs [0]); + g_string_append_printf (str, " %d", ins->sregs [0]); } else { char *descr = dump_interp_ins_data (ins, ins->il_offset, &ins->data [0], ins->opcode); - g_print ("%s", descr); + g_string_append_printf (str, "%s", descr); g_free (descr); } -} - -static void -dump_interp_inst (InterpInst *ins) -{ - dump_interp_inst_no_newline (ins); - g_print ("\n"); + g_print ("%s\n", str->str); + g_string_free (str, TRUE); } static G_GNUC_UNUSED void @@ -1574,21 +1589,6 @@ interp_method_get_header (MonoMethod* method, MonoError *error) return mono_method_get_header_internal (method, error); } -/* stores top of stack as local and pushes address of it on stack */ -static void -emit_store_value_as_local (TransformData *td, MonoType *src) -{ - int local = create_interp_local (td, mini_native_type_replace_type (src)); - - store_local (td, local); - - interp_add_ins (td, MINT_LDLOCA_S); - push_simple_type (td, STACK_TYPE_MP); - interp_ins_set_dreg (td->last_ins, td->sp [-1].local); - interp_ins_set_sreg (td->last_ins, local); - td->locals [local].indirects++; -} - static gboolean interp_ip_in_cbb (TransformData *td, int il_offset) { @@ -1899,15 +1899,15 @@ interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_metho int src_size = mini_magic_type_size (NULL, src); int dst_size = mini_magic_type_size (NULL, dst); - gboolean store_value_as_local = FALSE; + gboolean managed_fallback = FALSE; switch (type_index) { case 0: case 1: if (!mini_magic_is_int_type (src) || !mini_magic_is_int_type (dst)) { if (mini_magic_is_int_type (src)) - store_value_as_local = TRUE; + managed_fallback = TRUE; else if (mono_class_is_magic_float (src_klass)) - store_value_as_local = TRUE; + managed_fallback = TRUE; else return FALSE; } @@ -1915,21 +1915,17 @@ interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_metho case 2: if (!mini_magic_is_float_type (src) || !mini_magic_is_float_type (dst)) { if (mini_magic_is_float_type (src)) - store_value_as_local = TRUE; + managed_fallback = TRUE; else if (mono_class_is_magic_int (src_klass)) - store_value_as_local = TRUE; + managed_fallback = TRUE; else return FALSE; } break; } - if (store_value_as_local) { - emit_store_value_as_local (td, src); - - /* emit call to managed conversion method */ + if (managed_fallback) return FALSE; - } if (src_size > dst_size) { // 8 -> 4 switch (type_index) { @@ -1986,15 +1982,6 @@ interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_metho td->ip += 5; return TRUE; } else if (!strcmp ("CompareTo", tm) || !strcmp ("Equals", tm)) { - MonoType *arg = csignature->params [0]; - int mt = mint_type (arg); - - /* on 'System.n*::{CompareTo,Equals} (System.n*)' variant we need to push managed - * pointer instead of value */ - if (mt != MINT_TYPE_O) - emit_store_value_as_local (td, arg); - - /* emit call to managed conversion method */ return FALSE; } else if (!strcmp (".cctor", tm)) { return FALSE; @@ -2436,7 +2423,7 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas if (!strcmp (tm, "InternalGetHashCode")) { *op = MINT_INTRINS_GET_HASHCODE; } else if (!strcmp (tm, "GetType")) { - if (constrained_class && m_class_is_valuetype (constrained_class)) { + if (constrained_class && m_class_is_valuetype (constrained_class) && !mono_class_is_nullable (constrained_class)) { // If constrained_class is valuetype we already know its type. // Resolve GetType to a constant so we can fold type comparisons ERROR_DECL(error); @@ -2453,8 +2440,16 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas return TRUE; } else { if (constrained_class) { - // deref the managed pointer to get the object - interp_add_ins (td, MINT_LDIND_I); + if (mono_class_is_nullable (constrained_class)) { + // We can't determine the behavior here statically because we don't know if the + // nullable vt has a value or not. If it has a value, the result type is + // m_class_get_cast_class (constrained_class), otherwise GetType should throw NRE. + interp_add_ins (td, MINT_BOX_NULLABLE_PTR); + td->last_ins->data [0] = get_data_item_index (td, constrained_class); + } else { + // deref the managed pointer to get the object + interp_add_ins (td, MINT_LDIND_I); + } td->sp--; interp_ins_set_sreg (td->last_ins, td->sp [0].local); push_simple_type (td, STACK_TYPE_O); @@ -2823,8 +2818,7 @@ interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodS if (method->wrapper_type != MONO_WRAPPER_NONE) return FALSE; - /* Our usage of `emit_store_value_as_local ()` for nint, nuint and nfloat - * is kinda hacky, and doesn't work with the inliner */ + // FIXME Re-enable this if (mono_class_get_magic_index (method->klass) >= 0) return FALSE; @@ -4199,7 +4193,20 @@ interp_emit_sfld_access (TransformData *td, MonoClassField *field, MonoClass *fi if (interp_emit_load_const (td, field_addr, mt)) return; } - if (mt == MINT_TYPE_VT) { + } + guint32 vtable_index = get_data_item_wide_index (td, vtable); + guint32 addr_index = get_data_item_wide_index (td, (char*)field_addr); + gboolean wide_data = is_data_item_wide_index (vtable_index) || is_data_item_wide_index (addr_index); + guint32 klass_index = !wide_data ? 0 : get_data_item_wide_index (td, field_class); + if (is_load) { + if (G_UNLIKELY (wide_data)) { + interp_add_ins (td, MINT_LDSFLD_W); + if (mt == MINT_TYPE_VT) { + push_type_vt (td, field_class, size); + } else { + push_type (td, stack_type [mt], field_class); + } + } else if (mt == MINT_TYPE_VT) { interp_add_ins (td, MINT_LDSFLD_VT); push_type_vt (td, field_class, size); } else { @@ -4208,15 +4215,24 @@ interp_emit_sfld_access (TransformData *td, MonoClassField *field, MonoClass *fi } interp_ins_set_dreg (td->last_ins, td->sp [-1].local); } else { - interp_add_ins (td, (mt == MINT_TYPE_VT) ? MINT_STSFLD_VT : (MINT_STSFLD_I1 + mt - MINT_TYPE_I1)); + if (G_LIKELY (!wide_data)) + interp_add_ins (td, (mt == MINT_TYPE_VT) ? MINT_STSFLD_VT : (MINT_STSFLD_I1 + mt - MINT_TYPE_I1)); + else + interp_add_ins (td, MINT_STSFLD_W); td->sp--; interp_ins_set_sreg (td->last_ins, td->sp [0].local); } - td->last_ins->data [0] = get_data_item_index (td, vtable); - td->last_ins->data [1] = get_data_item_index (td, (char*)field_addr); - if (mt == MINT_TYPE_VT) - td->last_ins->data [2] = size; + if (G_LIKELY (!wide_data)) { + td->last_ins->data [0] = (guint16) vtable_index; + td->last_ins->data [1] = (guint16) addr_index; + if (mt == MINT_TYPE_VT) + td->last_ins->data [2] = size; + } else { + WRITE32_INS (td->last_ins, 0, &vtable_index); + WRITE32_INS (td->last_ins, 2, &addr_index); + WRITE32_INS (td->last_ins, 4, &klass_index); + } } } @@ -4389,6 +4405,9 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, end = td->ip + header->code_size; td->cbb = td->entry_bb = (InterpBasicBlock*)mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock)); + if (td->gen_sdb_seq_points) + td->basic_blocks = g_list_prepend_mempool (td->mempool, td->basic_blocks, td->cbb); + td->cbb->index = td->bb_count++; td->cbb->native_offset = -1; td->cbb->stack_height = td->sp - td->stack; @@ -5989,6 +6008,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, td->sp--; interp_emit_sfld_access (td, field, field_klass, mt, TRUE, error); goto_if_nok (error, exit); + } else if (td->sp [-1].type != STACK_TYPE_O && td->sp [-1].type != STACK_TYPE_MP && (mono_class_is_magic_int (klass) || mono_class_is_magic_float (klass))) { + // No need to load anything, the value is already on the execution stack } else if (td->sp [-1].type == STACK_TYPE_VT) { int size = 0; /* First we pop the vt object from the stack. Then we push the field */ @@ -9288,8 +9309,8 @@ interp_alloc_offsets (TransformData *td) if (ins->flags & INTERP_INST_FLAG_CALL) { int *call_args = ins->info.call_args; if (call_args) { - int pair_sregs [MINT_MOV_PAIRS_MAX]; - int pair_dregs [MINT_MOV_PAIRS_MAX]; + guint16 pair_sregs [MINT_MOV_PAIRS_MAX]; + guint16 pair_dregs [MINT_MOV_PAIRS_MAX]; int num_pairs = 0; int var = *call_args; @@ -9303,9 +9324,10 @@ interp_alloc_offsets (TransformData *td) td->locals [new_var].flags |= INTERP_LOCAL_FLAG_CALL_ARGS; int mt = mint_type (td->locals [var].type); - if (mt != MINT_TYPE_VT && num_pairs < MINT_MOV_PAIRS_MAX) { - pair_sregs [num_pairs] = var; - pair_dregs [num_pairs] = new_var; + if (mt != MINT_TYPE_VT && num_pairs < MINT_MOV_PAIRS_MAX && var <= G_MAXUINT16 && new_var <= G_MAXUINT16) { + // We store these in the instruction data slots so we do this optimizations only if they fit + pair_sregs [num_pairs] = (guint16)var; + pair_dregs [num_pairs] = (guint16)new_var; num_pairs++; // The arg of the call is no longer global *call_args = new_var; diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index f91a8a659b5c80..8b4db42b078b4f 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -1810,12 +1810,14 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign ins->type = STACK_I4; MONO_ADD_INS (cfg->cbb, ins); return ins; - } else if (((!strcmp (cmethod_klass_image->assembly->aname.name, "MonoMac") || - !strcmp (cmethod_klass_image->assembly->aname.name, "monotouch")) && - !strcmp (cmethod_klass_name_space, "XamCore.ObjCRuntime") && - !strcmp (cmethod_klass_name, "Selector")) || - ((!strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.iOS") || - !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.Mac")) && + } else if (((!strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.iOS") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.TVOS") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.MacCatalyst") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Xamarin.Mac") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.iOS") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.tvOS") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.MacCatalyst") || + !strcmp (cmethod_klass_image->assembly->aname.name, "Microsoft.macOS")) && !strcmp (cmethod_klass_name_space, "ObjCRuntime") && !strcmp (cmethod_klass_name, "Selector")) ) { diff --git a/src/mono/mono/mini/jit-icalls.c b/src/mono/mono/mini/jit-icalls.c index 84b800d69e6c4b..49cd2e73d5a047 100644 --- a/src/mono/mono/mini/jit-icalls.c +++ b/src/mono/mono/mini/jit-icalls.c @@ -868,6 +868,7 @@ mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *me return mono_ldtoken_wrapper (image, token, generic_context); } +#ifdef MONO_ARCH_EMULATE_FCONV_TO_U8 guint64 mono_fconv_u8 (double v) { @@ -885,18 +886,6 @@ mono_fconv_u8 (double v) #endif } -#ifdef MONO_ARCH_EMULATE_FCONV_TO_U8 -guint64 -mono_fconv_u8_2 (double v) -{ - // Separate from mono_fconv_u8 to avoid duplicate JIT icall. - // - // When there are duplicates, there is single instancing - // against function address that breaks stuff. For example, - // wrappers are only produced for one of them, breaking FullAOT. - return mono_fconv_u8 (v); -} - guint64 mono_rconv_u8 (float v) { @@ -923,6 +912,7 @@ mono_fconv_i8 (double v) } #endif +#ifdef MONO_ARCH_EMULATE_FCONV_TO_U4 guint32 mono_fconv_u4 (double v) { @@ -932,18 +922,6 @@ mono_fconv_u4 (double v) return (guint32)v; } -#ifdef MONO_ARCH_EMULATE_FCONV_TO_U4 -guint32 -mono_fconv_u4_2 (double v) -{ - // Separate from mono_fconv_u4 to avoid duplicate JIT icall. - // - // When there are duplicates, there is single instancing - // against function address that breaks stuff. For example, - // wrappers are only produced for one of them, breaking FullAOT. - return mono_fconv_u4 (v); -} - guint32 mono_rconv_u4 (float v) { diff --git a/src/mono/mono/mini/jit-icalls.h b/src/mono/mono/mini/jit-icalls.h index 86b96a7612f52e..6a7c969710ded4 100644 --- a/src/mono/mono/mini/jit-icalls.h +++ b/src/mono/mono/mini/jit-icalls.h @@ -73,14 +73,12 @@ ICALL_EXPORT gpointer mono_ldtoken_wrapper (MonoImage *image, int token, MonoGen ICALL_EXPORT gpointer mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method); ICALL_EXPORT guint64 mono_fconv_u8 (double v); -ICALL_EXPORT guint64 mono_fconv_u8_2 (double v); ICALL_EXPORT guint64 mono_rconv_u8 (float v); ICALL_EXPORT gint64 mono_fconv_i8 (double v); ICALL_EXPORT guint32 mono_fconv_u4 (double v); -ICALL_EXPORT guint32 mono_fconv_u4_2 (double v); ICALL_EXPORT guint32 mono_rconv_u4 (float v); diff --git a/src/mono/mono/mini/local-propagation.c b/src/mono/mono/mini/local-propagation.c index 3bd878e66b56a0..19801edd1f2814 100644 --- a/src/mono/mono/mini/local-propagation.c +++ b/src/mono/mono/mini/local-propagation.c @@ -223,7 +223,7 @@ mono_strength_reduction_division (MonoCompile *cfg, MonoInst *ins) guint32 tmp_regi; #endif struct magic_signed mag; - int power2 = mono_is_power_of_two (ins->inst_imm); + int power2 = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1; /* The decomposition doesn't handle exception throwing */ /* Optimization with MUL does not apply for -1, 0 and 1 divisors */ if (ins->inst_imm == 0 || ins->inst_imm == -1) { @@ -350,7 +350,7 @@ mono_strength_reduction_ins (MonoCompile *cfg, MonoInst *ins, const char **spec) ins->opcode = OP_INEG; } else if ((ins->opcode == OP_LMUL_IMM) && (ins->inst_imm == -1)) { ins->opcode = OP_LNEG; - } else { + } else if (ins->inst_imm > 0) { int power2 = mono_is_power_of_two (ins->inst_imm); if (power2 >= 0) { ins->opcode = (ins->opcode == OP_MUL_IMM) ? OP_SHL_IMM : ((ins->opcode == OP_LMUL_IMM) ? OP_LSHL_IMM : OP_ISHL_IMM); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 5b607e55636ead..0d2fee12d1e219 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -1149,7 +1149,10 @@ type_from_op (MonoCompile *cfg, MonoInst *ins, MonoInst *src1, MonoInst *src2) ins->opcode = OP_LCONV_TO_U; break; case STACK_R8: - ins->opcode = OP_FCONV_TO_U; + if (TARGET_SIZEOF_VOID_P == 8) + ins->opcode = OP_FCONV_TO_U8; + else + ins->opcode = OP_FCONV_TO_U4; break; case STACK_R4: if (TARGET_SIZEOF_VOID_P == 8) @@ -5324,20 +5327,20 @@ handle_call_res_devirt (MonoCompile *cfg, MonoMethod *cmethod, MonoInst *call_re MonoClass *gcomparer = mono_class_get_geqcomparer_class (); g_assert (gcomparer); gcomparer_inst = mono_class_inflate_generic_class_checked (gcomparer, &ctx, error); - mono_error_assert_ok (error); + if (is_ok (error)) { + MONO_INST_NEW (cfg, typed_objref, OP_TYPED_OBJREF); + typed_objref->type = STACK_OBJ; + typed_objref->dreg = alloc_ireg_ref (cfg); + typed_objref->sreg1 = call_res->dreg; + typed_objref->klass = gcomparer_inst; + MONO_ADD_INS (cfg->cbb, typed_objref); - MONO_INST_NEW (cfg, typed_objref, OP_TYPED_OBJREF); - typed_objref->type = STACK_OBJ; - typed_objref->dreg = alloc_ireg_ref (cfg); - typed_objref->sreg1 = call_res->dreg; - typed_objref->klass = gcomparer_inst; - MONO_ADD_INS (cfg->cbb, typed_objref); + call_res = typed_objref; - call_res = typed_objref; - - /* Force decompose */ - cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE; - cfg->cbb->needs_decompose = TRUE; + /* Force decompose */ + cfg->flags |= MONO_CFG_NEEDS_DECOMPOSE; + cfg->cbb->needs_decompose = TRUE; + } } } @@ -6080,6 +6083,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b seq_points = FALSE; } + if (method->wrapper_type == MONO_WRAPPER_OTHER) { + WrapperInfo *info = mono_marshal_get_wrapper_info (method); + if (info->subtype == WRAPPER_SUBTYPE_INTERP_IN) { + /* We could hit a seq point before attaching to the JIT (#8338) */ + seq_points = FALSE; + } + } + if (cfg->prof_coverage) { if (cfg->compile_aot) g_error ("Coverage profiling is not supported with AOT."); @@ -7314,13 +7325,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b sp -= n; - if (virtual_ && cmethod && sp [0]->opcode == OP_TYPED_OBJREF) { + if (virtual_ && cmethod && sp [0] && sp [0]->opcode == OP_TYPED_OBJREF) { ERROR_DECL (error); MonoMethod *new_cmethod = mono_class_get_virtual_method (sp [0]->klass, cmethod, error); - mono_error_assert_ok (error); - cmethod = new_cmethod; - virtual_ = FALSE; + if (is_ok (error)) { + cmethod = new_cmethod; + virtual_ = FALSE; + } else { + mono_error_cleanup (error); + } } if (cmethod && method_does_not_return (cmethod)) { diff --git a/src/mono/mono/mini/mini-arm.c b/src/mono/mono/mini/mini-arm.c index 58c0cef04842e9..59170bd09e8a5b 100644 --- a/src/mono/mono/mini/mini-arm.c +++ b/src/mono/mono/mini/mini-arm.c @@ -3466,7 +3466,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_c0 = 0; break; } - imm8 = mono_is_power_of_two (ins->inst_imm); + imm8 = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1; if (imm8 > 0) { ins->opcode = OP_SHL_IMM; ins->inst_imm = imm8; @@ -5685,7 +5685,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE); break; case OP_FCONV_TO_U4: - case OP_FCONV_TO_U: code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE); break; case OP_FCONV_TO_I8: diff --git a/src/mono/mono/mini/mini-llvm.c b/src/mono/mono/mini/mini-llvm.c index ada72e46a90afd..f75792659d49dd 100644 --- a/src/mono/mono/mini/mini-llvm.c +++ b/src/mono/mono/mini/mini-llvm.c @@ -529,23 +529,27 @@ ThisType (void) return TARGET_SIZEOF_VOID_P == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0); } +typedef struct { + int32_t size; + uint32_t align; +} MonoSizeAlign; + /* * get_vtype_size: * * Return the size of the LLVM representation of the vtype T. */ -static guint32 -get_vtype_size (MonoType *t) +static MonoSizeAlign +get_vtype_size_align (MonoType *t) { - int size; - - size = mono_class_value_size (mono_class_from_mono_type_internal (t), NULL); + uint32_t align = 0; + int32_t size = mono_class_value_size (mono_class_from_mono_type_internal (t), &align); /* LLVMArgAsIArgs depends on this since it stores whole words */ while (size < 2 * TARGET_SIZEOF_VOID_P && mono_is_power_of_two (size) == -1) size ++; - - return size; + MonoSizeAlign ret = { size, align }; + return ret; } /* @@ -680,11 +684,17 @@ create_llvm_type_for_type (MonoLLVMModule *module, MonoClass *klass) for (i = 0; i < size; ++i) eltypes [i] = esize == 4 ? LLVMFloatType () : LLVMDoubleType (); } else { - size = get_vtype_size (t); - - eltypes = g_new (LLVMTypeRef, size); - for (i = 0; i < size; ++i) - eltypes [i] = LLVMInt8Type (); + MonoSizeAlign size_align = get_vtype_size_align (t); + eltypes = g_new (LLVMTypeRef, size_align.size); + size = 0; + uint32_t bytes = 0; + uint32_t chunk = size_align.align < TARGET_SIZEOF_VOID_P ? size_align.align : TARGET_SIZEOF_VOID_P; + for (; chunk > 0; chunk = chunk >> 1) { + for (; (bytes + chunk) <= size_align.size; bytes += chunk) { + eltypes [size] = LLVMIntType (chunk * 8); + ++size; + } + } } name = mono_type_full_name (m_class_get_byval_arg (klass)); @@ -965,7 +975,6 @@ op_to_llvm_type (int opcode) case OP_RCONV_TO_U8: return LLVMInt64Type (); case OP_FCONV_TO_I: - case OP_FCONV_TO_U: return TARGET_SIZEOF_VOID_P == 8 ? LLVMInt64Type () : LLVMInt32Type (); case OP_IADD_OVF: case OP_IADD_OVF_UN: @@ -2671,11 +2680,11 @@ static void emit_vtype_to_args (EmitContext *ctx, LLVMBuilderRef builder, MonoType *t, LLVMValueRef address, LLVMArgInfo *ainfo, LLVMValueRef *args, guint32 *nargs) { int pindex = 0; - int j, size, nslots; + int j, nslots; LLVMTypeRef arg_type; t = mini_get_underlying_type (t); - size = get_vtype_size (t); + int32_t size = get_vtype_size_align (t).size; if (MONO_CLASS_IS_SIMD (ctx->cfg, mono_class_from_mono_type_internal (t))) address = LLVMBuildBitCast (ctx->builder, address, LLVMPointerType (LLVMInt8Type (), 0), ""); @@ -7341,7 +7350,7 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) } else if (ainfo->storage == LLVMArgVtypeAddr || values [ins->sreg1] == addresses [ins->sreg1]) { /* LLVMArgVtypeByRef/LLVMArgVtypeAddr, have to make a copy */ addresses [ins->dreg] = build_alloca (ctx, t); - LLVMValueRef v = LLVMBuildLoad (builder, addresses [ins->sreg1], ""); + LLVMValueRef v = LLVMBuildLoad (builder, addresses [ins->sreg1], "llvm_outarg_vt_copy"); LLVMBuildStore (builder, convert (ctx, v, type_to_llvm_type (ctx, t)), addresses [ins->dreg]); } else { addresses [ins->dreg] = addresses [ins->sreg1]; @@ -11473,7 +11482,7 @@ emit_method_inner (EmitContext *ctx) mono_llvm_add_func_attr (method, LLVM_ATTR_UW_TABLE); if (cfg->disable_omit_fp) - mono_llvm_add_func_attr_nv (method, "no-frame-pointer-elim", "true"); + mono_llvm_add_func_attr_nv (method, "frame-pointer", "all"); if (cfg->compile_aot) { if (mono_aot_is_externally_callable (cfg->method)) { diff --git a/src/mono/mono/mini/mini-mips.c b/src/mono/mono/mini/mini-mips.c index 9a353ce85fa1ea..01dc86ce28ea91 100644 --- a/src/mono/mono/mini/mini-mips.c +++ b/src/mono/mono/mini/mini-mips.c @@ -1987,7 +1987,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) MONO_DELETE_INS (bb, ins); continue; } - } else { + } else if (ins->inst_imm > 0) { int power2 = mono_is_power_of_two (ins->inst_imm); if (power2 > 0) { ins->opcode = OP_SHL_IMM; @@ -2666,7 +2666,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_c0 = 0; break; } - imm = mono_is_power_of_two (ins->inst_imm); + imm = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1; if (imm > 0) { ins->opcode = OP_SHL_IMM; ins->inst_imm = imm; @@ -4270,7 +4270,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE); break; case OP_FCONV_TO_U4: - case OP_FCONV_TO_U: code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE); break; case OP_SQRT: diff --git a/src/mono/mono/mini/mini-native-types.c b/src/mono/mono/mini/mini-native-types.c index 08f72acafe6840..6c7e6ffb1a8528 100644 --- a/src/mono/mono/mini/mini-native-types.c +++ b/src/mono/mono/mini/mini-native-types.c @@ -372,6 +372,16 @@ mono_class_is_magic_assembly (MonoClass *klass) return TRUE; if (!strcmp ("Xamarin.WatchOS", aname)) return TRUE; + if (!strcmp ("Xamarin.MacCatalyst", aname)) + return TRUE; + if (!strcmp ("Microsoft.iOS", aname)) + return TRUE; + if (!strcmp ("Microsoft.macOS", aname)) + return TRUE; + if (!strcmp ("Microsoft.watchOS", aname)) + return TRUE; + if (!strcmp ("Microsoft.MacCatalyst", aname)) + return TRUE; /* regression test suite */ if (!strcmp ("builtin-types", aname)) return TRUE; @@ -427,7 +437,7 @@ mono_class_is_magic_float (MonoClass *klass) if (!mono_class_is_magic_assembly (klass)) return FALSE; - if (strcmp ("System", m_class_get_name_space (klass)) != 0) + if (strcmp ("System", m_class_get_name_space (klass)) != 0 && strcmp ("ObjCRuntime", m_class_get_name_space (klass)) != 0) return FALSE; if (strcmp ("nfloat", m_class_get_name (klass)) == 0) { diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h index ed2d11d563a08c..9cfb59cdb4fbe1 100644 --- a/src/mono/mono/mini/mini-ops.h +++ b/src/mono/mono/mini/mini-ops.h @@ -583,7 +583,6 @@ MINI_OP(OP_FCGT_UN_MEMBASE,"float_cgt_un_membase", IREG, FREG, IREG) MINI_OP(OP_FCLT_MEMBASE, "float_clt_membase", IREG, FREG, IREG) MINI_OP(OP_FCLT_UN_MEMBASE,"float_clt_un_membase", IREG, FREG, IREG) -MINI_OP(OP_FCONV_TO_U, "float_conv_to_u", IREG, FREG, NONE) MINI_OP(OP_CKFINITE, "ckfinite", FREG, FREG, NONE) /* r4 opcodes: must be in the same order as the matching CEE_ opcodes: ovfops_op_map */ diff --git a/src/mono/mono/mini/mini-ppc.c b/src/mono/mono/mini/mini-ppc.c index 19097c9df89d91..112abb168bfe96 100644 --- a/src/mono/mono/mini/mini-ppc.c +++ b/src/mono/mono/mini/mini-ppc.c @@ -1963,7 +1963,7 @@ mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb) MONO_DELETE_INS (bb, ins); continue; } - } else { + } else if (inst->inst_imm > 0) { int power2 = mono_is_power_of_two (ins->inst_imm); if (power2 > 0) { ins->opcode = OP_SHL_IMM; @@ -2537,7 +2537,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb) ins->inst_c0 = 0; break; } - imm = mono_is_power_of_two (ins->inst_imm); + imm = (ins->inst_imm > 0) ? mono_is_power_of_two (ins->inst_imm) : -1; if (imm > 0) { ins->opcode = OP_SHL_IMM; ins->inst_imm = imm; @@ -4163,7 +4163,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE); break; case OP_FCONV_TO_U4: - case OP_FCONV_TO_U: code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE); break; case OP_LCONV_TO_R_UN: diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 2ca296b1fd60b5..d609531e6b948b 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -2999,6 +2999,8 @@ typedef struct { gpointer *wrapper_arg; } RuntimeInvokeInfo; +#define MONO_SIZEOF_DYN_CALL_RET_BUF TARGET_SIZEOF_VOID_P + static RuntimeInvokeInfo* create_runtime_invoke_info (MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, gboolean use_interp, MonoError *error) { @@ -3157,8 +3159,8 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void { MonoMethodSignature *sig = info->sig; MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method); - gpointer retval_ptr; - guint8 retval [256]; + int32_t retval_size = MONO_SIZEOF_DYN_CALL_RET_BUF; + gpointer retval = NULL; int i, pindex; error_init (error); @@ -3185,8 +3187,21 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (sig->hasthis) args [pindex ++] = &obj; if (sig->ret->type != MONO_TYPE_VOID) { - retval_ptr = &retval; - args [pindex ++] = &retval_ptr; + if (info->ret_box_class && !sig->ret->byref && + (sig->ret->type == MONO_TYPE_VALUETYPE || + (sig->ret->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (sig->ret)))) { + // if the return type is a struct, allocate enough stack space to hold it + MonoClass *ret_klass = mono_class_from_mono_type_internal (sig->ret); + g_assert (!mono_class_has_failure (ret_klass)); + int32_t inst_size = mono_class_instance_size (ret_klass); + if (inst_size > MONO_SIZEOF_DYN_CALL_RET_BUF) { + retval_size = inst_size; + } + } + } + retval = g_alloca (retval_size); + if (sig->ret->type != MONO_TYPE_VOID) { + args [pindex ++] = &retval; } for (i = 0; i < sig->param_count; ++i) { MonoType *t = sig->params [i]; @@ -3235,7 +3250,8 @@ mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void if (sig->ret->byref) { return mono_value_box_checked (info->ret_box_class, *(gpointer*)retval, error); } else { - return mono_value_box_checked (info->ret_box_class, retval, error); + MonoObject *ret = mono_value_box_checked (info->ret_box_class, retval, error); + return ret; } } else { if (sig->ret->byref) @@ -3398,7 +3414,22 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec gpointer *args; int i, pindex, buf_size; guint8 *buf; - guint8 retval [256]; + int32_t retval_size = MONO_SIZEOF_DYN_CALL_RET_BUF; + guint8 *retval = NULL; + + /* if the return type is a struct and it's too big, allocate more space for it */ + if (info->ret_box_class && !sig->ret->byref && + (sig->ret->type == MONO_TYPE_VALUETYPE || + (sig->ret->type == MONO_TYPE_GENERICINST && !MONO_TYPE_IS_REFERENCE (sig->ret)))) { + MonoClass *ret_klass = mono_class_from_mono_type_internal (sig->ret); + g_assert (!mono_class_has_failure (ret_klass)); + int32_t inst_size = mono_class_instance_size (ret_klass); + if (inst_size > MONO_SIZEOF_DYN_CALL_RET_BUF) { + retval_size = inst_size; + } + } + + retval = g_alloca (retval_size); /* Convert the arguments to the format expected by start_dyn_call () */ args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer)); @@ -3434,10 +3465,29 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec return NULL; } - if (info->ret_box_class) - return mono_value_box_checked (info->ret_box_class, retval, error); - else - return *(MonoObject**)retval; + if (sig->ret->byref) { + if (*(gpointer*)retval == NULL) { + MonoClass *klass = mono_class_get_nullbyrefreturn_ex_class (); + MonoObject *ex = mono_object_new_checked (klass, error); + mono_error_assert_ok (error); + mono_error_set_exception_instance (error, (MonoException*)ex); + return NULL; + } + } + + if (info->ret_box_class) { + if (sig->ret->byref) { + return mono_value_box_checked (info->ret_box_class, *(gpointer*)retval, error); + } else { + MonoObject *boxed_ret = mono_value_box_checked (info->ret_box_class, retval, error); + return boxed_ret; + } + } else { + if (sig->ret->byref) + return **(MonoObject***)retval; + else + return *(MonoObject**)retval; + } } #endif @@ -4697,11 +4747,11 @@ register_icalls (void) #endif #ifdef MONO_ARCH_EMULATE_FCONV_TO_U8 - register_opcode_emulation (OP_FCONV_TO_U8, __emul_fconv_to_u8, mono_icall_sig_ulong_double, mono_fconv_u8_2, FALSE); + register_opcode_emulation (OP_FCONV_TO_U8, __emul_fconv_to_u8, mono_icall_sig_ulong_double, mono_fconv_u8, FALSE); register_opcode_emulation (OP_RCONV_TO_U8, __emul_rconv_to_u8, mono_icall_sig_ulong_float, mono_rconv_u8, FALSE); #endif #ifdef MONO_ARCH_EMULATE_FCONV_TO_U4 - register_opcode_emulation (OP_FCONV_TO_U4, __emul_fconv_to_u4, mono_icall_sig_uint32_double, mono_fconv_u4_2, FALSE); + register_opcode_emulation (OP_FCONV_TO_U4, __emul_fconv_to_u4, mono_icall_sig_uint32_double, mono_fconv_u4, FALSE); register_opcode_emulation (OP_RCONV_TO_U4, __emul_rconv_to_u4, mono_icall_sig_uint32_float, mono_rconv_u4, FALSE); #endif register_opcode_emulation (OP_FCONV_TO_OVF_I8, __emul_fconv_to_ovf_i8, mono_icall_sig_long_double, mono_fconv_ovf_i8, FALSE); @@ -4779,13 +4829,6 @@ register_icalls (void) register_icall (mono_class_interface_match, mono_icall_sig_uint32_ptr_int32, TRUE); #endif - // FIXME Elsewhere these are registered with no_wrapper = FALSE -#if SIZEOF_REGISTER == 4 - register_opcode_emulation (OP_FCONV_TO_U, __emul_fconv_to_u, mono_icall_sig_uint32_double, mono_fconv_u4, TRUE); -#else - register_opcode_emulation (OP_FCONV_TO_U, __emul_fconv_to_u, mono_icall_sig_ulong_double, mono_fconv_u8, TRUE); -#endif - /* other jit icalls */ register_icall (ves_icall_mono_delegate_ctor, mono_icall_sig_void_object_object_ptr, FALSE); register_icall (ves_icall_mono_delegate_ctor_interp, mono_icall_sig_void_object_object_ptr, FALSE); diff --git a/src/mono/mono/mini/mini-s390x.c b/src/mono/mono/mini/mini-s390x.c index 5ad3edbef2c4a7..1c4789750f0269 100644 --- a/src/mono/mono/mini/mini-s390x.c +++ b/src/mono/mono/mini/mini-s390x.c @@ -4286,7 +4286,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_cfdbr (code, ins->dreg, 5, ins->sreg1); break; case OP_FCONV_TO_U4: - case OP_FCONV_TO_U: if (mono_hwcap_s390x_has_fpe) { s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0); } else { diff --git a/src/mono/mono/mini/mini-sparc.c b/src/mono/mono/mini/mini-sparc.c index 448f150c5505b8..01cbb979c48547 100644 --- a/src/mono/mono/mini/mini-sparc.c +++ b/src/mono/mono/mini/mini-sparc.c @@ -3395,7 +3395,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_FCONV_TO_U2: #ifndef SPARCV9 case OP_FCONV_TO_I: - case OP_FCONV_TO_U: #endif case OP_FCONV_TO_I4: case OP_FCONV_TO_U4: { diff --git a/src/mono/mono/mini/mini-trampolines.c b/src/mono/mono/mini/mini-trampolines.c index c6901fb339330d..07a50524a0feb2 100644 --- a/src/mono/mono/mini/mini-trampolines.c +++ b/src/mono/mono/mini/mini-trampolines.c @@ -554,7 +554,7 @@ common_call_trampoline (host_mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTa /* * The caller is gshared code, compute the actual method to call from M and this/rgctx. */ - if (m->is_inflated && mono_method_get_context (m)->method_inst) { + if (m->is_inflated && (mono_method_get_context (m)->method_inst || mini_method_is_default_method (m))) { MonoMethodRuntimeGenericContext *mrgctx = (MonoMethodRuntimeGenericContext*)mono_arch_find_static_call_vtable (regs, code); klass = mrgctx->class_vtable->klass; @@ -632,11 +632,13 @@ common_call_trampoline (host_mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTa return NULL; if (generic_virtual || variant_iface) { - if (m_class_is_valuetype (vt->klass)) /*FIXME is this required variant iface?*/ + if (m_class_is_valuetype (vt->klass) && !mini_method_is_default_method (m)) /*FIXME is this required variant iface?*/ need_unbox_tramp = TRUE; } else if (orig_vtable_slot) { - if (m_class_is_valuetype (m->klass)) + if (m_class_is_valuetype (m->klass)) { + g_assert (!mini_method_is_default_method (m)); need_unbox_tramp = TRUE; + } } addr = mini_add_method_trampoline (m, compiled_method, need_rgctx_tramp, need_unbox_tramp); diff --git a/src/mono/mono/profiler/CMakeLists.txt b/src/mono/mono/profiler/CMakeLists.txt index 784ceb0203d3d4..2b06ab374feb45 100644 --- a/src/mono/mono/profiler/CMakeLists.txt +++ b/src/mono/mono/profiler/CMakeLists.txt @@ -22,6 +22,10 @@ if(NOT DISABLE_LIBS) add_library(mono-profiler-log-static STATIC helper.c log.c log-args.c) set_target_properties(mono-profiler-log-static PROPERTIES OUTPUT_NAME mono-profiler-log) install(TARGETS mono-profiler-log-static LIBRARY) + + if(HAVE_SYS_ZLIB) + target_link_libraries(mono-profiler-log z) + endif() endif() add_library(mono-profiler-aot-static STATIC aot.c helper.c) diff --git a/src/mono/mono/sgen/sgen-cardtable.c b/src/mono/mono/sgen/sgen-cardtable.c index 120afe0d4ea2c9..31a25f47fd8fdc 100644 --- a/src/mono/mono/sgen/sgen-cardtable.c +++ b/src/mono/mono/sgen/sgen-cardtable.c @@ -594,9 +594,9 @@ sgen_cardtable_scan_object (GCObject *obj, mword block_obj_size, guint8 *cards, HEAVY_STAT (++bloby_objects); if (cards) { if (sgen_card_table_is_range_marked (cards, (mword)obj, block_obj_size)) - ctx.ops->scan_object (obj, sgen_obj_get_descriptor (obj), ctx.queue); + ctx.ops->scan_object (obj, sgen_obj_get_descriptor_safe (obj), ctx.queue); } else if (sgen_card_table_region_begin_scanning ((mword)obj, block_obj_size)) { - ctx.ops->scan_object (obj, sgen_obj_get_descriptor (obj), ctx.queue); + ctx.ops->scan_object (obj, sgen_obj_get_descriptor_safe (obj), ctx.queue); } sgen_binary_protocol_card_scan (obj, sgen_safe_object_get_size (obj)); diff --git a/src/mono/mono/sgen/sgen-marksweep.c b/src/mono/mono/sgen/sgen-marksweep.c index ca01a483e9d545..f767431c1699ee 100644 --- a/src/mono/mono/sgen/sgen-marksweep.c +++ b/src/mono/mono/sgen/sgen-marksweep.c @@ -2661,7 +2661,7 @@ scan_card_table_for_block (MSBlockInfo *block, CardTableScanType scan_type, Scan if (small_objects) { HEAVY_STAT (++scanned_objects); - scan_func (object, sgen_obj_get_descriptor (object), queue); + scan_func (object, sgen_obj_get_descriptor_safe (object), queue); } else { size_t offset = sgen_card_table_get_card_offset (obj, block_start); sgen_cardtable_scan_object (object, block_obj_size, card_base + offset, ctx); diff --git a/src/mono/mono/utils/mono-math.h b/src/mono/mono/utils/mono-math.h index 0f535e8ca28629..a24a0a303a9efc 100644 --- a/src/mono/mono/utils/mono-math.h +++ b/src/mono/mono/utils/mono-math.h @@ -7,6 +7,7 @@ #include #include +#include // Instead of isfinite, isinf, isnan, etc., // use mono_isfininite, mono_isinf, mono_isnan, etc. @@ -99,4 +100,27 @@ mono_round_to_even (double x) return copysign (floor_tmp, x); } +static inline gboolean +mono_try_trunc_i64 (double val, gint64 *out) +{ + const double two63 = 2147483648.0 * 4294967296.0; + // 0x402 is epsilon used to get us to the next value + if (val > (-two63 - 0x402) && val < two63) { + *out = (gint64)val; + return TRUE; + } + return FALSE; +} + +static inline gboolean +mono_try_trunc_u64 (double val, guint64 *out) +{ + const double two64 = 4294967296.0 * 4294967296.0; + if (val > -1.0 && val < two64) { + *out = (guint64)val; + return TRUE; + } + return FALSE; +} + #endif diff --git a/src/mono/mono/utils/mono-threads-coop.c b/src/mono/mono/utils/mono-threads-coop.c index 44d1ee8681df82..970a7099e9ecfa 100644 --- a/src/mono/mono/utils/mono-threads-coop.c +++ b/src/mono/mono/utils/mono-threads-coop.c @@ -95,12 +95,11 @@ coop_tls_pop (gpointer received_cookie) static void check_info (MonoThreadInfo *info, const gchar *action, const gchar *state, const char *func) { - if (!info) - g_error ("%s Cannot %s GC %s region if the thread is not attached", func, action, state); - if (!mono_thread_info_is_current (info)) - g_error ("%s [%p] Cannot %s GC %s region on a different thread", func, mono_thread_info_get_tid (info), action, state); - if (!mono_thread_info_is_live (info)) - g_error ("%s [%p] Cannot %s GC %s region if the thread is not live", func, mono_thread_info_get_tid (info), action, state); +#ifdef ENABLE_CHECKED_BUILD + g_assertf (info, "%s Cannot %s GC %s region if the thread is not attached", func, action, state); + g_assertf (mono_thread_info_is_current (info), "%s [%p] Cannot %s GC %s region on a different thread", func, mono_thread_info_get_tid (info), action, state); + g_assertf (mono_thread_info_is_live (info), "%s [%p] Cannot %s GC %s region if the thread is not live", func, mono_thread_info_get_tid (info), action, state); +#endif } static int coop_reset_blocking_count; diff --git a/src/mono/mono/utils/mono-threads-state-machine.c b/src/mono/mono/utils/mono-threads-state-machine.c index 2d9a06cd76f61b..927d86d619f23a 100644 --- a/src/mono/mono/utils/mono-threads-state-machine.c +++ b/src/mono/mono/utils/mono-threads-state-machine.c @@ -105,6 +105,7 @@ unwrap_thread_state (MonoThreadInfo* info, static void check_thread_state (MonoThreadInfo* info) { +#ifdef ENABLE_CHECKED_BUILD int raw_state, cur_state, suspend_count; gboolean no_safepoints; UNWRAP_THREAD_STATE (raw_state, cur_state, suspend_count, no_safepoints, info); @@ -133,6 +134,7 @@ check_thread_state (MonoThreadInfo* info) default: g_error ("Invalid state %d", cur_state); } +#endif } static void diff --git a/src/mono/nuget/Directory.Build.props b/src/mono/nuget/Directory.Build.props index e4a7e0f90ba31e..7b96c763867037 100644 --- a/src/mono/nuget/Directory.Build.props +++ b/src/mono/nuget/Directory.Build.props @@ -14,8 +14,9 @@ true - 6.0.0 + $(ProductVersion) $(PackageVersion) + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj index 747da02070f2f9..b59bff406ce153 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/Microsoft.NET.Workload.Mono.Toolchain.Manifest.pkgproj @@ -20,6 +20,12 @@ + + + + data/localize + + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in index d9a9dc2a72d463..9b13301584dc5d 100644 --- a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in @@ -7,13 +7,9 @@ !$([MSBuild]::VersionGreaterThanOrEquals('$(TargetFrameworkVersion)', '6.0'))">true - - <_NativeBuildNeeded Condition="'$(RunAOTCompilation)' == 'true'">true - WebAssembly workloads (required for AOT) are only supported for projects targeting net6.0+ - - - true + + true $(WasmNativeWorkload) @@ -128,7 +124,21 @@ /> - - + + + + + + + + + + diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.cs.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.cs.json new file mode 100644 index 00000000000000..da1ee8979a0a73 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.cs.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Nástroje pro sestavení .NET WebAssembly" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.de.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.de.json new file mode 100644 index 00000000000000..3d4467d7b055eb --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.de.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly-Buildtools" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.en.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.en.json new file mode 100644 index 00000000000000..a6dcccedcf59ff --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.en.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly build tools" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.es.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.es.json new file mode 100644 index 00000000000000..166e1db9fe8162 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.es.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Herramientas de compilación de WebAssembly de .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.fr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.fr.json new file mode 100644 index 00000000000000..e660e45a264dbe --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.fr.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Outils de construction .NET WebAssembly" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.it.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.it.json new file mode 100644 index 00000000000000..6703c0025606b4 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.it.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Strumenti di compilazione WebAssembly .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ja.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ja.json new file mode 100644 index 00000000000000..fd3fe984155ab5 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ja.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly ビルド ツール" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ko.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ko.json new file mode 100644 index 00000000000000..c5261248ff6092 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ko.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly 빌드 도구" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pl.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pl.json new file mode 100644 index 00000000000000..858653c73b527a --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pl.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Narzędzia kompilacji zestawu WebAssembly platformy .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pt-BR.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pt-BR.json new file mode 100644 index 00000000000000..a8dceaf324f2cb --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.pt-BR.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Ferramentas de build do .NET WebAssembly" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ru.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ru.json new file mode 100644 index 00000000000000..102e67acdc2c21 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.ru.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": "Средства сборки WebAssembly .NET" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.tr.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.tr.json new file mode 100644 index 00000000000000..34d4e3b66de92e --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.tr.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly derleme araçları" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hans.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hans.json new file mode 100644 index 00000000000000..360e1e5a5d1f03 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hans.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly 生成工具" +} \ No newline at end of file diff --git a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hant.json b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hant.json new file mode 100644 index 00000000000000..c5d85ecc0f5c04 --- /dev/null +++ b/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/localize/WorkloadManifest.zh-Hant.json @@ -0,0 +1,3 @@ +{ + "workloads/wasm-tools/description": ".NET WebAssembly 組建工具" +} \ No newline at end of file diff --git a/src/mono/nuget/mono-packages.proj b/src/mono/nuget/mono-packages.proj index a56c63f8827642..98b576787e8841 100644 --- a/src/mono/nuget/mono-packages.proj +++ b/src/mono/nuget/mono-packages.proj @@ -14,11 +14,18 @@ - - + + + + + + diff --git a/src/mono/sample/Android/AndroidSampleApp.csproj b/src/mono/sample/Android/AndroidSampleApp.csproj index 1abf7659bd0997..a5129bdfe82c68 100644 --- a/src/mono/sample/Android/AndroidSampleApp.csproj +++ b/src/mono/sample/Android/AndroidSampleApp.csproj @@ -72,6 +72,7 @@ AotModulesTablePath="$(_AotModulesTablePath)" ToolPrefix="$(_AotToolPrefix)" LibraryFormat="$(_AotLibraryFormat)" + IntermediateOutputPath="$(IntermediateOutputPath)" UseLLVM="$(UseLLVM)" LLVMPath="$(MonoAotCrossDir)"> diff --git a/src/mono/sample/iOS/Makefile b/src/mono/sample/iOS/Makefile index 34279c41d8187c..bdfc6c8f854b2b 100644 --- a/src/mono/sample/iOS/Makefile +++ b/src/mono/sample/iOS/Makefile @@ -4,6 +4,8 @@ DOTNET := ../../../../dotnet.sh USE_LLVM=true AOT?=false TARGET?=iOSSimulator +DEPLOY_AND_RUN?=true +APP_SANDBOX?=false #If DIAGNOSTIC_PORTS is enabled, RUNTIME_COMPONENTS must also be enabled. #If RUNTIME_COMPONENTS is enabled, DIAGNOSTIC_PORTS is optional. @@ -31,6 +33,7 @@ run: clean appbuilder /p:UseLLVM=$(USE_LLVM) \ /p:ForceAOT=$(AOT) \ '/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \ + '/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \ '/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"' run-sim: clean appbuilder @@ -41,10 +44,12 @@ run-sim: clean appbuilder /p:UseLLVM=$(USE_LLVM) \ /p:ForceAOT=$(AOT) \ '/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \ + '/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \ '/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"' build-appbundle: clean appbuilder $(DOTNET) publish -c $(MONO_CONFIG) /p:TargetOS=$(TARGET) /p:TargetArchitecture=$(MONO_ARCH) \ + '/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \ /p:UseLLVM=$(USE_LLVM) /p:ForceAOT=$(AOT) /bl \ run-catalyst: @@ -52,8 +57,10 @@ run-catalyst: -c $(MONO_CONFIG) \ /p:TargetOS=MacCatalyst \ /p:TargetArchitecture=$(MONO_ARCH) \ + '/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \ /p:UseLLVM=False \ - /p:ForceAOT=True + /p:ForceAOT=True \ + /p:EnableAppSandbox=$(APP_SANDBOX) run-sim-interp: clean appbuilder $(DOTNET) publish \ @@ -63,6 +70,7 @@ run-sim-interp: clean appbuilder /p:UseLLVM=$(USE_LLVM) \ /p:ForceAOT=$(AOT) \ /p:MonoForceInterpreter=true \ + '/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \ '/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \ '/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"' @@ -72,7 +80,9 @@ run-catalyst-interp: /p:TargetOS=MacCatalyst \ /p:TargetArchitecture=$(MONO_ARCH) \ /p:UseLLVM=False \ + '/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \ /p:ForceAOT=True \ + /p:EnableAppSandbox=$(APP_SANDBOX) \ /p:MonoForceInterpreter=true clean: diff --git a/src/mono/sample/iOS/Program.csproj b/src/mono/sample/iOS/Program.csproj index 471abcbbe69c81..65f252e7e55221 100644 --- a/src/mono/sample/iOS/Program.csproj +++ b/src/mono/sample/iOS/Program.csproj @@ -5,6 +5,7 @@ $(NetCoreAppToolCurrent) iOS iOSSimulator + true $(TargetOS.ToLower())-$(TargetArchitecture) $(DefineConstants);CI_TEST @@ -17,6 +18,7 @@ adhoc + false @@ -59,6 +61,7 @@ AotModulesTablePath="$(AppDir)\modules.m" AotModulesTableLanguage="ObjC" OutputDir="$(PublishDir)" + IntermediateOutputPath="$(IntermediateOutputPath)" UseLLVM="$(UseLLVM)" LLVMPath="$(MonoAotCrossDir)"> @@ -79,6 +82,7 @@ ForceAOT="$(RunAOTCompilation)" ForceInterpreter="$(MonoForceInterpreter)" RuntimeComponents="$(RuntimeComponents)" + EnableAppSandbox="$(EnableAppSandbox)" DiagnosticPorts="$(DiagnosticPorts)" AppDir="$(MSBuildThisFileDirectory)$(PublishDir)"> @@ -91,7 +95,7 @@ + Condition="'$(ArchiveTests)' != 'true' and '$(DeployAndRun)' == 'true'"> diff --git a/src/mono/sample/mbr/browser/WasmDelta.csproj b/src/mono/sample/mbr/browser/WasmDelta.csproj index 322a01ba8595a7..c150529f753c6d 100644 --- a/src/mono/sample/mbr/browser/WasmDelta.csproj +++ b/src/mono/sample/mbr/browser/WasmDelta.csproj @@ -31,7 +31,6 @@ - \%(_DeltaFileForPublish.Filename)%(_DeltaFileForPublish.Extension) diff --git a/src/mono/sample/wasm/Directory.Build.targets b/src/mono/sample/wasm/Directory.Build.targets index 492c61cf048467..bc7f6b24b0ba27 100644 --- a/src/mono/sample/wasm/Directory.Build.targets +++ b/src/mono/sample/wasm/Directory.Build.targets @@ -1,10 +1,5 @@ - - - - - Main(string[] args) } return args.Length; } -} \ No newline at end of file +} diff --git a/src/mono/sample/wasm/wasm.mk b/src/mono/sample/wasm/wasm.mk index 2eb4adcfb45853..e3405dbcc0d0d5 100644 --- a/src/mono/sample/wasm/wasm.mk +++ b/src/mono/sample/wasm/wasm.mk @@ -10,9 +10,12 @@ CONFIG?=Release WASM_DEFAULT_BUILD_ARGS?=/p:TargetArchitecture=wasm /p:TargetOS=Browser /p:Configuration=$(CONFIG) -all: build +all: publish build: + EMSDK_PATH=$(realpath $(TOP)/src/mono/wasm/emsdk) $(DOTNET) build $(DOTNET_Q_ARGS) $(WASM_DEFAULT_BUILD_ARGS) $(MSBUILD_ARGS) $(PROJECT_NAME) + +publish: EMSDK_PATH=$(realpath $(TOP)/src/mono/wasm/emsdk) $(DOTNET) publish $(DOTNET_Q_ARGS) $(WASM_DEFAULT_BUILD_ARGS) $(MSBUILD_ARGS) $(PROJECT_NAME) clean: diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 52e5de9e30227e..63e03b225468c7 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -72,7 +72,7 @@ MONO_LIBS = \ $(ICU_LIBDIR)/libicui18n.a EMCC_DEBUG_FLAGS =-g -Os -s -DDEBUG=1 -EMCC_RELEASE_FLAGS=-Oz +EMCC_RELEASE_FLAGS=-O2 ifeq ($(NOSTRIP),) STRIP_CMD=&& $(EMSDK_PATH)/upstream/bin/wasm-opt --strip-dwarf $(NATIVE_BIN_DIR)/dotnet.wasm -o $(NATIVE_BIN_DIR)/dotnet.wasm diff --git a/src/mono/wasm/build/README.md b/src/mono/wasm/build/README.md index 854ea041398fa0..312b5308645c39 100644 --- a/src/mono/wasm/build/README.md +++ b/src/mono/wasm/build/README.md @@ -1,3 +1,58 @@ +# Wasm app build + +This usually consists of taking the built assemblies, and related files, and generating an app bundle. + +Wasm app build can run in two scenarios: + +1. After build, eg. when running the app in VS, or `dotnet build foo.csproj` +2. For Publish, eg, when publishing the app to a folder, or Azure + +A dotnet wasm app has some native wasm files (`dotnet.wasm`, and `dotnet.js`). How these files are obtained, or generated: + +1. Build + a. with no native libraries referenced (AOT setting is ignored here) + - files from the runtime pack are used as-is + b. with native libraries referenced + - dotnet.wasm is relinked with the native libraries +2. Publish + - dotnet.wasm is relinked with the native libraries, and updated pinvoke/icalls from the trimmed assemblies + - if `RunAOTCompilation=true`, then the relinking includes AOT'ed assemblies + +## `Build` + +Implementation: + +- Target `WasmBuildApp` +- runs after `Build` by default + - which can be disabled by `$(DisableAutoWasmBuildApp)` + - or the run-after target can be set via `$(WasmBuildAppAfterThisTarget)` + +- To run a custom target + - *before* any of the wasm build targets, use `$(WasmBuildAppDependsOn)`, and prepend your target name to that + - *after* any of the wasm build targets, use `AfterTargets="WasmBuildApp"` on that target +- Avoid depending on this target, because it is available only when the workload is installed. Use `$(WasmNativeWorkload)` to check if it is installed. + +## `Publish` + +Implementation: + +- This part runs as a nested build using a `MSBuild` task, which means that the project gets reevaluated. So, if there were any changes made to items/properties in targets before this, then they won't be visible in the nested build. +- By default `WasmTriggerPublishApp` runs after the `Publish` target, and that triggers the nested build + - The nested build runs `WasmNestedPublishApp`, which causes `Build`, and `Publish` targets to be run + - Because this causes `Build` to be run again, if you have any targets that get triggered by that, then they will be running twice. + - But the original *build* run, and this *publish* run can be differentiated using `$(WasmBuildingForNestedPublish)` + +- `WasmTriggerPublishApp` essentially just invokes the nested publish + - This runs after `Publish` + - which can be disabled by `$(DisableAutoWasmPublishApp)` + - or the run-after target can be set via `$(WasmTriggerPublishAppAfterThisTarget)` + + - To influence the wasm build for publish, use `WasmNestedPublishApp` + - To run a custom target before it, use `$(WasmNestedPublishAppDependsOn)` + - to run a custom target *after* it, use `AfterTargets="WasmNestedPublishApp"` + + - If you want to *dependsOn* on this, then use `DependsOnTargets="WasmTriggerPublishApp"` + # `WasmApp.{props,targets}`, and `WasmApp.InTree.{props,targets}` - Any project that wants to use this, can import the props+targets, and set up the @@ -74,4 +129,4 @@ them for the new task assembly. 3. Make changes similar to the one for existing dependent tasks in - `eng/testing/linker/trimmingTests.targets`, - `src/tests/Common/wasm-test-runner/WasmTestRunner.proj` - - `src/tests/Directory.Build.targets` \ No newline at end of file + - `src/tests/Directory.Build.targets` diff --git a/src/mono/wasm/build/WasmApp.InTree.targets b/src/mono/wasm/build/WasmApp.InTree.targets index b345da95cf93c2..f8c26080f0268d 100644 --- a/src/mono/wasm/build/WasmApp.InTree.targets +++ b/src/mono/wasm/build/WasmApp.InTree.targets @@ -17,7 +17,7 @@ Condition="'$(_LocalMicrosoftNetCoreAppRuntimePackDir)' != '' and '%(ResolvedRuntimePack.FrameworkName)' == 'Microsoft.NETCore.App'" /> - + @@ -35,9 +35,9 @@ + DependsOnTargets="WasmTriggerPublishApp"> $(MSBuildProjectName) diff --git a/src/mono/wasm/build/WasmApp.LocalBuild.props b/src/mono/wasm/build/WasmApp.LocalBuild.props index d92024f720d46c..70c0d5edafe407 100644 --- a/src/mono/wasm/build/WasmApp.LocalBuild.props +++ b/src/mono/wasm/build/WasmApp.LocalBuild.props @@ -32,7 +32,7 @@ $([MSBuild]::NormalizeDirectory($(ArtifactsBinDir), 'microsoft.netcore.app.runtime.browser-wasm', $(RuntimeConfig))) - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(_NetCoreAppToolCurrent)', 'publish')) + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(_NetCoreAppToolCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmBuildTasks', 'Debug', '$(_NetCoreAppToolCurrent)', 'publish')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MonoAOTCompiler', 'Debug', '$(_NetCoreAppToolCurrent)')) $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'RuntimeConfigParser', 'Debug', '$(_NetCoreAppToolCurrent)')) diff --git a/src/mono/wasm/build/WasmApp.LocalBuild.targets b/src/mono/wasm/build/WasmApp.LocalBuild.targets index 23f5249786d665..47559bccb84288 100644 --- a/src/mono/wasm/build/WasmApp.LocalBuild.targets +++ b/src/mono/wasm/build/WasmApp.LocalBuild.targets @@ -25,7 +25,7 @@ - true + true link @@ -45,7 +45,7 @@ Condition="'$(MicrosoftNetCoreAppRuntimePackLocationToUse)' != '' and '%(ResolvedRuntimePack.FrameworkName)' == 'Microsoft.NETCore.App'" /> - + diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index 5b43374ab16b7f..7404e74554ac79 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -17,12 +17,6 @@ _CompleteWasmBuildNative - - _InitializeCommonProperties; - _PrepareForWasmBuildNativeOnly; - _WasmBuildNativeCore; - - <_BeforeWasmBuildAppDependsOn> $(_BeforeWasmBuildAppDependsOn); _SetupEmscripten; @@ -33,22 +27,16 @@ true + + + + <_MonoComponent Include="hot_reload;debugger" /> - - - - - - <_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" /> - <_WasmAssembliesInternal Include="@(WasmAssembliesToBundle->Distinct())" /> - - - <_EMSDKMissingPaths Condition="'$(_EMSDKMissingPaths)' == '' and ('$(EmscriptenSdkToolsPath)' == '' or !Exists('$(EmscriptenSdkToolsPath)'))">%24(EmscriptenSdkToolsPath)=$(EmscriptenSdkToolsPath) @@ -117,11 +105,27 @@ - + + + + true + + true + false + + + + + true true - false - true + + + false + + + true + false @@ -143,6 +147,7 @@ <_MonoAotCrossCompilerPath>@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','browser-wasm')) <_EmccDefaultFlagsRsp>$([MSBuild]::NormalizePath($(_WasmRuntimePackSrcDir), 'emcc-default.rsp')) + false true true $(WasmBuildNative) @@ -152,15 +157,15 @@ <_WasmPInvokeHPath>$(_WasmRuntimePackIncludeDir)wasm\pinvoke.h <_DriverGenCPath>$(_WasmIntermediateOutputPath)driver-gen.c - <_DriverGenCNeeded Condition="'$(_DriverGenCNeeded)' == '' and '$(RunAOTCompilation)' == 'true'">true + <_DriverGenCNeeded Condition="'$(_DriverGenCNeeded)' == '' and '$(_WasmShouldAOT)' == 'true'">true <_EmccAssertionLevelDefault>0 <_EmccOptimizationFlagDefault Condition="'$(_WasmDevel)' == 'true'">-O0 -s ASSERTIONS=$(_EmccAssertionLevelDefault) - <_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(OS)' != 'Windows_NT' and '$(Configuration)' == 'Debug'">-Os - <_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' != 'Debug'">-Oz + <_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == '' and '$(Configuration)' == 'Debug' and '$(WasmBuildingForNestedPublish)' != 'true'">-O1 <_EmccOptimizationFlagDefault Condition="'$(_EmccOptimizationFlagDefault)' == ''">-Oz $(_EmccOptimizationFlagDefault) + -O2 $(EmccCompileOptimizationFlag) <_EmccCompileRsp>$(_WasmIntermediateOutputPath)emcc-compile.rsp @@ -190,8 +195,8 @@ <_EmccCFlags Include="$(EmccCompileOptimizationFlag)" /> <_EmccCFlags Include="@(_EmccCommonFlags)" /> - <_EmccCFlags Include="-DENABLE_AOT=1" Condition="'$(RunAOTCompilation)' == 'true'" /> - <_EmccCFlags Include="-DDRIVER_GEN=1" Condition="'$(RunAOTCompilation)' == 'true'" /> + <_EmccCFlags Include="-DENABLE_AOT=1" Condition="'$(_WasmShouldAOT)' == 'true'" /> + <_EmccCFlags Include="-DDRIVER_GEN=1" Condition="'$(_WasmShouldAOT)' == 'true'" /> <_EmccCFlags Include="-DINVARIANT_GLOBALIZATION=1" Condition="'$(InvariantGlobalization)' == 'true'" /> <_EmccCFlags Include="-DLINK_ICALLS=1" Condition="'$(WasmLinkIcalls)' == 'true'" /> <_EmccCFlags Include="-DCORE_BINDINGS" /> @@ -206,6 +211,9 @@ <_EmccLDFlags Include="@(_EmccCommonFlags)" /> <_EmccLDFlags Include="-s TOTAL_MEMORY=$(EmccTotalMemory)" /> + + <_EmccLDFlags Include="-s ERROR_ON_UNDEFINED_SYMBOLS=0" Condition="'$(WasmBuildingForNestedPublish)' != 'true'" /> + <_DriverCDependencies Include="$(_WasmPInvokeHPath);$(_WasmICallTablePath)" /> <_DriverCDependencies Include="$(_DriverGenCPath)" Condition="'$(_DriverGenCNeeded)' == 'true'" /> @@ -236,7 +244,9 @@ + OutputPath="$(_WasmPInvokeTablePath)"> + + @@ -244,10 +254,16 @@ Text="Could not find AOT cross compiler at %24(_MonoAotCrossCompilerPath)=$(_MonoAotCrossCompilerPath)" /> + + + + + OutputPath="$(_WasmICallTablePath)"> + + @@ -263,6 +279,9 @@ + + + @@ -276,14 +295,17 @@ SourceFiles="@(_WasmSourceFileToCompile)" Arguments='"@$(_EmccDefaultFlagsRsp)" "@$(_EmccCompileRsp)"' EnvironmentVariables="@(EmscriptenEnvVars)" - OutputMessageImportance="$(_EmccCompileOutputMessageImportance)" /> + OutputMessageImportance="$(_EmccCompileOutputMessageImportance)"> + + + Condition="'$(_WasmShouldAOT)' == 'true' and @(_BitcodeFile->Count()) > 0" + DependsOnTargets="_WasmWriteRspForCompilingBitcode" + Returns="@(FileWrites)"> <_BitCodeFile Dependencies="%(_BitCodeFile.Dependencies);$(_EmccDefaultFlagsRsp);$(_EmccCompileBitcodeRsp)" /> @@ -294,7 +316,9 @@ SourceFiles="@(_BitCodeFile)" Arguments=""@$(_EmccDefaultFlagsRsp)" "@$(_EmccCompileBitcodeRsp)"" EnvironmentVariables="@(EmscriptenEnvVars)" - OutputMessageImportance="$(_EmccCompileOutputMessageImportance)" /> + OutputMessageImportance="$(_EmccCompileOutputMessageImportance)"> + + @@ -303,6 +327,9 @@ <_BitcodeLDFlags Include="$(EmccExtraBitcodeLDFlags)" /> + + + @@ -312,8 +339,8 @@ <_WasmNativeFileForLinking Include="%(_WasmSourceFileToCompile.ObjectFile)" /> <_WasmNativeFileForLinking - Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\*.a" - Exclude="@(_MonoRuntimeComponentDontLink->'$(MicrosoftNetCoreAppRuntimePackRidNativeDir)\%(Identity)')" /> + Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)*.a" + Exclude="@(_MonoRuntimeComponentDontLink->'$(MicrosoftNetCoreAppRuntimePackRidNativeDir)%(Identity)')" /> <_WasmExtraJSFile Include="@(Content)" Condition="'%(Content.Extension)' == '.js'" /> @@ -336,16 +363,24 @@ + + + + DependsOnTargets="_WasmSelectRuntimeComponentsForLinking;_WasmCompileAssemblyBitCodeFilesForAOT;_WasmWriteRspFilesForLinking" + Returns="@(FileWrites)" > + + + + @@ -358,7 +393,7 @@ - + $(EmccExtraCFlags) -DDRIVER_GEN=1 <_DriverGenCNeeded>true @@ -414,7 +449,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ ******************************* --> - + <_MonoAotCrossCompilerPath>@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','browser-wasm')) @@ -433,13 +468,11 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ - <_AotInputAssemblies Include="@(_WasmAssembliesInternal)" Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'"> + <_AotInputAssemblies Include="@(_WasmAssembliesInternal)"> @(MonoAOTCompilerDefaultAotArguments, ';') @(MonoAOTCompilerDefaultProcessArguments, ';') - <_AOT_InternalForceInterpretAssemblies Include="@(_WasmAssembliesInternal->WithMetadataValue('_InternalForceInterpret', 'true'))" /> - <_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" /> <_WasmAOTSearchPaths Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)" /> @@ -452,16 +485,13 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ <_AOTCompilerCacheFile>$(_WasmIntermediateOutputPath)aot_compiler_cache.json - - <_WasmDedupAssembly>$(_WasmIntermediateOutputPath)\aot-instances.dll - + + LLVMPath="$(EmscriptenUpstreamBinPath)" + IntermediateOutputPath="$(_WasmIntermediateOutputPath)"> - - <_WasmAssembliesInternal Include="@(_AOT_InternalForceInterpretAssemblies)" /> - - <_AOTAssemblies Include="@(_WasmAssembliesInternal)" Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'" /> <_BitcodeFile Include="%(_WasmAssembliesInternal.LlvmBitcodeFile)" /> <_BitcodeFile ObjectFile="$(_WasmIntermediateOutputPath)%(FileName).o" /> - + <_WasmStrippedAssembliesPath>$([MSBuild]::NormalizeDirectory($(_WasmIntermediateOutputPath), 'stripped-assemblies')) + <_AOTedAssemblies Include="@(_WasmAssembliesInternal)" /> <_WasmStrippedAssemblies - Condition="'%(_WasmAssembliesInternal._InternalForceInterpret)' != 'true'" - Include="@(_WasmAssembliesInternal->'$(_WasmStrippedAssembliesPath)%(FileName)%(Extension)')" + Include="@(_AOTedAssemblies)" OriginalPath="%(_WasmAssembliesInternal.Identity)" /> - <_WasmInterpOnlyAssembly Include="@(_WasmAssembliesInternal->WithMetadataValue('_InternalForceInterpret', 'true'))" /> @@ -531,7 +557,7 @@ EMSCRIPTEN_KEEPALIVE void mono_wasm_load_profiler_aot (const char *desc) { mono_ <_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" /> - <_WasmAssembliesInternal Include="@(_WasmStrippedAssemblies);@(_WasmInterpOnlyAssembly)" /> + <_WasmAssembliesInternal Include="@(_WasmStrippedAssemblies)" /> diff --git a/src/mono/wasm/build/WasmApp.props b/src/mono/wasm/build/WasmApp.props index bc45a6d54d73d8..7fdde27c4affb5 100644 --- a/src/mono/wasm/build/WasmApp.props +++ b/src/mono/wasm/build/WasmApp.props @@ -5,8 +5,7 @@ browser-wasm true - Publish - + <_WasmBuildCoreDependsOn> _InitializeCommonProperties; _BeforeWasmBuildApp; _WasmResolveReferences; @@ -15,6 +14,16 @@ _WasmBuildNativeCore; _WasmGenerateAppBundle; _AfterWasmBuildApp + + + + _PrepareForAfterBuild; + $(_WasmBuildCoreDependsOn) + + + _PrepareForNestedPublish; + $(_WasmBuildCoreDependsOn) + diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index e5ceb13def292e..7642cf01694908 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -5,9 +5,6 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_WasmRuntimeConfigFilePath Condition="$([System.String]::new(%(PublishItemsOutputGroupOutputs.Identity)).EndsWith('$(AssemblyName).runtimeconfig.json'))">@(PublishItemsOutputGroupOutputs) + + + + + + - - + + <_WasmRuntimeConfigFilePath Condition="$([System.String]::new(%(PublishItemsOutputGroupOutputs.Identity)).EndsWith('$(AssemblyName).runtimeconfig.json'))">@(PublishItemsOutputGroupOutputs) + + + + - + + + Text="%24(MicrosoftNetCoreAppRuntimePackDir)='', and cannot find %25(ResolvedRuntimePack.PackageDirectory)=%(ResolvedRuntimePack.PackageDirectory). One of these need to be set to a valid path" /> @@ -106,37 +171,50 @@ <_WasmRuntimePackIncludeDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include')) <_WasmRuntimePackSrcDir>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'src')) - <_WasmIntermediateOutputPath>$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'wasm')) + <_WasmIntermediateOutputPath Condition="'$(WasmBuildingForNestedPublish)' == ''">$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'wasm', 'for-build')) + <_WasmIntermediateOutputPath Condition="'$(WasmBuildingForNestedPublish)' != ''">$([MSBuild]::NormalizeDirectory($(IntermediateOutputPath), 'wasm', 'for-publish')) <_DriverGenCPath>$(_WasmIntermediateOutputPath)driver-gen.c + <_WasmShouldAOT Condition="'$(WasmBuildingForNestedPublish)' == 'true' and '$(RunAOTCompilation)' == 'true'">true + <_WasmShouldAOT Condition="'$(RunAOTCompilationAfterBuild)' == 'true' and '$(RunAOTCompilation)' == 'true'">true + <_WasmShouldAOT Condition="'$(_WasmShouldAOT)' == ''">false + + + + + + - true + true + false $([MSBuild]::NormalizeDirectory($(OutputPath), 'AppBundle')) $(TargetFileName) $([MSBuild]::NormalizeDirectory($(WasmAppDir))) <_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == $(AssemblyName) and '%(WasmAssembliesToBundle.Extension)' == '.dll' and $(WasmGenerateAppBundle) == 'true'">%(WasmAssembliesToBundle.Identity) - <_WasmRuntimeConfigFilePath Condition="$(_MainAssemblyPath) != ''">$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json')) - <_ParsedRuntimeConfigFilePath Condition="'$(_MainAssemblyPath)' != ''">$([System.IO.Path]::GetDirectoryName($(_MainAssemblyPath)))\runtimeconfig.bin + <_WasmRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' == '' and $(_MainAssemblyPath) != ''">$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json')) + <_ParsedRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' != ''">$([System.IO.Path]::GetDirectoryName($(_WasmRuntimeConfigFilePath)))\runtimeconfig.bin - + + <_WasmAssembliesInternal Remove="@(_WasmAssembliesInternal)" /> <_WasmAssembliesInternal Include="@(WasmAssembliesToBundle->Distinct())" /> + <_WasmSatelliteAssemblies Remove="@(_WasmSatelliteAssemblies)" /> <_WasmSatelliteAssemblies Include="@(_WasmAssembliesInternal)" /> <_WasmSatelliteAssemblies Remove="@(_WasmSatelliteAssemblies)" Condition="!$([System.String]::Copy('%(Identity)').EndsWith('.resources.dll'))" /> @@ -166,9 +244,7 @@ - - - + icudt.dat @@ -184,7 +260,16 @@ + + + + + + + diff --git a/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj b/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj index 3a7b66fac7389f..65a0df19fb640c 100644 --- a/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj +++ b/src/mono/wasm/data/aot-tests/ProxyProjectForAOTOnHelix.proj @@ -5,6 +5,7 @@ $(MSBuildThisFileDirectory)..\wasm_build\ true + true $(TestRootDir)..\publish\ $(OriginalPublishDir)..\extraFiles\ $(TestRootDir)\obj\ diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs index be7d729dd019e4..08ca2a974b4360 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DebugStore.cs @@ -514,20 +514,30 @@ internal class AssemblyInfo internal PEReader peReader; internal MemoryStream asmStream; internal MemoryStream pdbStream; - public int DebugId { get; set; } + private int debugId; public bool TriedToLoadSymbolsOnDemand { get; set; } public unsafe AssemblyInfo(string url, byte[] assembly, byte[] pdb) { + debugId = -1; this.id = Interlocked.Increment(ref next_id); asmStream = new MemoryStream(assembly); peReader = new PEReader(asmStream); asmMetadataReader = PEReaderExtensions.GetMetadataReader(peReader); + Name = asmMetadataReader.GetAssemblyDefinition().GetAssemblyName().Name + ".dll"; + AssemblyNameUnqualified = Name; if (pdb != null) { pdbStream = new MemoryStream(pdb); - pdbMetadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); + try + { + pdbMetadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader(); + } + catch (BadImageFormatException) + { + Console.WriteLine($"Warning: Unable to read debug information of: {Name} (use DebugType=Portable/Embedded)"); + } } else { @@ -538,11 +548,21 @@ public unsafe AssemblyInfo(string url, byte[] assembly, byte[] pdb) pdbMetadataReader = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry).GetMetadataReader(); } } - Name = asmMetadataReader.GetAssemblyDefinition().GetAssemblyName().Name + ".dll"; - AssemblyNameUnqualified = asmMetadataReader.GetAssemblyDefinition().GetAssemblyName().Name + ".dll"; Populate(); } + public async Task GetDebugId(SessionId sessionId, MonoSDBHelper sdbAgent, CancellationToken token) + { + if (debugId > 0) + return debugId; + debugId = await sdbAgent.GetAssemblyId(sessionId, Name, token); + return debugId; + } + public void SetDebugId(int id) + { + if (debugId <= 0 && debugId != id) + debugId = id; + } public bool EnC(byte[] meta, byte[] pdb) { var asmStream = new MemoryStream(meta); diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index bc0f4faeb456b5..950acbb2dcf915 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -267,6 +267,14 @@ internal enum StepKind Out } + internal enum PauseOnExceptionsKind + { + Unset, + None, + Uncaught, + All + } + internal class ExecutionContext { public string DebugId { get; set; } @@ -279,8 +287,7 @@ internal class ExecutionContext public int Id { get; set; } public object AuxData { get; set; } - public bool PauseOnUncaught { get; set; } - public bool PauseOnCaught { get; set; } + public PauseOnExceptionsKind PauseOnExceptions { get; set; } public List CallStack { get; set; } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs index 55896677f2b052..9469cac5b9951a 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MemberReferenceResolver.cs @@ -124,7 +124,7 @@ public async Task TryToRunOnLoadedClasses(string varName, CancellationT var type = asm.GetTypeByName(classNameToFind); if (type != null) { - typeId = await sdbHelper.GetTypeIdFromToken(sessionId, asm.DebugId, type.Token, token); + typeId = await sdbHelper.GetTypeIdFromToken(sessionId, await asm.GetDebugId(sessionId, sdbHelper, token), type.Token, token); } } } diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs index 95aa6dedcd0069..af4707ae7b8cfe 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs @@ -126,20 +126,26 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth case "Runtime.exceptionThrown": { - if (!GetContext(sessionId).IsRuntimeReady) + // Don't process events from sessions we aren't tracking + if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + return false; + + if (!context.IsRuntimeReady) { string exceptionError = args?["exceptionDetails"]?["exception"]?["value"]?.Value(); if (exceptionError == sPauseOnUncaught || exceptionError == sPauseOnCaught) - { return true; - } } break; } case "Debugger.paused": { - if (!GetContext(sessionId).IsRuntimeReady) + // Don't process events from sessions we aren't tracking + if (!contexts.TryGetValue(sessionId, out ExecutionContext context)) + return false; + + if (!context.IsRuntimeReady) { string reason = args?["reason"]?.Value(); if (reason == "exception") @@ -148,17 +154,19 @@ protected override async Task AcceptEvent(SessionId sessionId, string meth if (exceptionError == sPauseOnUncaught) { await SendCommand(sessionId, "Debugger.resume", new JObject(), token); - GetContext(sessionId).PauseOnUncaught = true; + if (context.PauseOnExceptions == PauseOnExceptionsKind.Unset) + context.PauseOnExceptions = PauseOnExceptionsKind.Uncaught; return true; } if (exceptionError == sPauseOnCaught) { await SendCommand(sessionId, "Debugger.resume", new JObject(), token); - GetContext(sessionId).PauseOnCaught = true; + context.PauseOnExceptions = PauseOnExceptionsKind.All; return true; } } } + //TODO figure out how to stich out more frames and, in particular what happens when real wasm is on the stack string top_func = args?["callFrames"]?[0]?["functionName"]?.Value(); switch (top_func) { @@ -434,23 +442,16 @@ protected override async Task AcceptCommand(MessageId id, string method, J case "Debugger.setPauseOnExceptions": { string state = args["state"].Value(); - if (!context.IsRuntimeReady) + context.PauseOnExceptions = state switch { - context.PauseOnCaught = false; - context.PauseOnUncaught = false; - switch (state) - { - case "all": - context.PauseOnCaught = true; - context.PauseOnUncaught = true; - break; - case "uncaught": - context.PauseOnUncaught = true; - break; - } - } - else - await SdbHelper.EnableExceptions(id, state, token); + "all" => PauseOnExceptionsKind.All, + "uncaught" => PauseOnExceptionsKind.Uncaught, + "none" => PauseOnExceptionsKind.None, + _ => PauseOnExceptionsKind.Unset + }; + + if (context.IsRuntimeReady) + await SdbHelper.EnableExceptions(id, context.PauseOnExceptions, token); // Pass this on to JS too return false; } @@ -552,7 +553,7 @@ private async Task CallOnFunction(MessageId id, JObject args, Cancellation args["details"] = await SdbHelper.GetPointerContent(id, int.Parse(objectId.Value), token); break; case "array": - args["details"] = await SdbHelper.GetArrayValues(id, int.Parse(objectId.Value), token); + args["details"] = await SdbHelper.GetArrayValuesProxy(id, int.Parse(objectId.Value), token); break; case "cfo_res": { @@ -820,6 +821,7 @@ private async Task SendCallStack(SessionId sessionId, ExecutionContext con }); if (!await EvaluateCondition(sessionId, context, context.CallStack.First(), bp, token)) { + context.ClearState(); await SendCommand(sessionId, "Debugger.resume", new JObject(), token); return true; } @@ -866,7 +868,7 @@ private async Task OnReceiveDebuggerAgentEvent(SessionId sessionId, JObjec int object_id = retDebuggerCmdReader.ReadInt32(); var caught = retDebuggerCmdReader.ReadByte(); var exceptionObject = await SdbHelper.GetObjectValues(sessionId, object_id, GetObjectCommandOptions.WithProperties | GetObjectCommandOptions.OwnProperties, token); - var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value().Equals("message")); + var exceptionObjectMessage = exceptionObject.FirstOrDefault(attr => attr["name"].Value().Equals("_message")); var data = JObject.FromObject(new { type = "object", @@ -956,6 +958,7 @@ private async Task OnDefaultContext(SessionId sessionId, ExecutionContext contex { context.BreakpointRequests[kvp.Key] = kvp.Value.Clone(); } + context.PauseOnExceptions = previousContext.PauseOnExceptions; } if (await IsRuntimeAlreadyReadyAlready(sessionId, token)) @@ -1182,18 +1185,18 @@ internal async Task LoadStore(SessionId sessionId, CancellationToken try { - string[] loaded_files = context.LoadedFiles; + string[] loaded_files = await GetLoadedFiles(sessionId, context, token); if (loaded_files == null) { - Result loaded = await SendMonoCommand(sessionId, MonoCommands.GetLoadedFiles(), token); - loaded_files = loaded.Value?["result"]?["value"]?.ToObject(); + Console.WriteLine($"Failed to get the list of loaded files. Managed code debugging won't work due to this."); } - - await - foreach (SourceFile source in context.store.Load(sessionId, loaded_files, token).WithCancellation(token)) + else { - await OnSourceFileAdded(sessionId, source, context, token); + await foreach (SourceFile source in context.store.Load(sessionId, loaded_files, token).WithCancellation(token)) + { + await OnSourceFileAdded(sessionId, source, context, token); + } } } catch (Exception e) @@ -1204,6 +1207,25 @@ internal async Task LoadStore(SessionId sessionId, CancellationToken if (!context.Source.Task.IsCompleted) context.Source.SetResult(context.store); return context.store; + + async Task GetLoadedFiles(SessionId sessionId, ExecutionContext context, CancellationToken token) + { + if (context.LoadedFiles != null) + return context.LoadedFiles; + + Result loaded = await SendMonoCommand(sessionId, MonoCommands.GetLoadedFiles(), token); + if (!loaded.IsOk) + { + Console.WriteLine($"Error on mono_wasm_get_loaded_files {loaded}"); + return null; + } + + string[] files = loaded.Value?["result"]?["value"]?.ToObject(); + if (files == null) + Console.WriteLine($"Error extracting the list of loaded_files from the result of mono_wasm_get_loaded_files: {loaded}"); + + return files; + } } private async Task RuntimeReady(SessionId sessionId, CancellationToken token) @@ -1213,16 +1235,10 @@ private async Task RuntimeReady(SessionId sessionId, CancellationTok return await context.ready.Task; var commandParams = new MemoryStream(); - var retDebuggerCmdReader = await SdbHelper.SendDebuggerAgentCommand(sessionId, CmdEventRequest.ClearAllBreakpoints, commandParams, token); - if (retDebuggerCmdReader == null) - { - Log("verbose", $"Failed to clear breakpoints"); - } + await SdbHelper.SendDebuggerAgentCommand(sessionId, CmdEventRequest.ClearAllBreakpoints, commandParams, token); - if (context.PauseOnCaught && context.PauseOnUncaught) - await SdbHelper.EnableExceptions(sessionId, "all", token); - else if (context.PauseOnUncaught) - await SdbHelper.EnableExceptions(sessionId, "uncaught", token); + if (context.PauseOnExceptions != PauseOnExceptionsKind.None && context.PauseOnExceptions != PauseOnExceptionsKind.Unset) + await SdbHelper.EnableExceptions(sessionId, context.PauseOnExceptions, token); await SdbHelper.SetProtocolVersion(sessionId, token); await SdbHelper.EnableReceiveRequests(sessionId, EventKind.UserBreak, token); @@ -1232,7 +1248,7 @@ private async Task RuntimeReady(SessionId sessionId, CancellationTok DebugStore store = await LoadStore(sessionId, token); context.ready.SetResult(store); SendEvent(sessionId, "Mono.runtimeReady", new JObject(), token); - SdbHelper.SetStore(store); + SdbHelper.ResetStore(store); return store; } @@ -1384,8 +1400,19 @@ private async Task AttachToTarget(SessionId sessionId, CancellationToken token) // see https://github.com/mono/mono/issues/19549 for background if (sessions.Add(sessionId)) { - string checkUncaughtExceptions = $"throw \"{sPauseOnUncaught}\";"; - string checkCaughtExceptions = $"try {{throw \"{sPauseOnCaught}\";}} catch {{}}"; + string checkUncaughtExceptions = string.Empty; + string checkCaughtExceptions = string.Empty; + + //we only need this check if it's a non-vs debugging + if (sessionId == SessionId.Null) + { + if (!contexts.TryGetValue(sessionId, out ExecutionContext context) || context.PauseOnExceptions == PauseOnExceptionsKind.Unset) + { + checkUncaughtExceptions = $"throw \"{sPauseOnUncaught}\";"; + checkCaughtExceptions = $"try {{throw \"{sPauseOnCaught}\";}} catch {{}}"; + } + } + await SendMonoCommand(sessionId, new MonoCommands("globalThis.dotnetDebugger = true"), token); Result res = await SendCommand(sessionId, "Page.addScriptToEvaluateOnNewDocument", diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs index d804421e78ab51..3787ca4538b1e8 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/MonoSDBHelper.cs @@ -17,6 +17,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp; using System.Reflection; +using System.Text; namespace Microsoft.WebAssembly.Diagnostics { @@ -357,6 +358,52 @@ internal enum StepSize Line } + internal record ArrayDimensions + { + internal int Rank { get; } + internal int [] Bounds { get; } + internal int TotalLength { get; } + public ArrayDimensions(int [] rank) + { + Rank = rank.Length; + Bounds = rank; + TotalLength = 1; + for (int i = 0 ; i < Rank ; i++) + TotalLength *= Bounds[i]; + } + + public override string ToString() + { + return $"{string.Join(", ", Bounds)}"; + } + internal string GetArrayIndexString(int idx) + { + if (idx < 0 || idx >= TotalLength) + return "Invalid Index"; + int boundLimit = 1; + int lastBoundLimit = 1; + int[] arrayStr = new int[Rank]; + int rankStart = 0; + while (idx > 0) + { + boundLimit = 1; + for (int i = Rank - 1; i >= rankStart; i--) + { + lastBoundLimit = boundLimit; + boundLimit *= Bounds[i]; + if (idx < boundLimit) + { + arrayStr[i] = (int)(idx / lastBoundLimit); + idx -= arrayStr[i] * lastBoundLimit; + rankStart = i; + break; + } + } + } + return $"{string.Join(", ", arrayStr)}"; + } + } + internal record MethodInfoWithDebugInformation(MethodInfo Info, int DebugId, string Name); internal class TypeInfoWithDebugInformation @@ -365,7 +412,7 @@ internal class TypeInfoWithDebugInformation public int DebugId { get; } public string Name { get; } public List FieldsList { get; set; } - public MonoBinaryReader PropertiesBinaryReader { get; set; } + public byte[] PropertiesBuffer { get; set; } public List TypeParamsOrArgsForGenericType { get; set; } public TypeInfoWithDebugInformation(TypeInfo typeInfo, int debugId, string name) @@ -378,7 +425,11 @@ public TypeInfoWithDebugInformation(TypeInfo typeInfo, int debugId, string name) internal class MonoBinaryReader : BinaryReader { - public MonoBinaryReader(Stream stream) : base(stream) {} + public bool HasError { get; } + public MonoBinaryReader(Stream stream, bool hasError = false) : base(stream) + { + HasError = hasError; + } internal static unsafe void PutBytesBE (byte *dest, byte *src, int count) { @@ -397,9 +448,10 @@ internal static unsafe void PutBytesBE (byte *dest, byte *src, int count) public override string ReadString() { var valueLen = ReadInt32(); - char[] value = new char[valueLen]; + byte[] value = new byte[valueLen]; Read(value, 0, valueLen); - return new string(value); + + return new string(Encoding.UTF8.GetChars(value, 0, valueLen)); } public unsafe long ReadLong() { @@ -654,9 +706,9 @@ internal class MonoSDBHelper private static int MINOR_VERSION = 61; private static int MAJOR_VERSION = 2; - private Dictionary methods = new(); - private Dictionary assemblies = new(); - private Dictionary types = new(); + private Dictionary methods; + private Dictionary assemblies; + private Dictionary types; internal Dictionary valueTypes = new Dictionary(); internal Dictionary pointerValues = new Dictionary(); @@ -671,12 +723,16 @@ public MonoSDBHelper(MonoProxy proxy, ILogger logger) { this.proxy = proxy; this.logger = logger; - this.store = null; + ResetStore(null); } - public void SetStore(DebugStore store) + public void ResetStore(DebugStore store) { this.store = store; + this.methods = new(); + this.assemblies = new(); + this.types = new(); + ClearCache(); } public async Task GetAssemblyInfo(SessionId sessionId, int assemblyId, CancellationToken token) @@ -700,7 +756,7 @@ public async Task GetAssemblyInfo(SessionId sessionId, int assembl return null; } } - asm.DebugId = assemblyId; + asm.SetDebugId(assemblyId); assemblies[assemblyId] = asm; return asm; } @@ -814,12 +870,12 @@ public async Task EnableReceiveRequests(SessionId sessionId, EventKind eve internal async Task SendDebuggerAgentCommandInternal(SessionId sessionId, int command_set, int command, MemoryStream parms, CancellationToken token) { Result res = await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommand(GetId(), command_set, command, Convert.ToBase64String(parms.ToArray())), token); - if (res.IsErr) { - throw new Exception($"SendDebuggerAgentCommand Error - {(CommandSet)command_set} - {command}"); + byte[] newBytes = Array.Empty(); + if (!res.IsErr) { + newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); } - byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); var retDebuggerCmd = new MemoryStream(newBytes); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd, res.IsErr); return retDebuggerCmdReader; } @@ -852,12 +908,12 @@ internal Task SendDebuggerAgentCommandWithParms(SessionId s internal async Task SendDebuggerAgentCommandWithParmsInternal(SessionId sessionId, int command_set, int command, MemoryStream parms, int type, string extraParm, CancellationToken token) { Result res = await proxy.SendMonoCommand(sessionId, MonoCommands.SendDebuggerAgentCommandWithParms(GetId(), command_set, command, Convert.ToBase64String(parms.ToArray()), parms.ToArray().Length, type, extraParm), token); - if (res.IsErr) { - throw new Exception("SendDebuggerAgentCommandWithParms Error"); + byte[] newBytes = Array.Empty(); + if (!res.IsErr) { + newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); } - byte[] newBytes = Convert.FromBase64String(res.Value?["result"]?["value"]?["value"]?.Value()); var retDebuggerCmd = new MemoryStream(newBytes); - var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd, res.IsErr); return retDebuggerCmdReader; } @@ -1210,18 +1266,21 @@ public async Task GetTypePropertiesReader(SessionId sessionId, if (typeInfo == null) return null; - if (typeInfo.PropertiesBinaryReader != null) + if (typeInfo.PropertiesBuffer != null) { - typeInfo.PropertiesBinaryReader.BaseStream.Seek(0, SeekOrigin.Begin); - return typeInfo.PropertiesBinaryReader; + var retDebuggerCmd = new MemoryStream(typeInfo.PropertiesBuffer); + var retDebuggerCmdReader = new MonoBinaryReader(retDebuggerCmd); + return retDebuggerCmdReader; } var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); commandParamsWriter.Write(typeId); - typeInfo.PropertiesBinaryReader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); - return typeInfo.PropertiesBinaryReader; + var reader = await SendDebuggerAgentCommand(sessionId, CmdType.GetProperties, commandParams, token); + typeInfo.PropertiesBuffer = reader.ReadBytes((int)reader.BaseStream.Length); + reader.BaseStream.Position = 0; + return reader; } public async Task> GetTypeFields(SessionId sessionId, int typeId, CancellationToken token) @@ -1387,7 +1446,8 @@ public async Task GetTypeName(SessionId sessionId, int typeId, Cancellat string className = await GetTypeNameOriginal(sessionId, typeId, token); className = className.Replace("+", "."); className = Regex.Replace(className, @"`\d+", ""); - className = className.Replace("[]", "__SQUARED_BRACKETS__"); + className = Regex.Replace(className, @"[[, ]+]", "__SQUARED_BRACKETS__"); + //className = className.Replace("[]", "__SQUARED_BRACKETS__"); className = className.Replace("[", "<"); className = className.Replace("]", ">"); className = className.Replace("__SQUARED_BRACKETS__", "[]"); @@ -1438,15 +1498,20 @@ public async Task GetStringValue(SessionId sessionId, int string_id, Can } return null; } - public async Task GetArrayLength(SessionId sessionId, int object_id, CancellationToken token) + public async Task GetArrayDimensions(SessionId sessionId, int object_id, CancellationToken token) { var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); commandParamsWriter.Write(object_id); var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetLength, commandParams, token); var length = retDebuggerCmdReader.ReadInt32(); - length = retDebuggerCmdReader.ReadInt32(); - return length; + var rank = new int[length]; + for (int i = 0 ; i < length; i++) + { + rank[i] = retDebuggerCmdReader.ReadInt32(); + retDebuggerCmdReader.ReadInt32(); //lower_bound + } + return new ArrayDimensions(rank); } public async Task> GetTypeIdFromObject(SessionId sessionId, int object_id, bool withParents, CancellationToken token) { @@ -1765,9 +1830,14 @@ public async Task CreateJObjectForString(SessionId sessionId, MonoBinar public async Task CreateJObjectForArray(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, CancellationToken token) { var objectId = retDebuggerCmdReader.ReadInt32(); - var value = await GetClassNameFromObject(sessionId, objectId, token); - var length = await GetArrayLength(sessionId, objectId, token); - return CreateJObject(null, "object", $"{value.ToString()}({length})", false, value.ToString(), "dotnet:array:" + objectId, null, "array"); + var className = await GetClassNameFromObject(sessionId, objectId, token); + var arrayType = className.ToString(); + var length = await GetArrayDimensions(sessionId, objectId, token); + if (arrayType.LastIndexOf('[') > 0) + arrayType = arrayType.Insert(arrayType.LastIndexOf('[')+1, length.ToString()); + if (className.LastIndexOf('[') > 0) + className = className.Insert(arrayType.LastIndexOf('[')+1, new string(',', length.Rank-1)); + return CreateJObject(null, "object", description : arrayType, writable : false, className.ToString(), "dotnet:array:" + objectId, null, subtype : length.Rank == 1 ? "array" : null); } public async Task CreateJObjectForObject(SessionId sessionId, MonoBinaryReader retDebuggerCmdReader, int typeIdFromAttribute, bool forDebuggerDisplayAttribute, CancellationToken token) @@ -2193,23 +2263,41 @@ public async Task GetValueTypeProxy(SessionId sessionId, int valueTypeId public async Task GetArrayValues(SessionId sessionId, int arrayId, CancellationToken token) { - var length = await GetArrayLength(sessionId, arrayId, token); + var dimensions = await GetArrayDimensions(sessionId, arrayId, token); var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); commandParamsWriter.Write(arrayId); commandParamsWriter.Write(0); - commandParamsWriter.Write(length); + commandParamsWriter.Write(dimensions.TotalLength); var retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdArray.GetValues, commandParams, token); JArray array = new JArray(); - for (int i = 0 ; i < length ; i++) + for (int i = 0 ; i < dimensions.TotalLength; i++) { - var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, i.ToString(), false, -1, false, token); + var var_json = await CreateJObjectForVariableValue(sessionId, retDebuggerCmdReader, dimensions.GetArrayIndexString(i), isOwn : false, -1, forDebuggerDisplayAttribute : false, token); array.Add(var_json); } return array; } - public async Task EnableExceptions(SessionId sessionId, string state, CancellationToken token) + + public async Task GetArrayValuesProxy(SessionId sessionId, int arrayId, CancellationToken token) + { + var length = await GetArrayDimensions(sessionId, arrayId, token); + var arrayProxy = JObject.FromObject(new + { + items = await GetArrayValues(sessionId, arrayId, token), + dimensionsDetails = length.Bounds + }); + return arrayProxy; + } + + public async Task EnableExceptions(SessionId sessionId, PauseOnExceptionsKind state, CancellationToken token) { + if (state == PauseOnExceptionsKind.Unset) + { + logger.LogDebug($"Trying to setPauseOnExceptions using status Unset"); + return false; + } + var commandParams = new MemoryStream(); var commandParamsWriter = new MonoBinaryWriter(commandParams); commandParamsWriter.Write((byte)EventKind.Exception); @@ -2217,14 +2305,16 @@ public async Task EnableExceptions(SessionId sessionId, string state, Canc commandParamsWriter.Write((byte)1); commandParamsWriter.Write((byte)ModifierKind.ExceptionOnly); commandParamsWriter.Write(0); //exc_class - if (state == "all") + if (state == PauseOnExceptionsKind.All) commandParamsWriter.Write((byte)1); //caught else commandParamsWriter.Write((byte)0); //caught - if (state == "uncaught" || state == "all") + + if (state == PauseOnExceptionsKind.Uncaught || state == PauseOnExceptionsKind.All) commandParamsWriter.Write((byte)1); //uncaught else commandParamsWriter.Write((byte)0); //uncaught + commandParamsWriter.Write((byte)1);//subclasses commandParamsWriter.Write((byte)0);//not_filtered_feature commandParamsWriter.Write((byte)0);//everything_else @@ -2280,10 +2370,16 @@ public async Task GetValuesFromDebuggerProxyAttribute(SessionId sessionI var assemblyNameArg = await GetFullAssemblyName(sessionId, assemblyIdArg, token); var classNameArg = await GetTypeNameOriginal(sessionId, genericTypeArgs[k], token); typeToSearch += classNameArg +", " + assemblyNameArg; + if (k + 1 < genericTypeArgs.Count) + typeToSearch += "], ["; + else + typeToSearch += "]"; } - typeToSearch += "]]"; + typeToSearch += "]"; typeToSearch += ", " + assemblyName; var genericTypeId = await GetTypeByName(sessionId, typeToSearch, token); + if (genericTypeId < 0) + return null; methodId = await GetMethodIdByName(sessionId, genericTypeId, ".ctor", token); } else @@ -2511,15 +2607,9 @@ public async Task SetVariableValue(SessionId sessionId, int thread_id, int JArray locals = new JArray(); retDebuggerCmdReader = await SendDebuggerAgentCommand(sessionId, CmdFrame.GetValues, commandParams, token); int etype = retDebuggerCmdReader.ReadByte(); - try - { - retDebuggerCmdReader = await SendDebuggerAgentCommandWithParms(sessionId, CmdFrame.SetValues, commandParams, etype, newValue, token); - } - catch (Exception) - { + retDebuggerCmdReader = await SendDebuggerAgentCommandWithParms(sessionId, CmdFrame.SetValues, commandParams, etype, newValue, token); + if (retDebuggerCmdReader.HasError) return false; - } - return true; } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs index dfe99aed5a7694..22447a87c88806 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/ArrayTests.cs @@ -198,6 +198,24 @@ public async Task InspectGenericValueTypeArrayLocals2(int line, int col, string frame_idx: frame_idx, use_cfo: use_cfo); + async Task GetObjectWithCFO(string objectId, JObject fn_args = null) + { + var fn_decl = "function () { return this; }"; + var cfo_args = JObject.FromObject(new + { + functionDeclaration = fn_decl, + objectId = objectId + }); + + if (fn_args != null) + cfo_args["arguments"] = fn_args; + + // callFunctionOn + var result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); + + return await GetProperties(result.Value["result"]["objectId"]?.Value(), fn_args); + } + async Task TestSimpleArrayLocals(int line, int col, string entry_method_name, string method_name, string etype_name, string local_var_name_prefix, object[] array, object[] array_elem_props, bool test_prev_frame = false, int frame_idx = 0, bool use_cfo = false) @@ -215,8 +233,8 @@ async Task TestSimpleArrayLocals(int line, int col, string entry_method_name, st var locals = await GetProperties(pause_location["callFrames"][frame_idx]["callFrameId"].Value()); Assert.Equal(4, locals.Count()); - CheckArray(locals, $"{local_var_name_prefix}_arr", $"{etype_name}[]", array?.Length ?? 0); - CheckArray(locals, $"{local_var_name_prefix}_arr_empty", $"{etype_name}[]", 0); + CheckArray(locals, $"{local_var_name_prefix}_arr", $"{etype_name}[]", $"{etype_name}[{array?.Length ?? 0}]"); + CheckArray(locals, $"{local_var_name_prefix}_arr_empty", $"{etype_name}[]", $"{etype_name}[0]"); CheckObject(locals, $"{local_var_name_prefix}_arr_null", $"{etype_name}[]", is_null: true); CheckBool(locals, "call_other", test_prev_frame); @@ -264,24 +282,6 @@ async Task TestSimpleArrayLocals(int line, int col, string entry_method_name, st var props = await GetObjectOnFrame(pause_location["callFrames"][frame_idx], $"{local_var_name_prefix}_arr_empty"); await CheckProps(props, new object[0], "${local_var_name_prefix}_arr_empty"); - - async Task GetObjectWithCFO(string objectId, JObject fn_args = null) - { - var fn_decl = "function () { return this; }"; - var cfo_args = JObject.FromObject(new - { - functionDeclaration = fn_decl, - objectId = objectId - }); - - if (fn_args != null) - cfo_args["arguments"] = fn_args; - - // callFunctionOn - var result = await cli.SendCommand("Runtime.callFunctionOn", cfo_args, token); - - return await GetProperties(result.Value["result"]["objectId"]?.Value(), fn_args); - } } [Theory] @@ -313,10 +313,10 @@ public async Task InspectObjectArrayMembers(bool use_cfo) await CheckProps(c_props, new { id = TString("c#id"), - ClassArrayProperty = TArray("DebuggerTests.SimpleClass[]", 3), - ClassArrayField = TArray("DebuggerTests.SimpleClass[]", 3), - PointsProperty = TArray("DebuggerTests.Point[]", 2), - PointsField = TArray("DebuggerTests.Point[]", 2) + ClassArrayProperty = TArray("DebuggerTests.SimpleClass[]", "DebuggerTests.SimpleClass[3]"), + ClassArrayField = TArray("DebuggerTests.SimpleClass[]", "DebuggerTests.SimpleClass[3]"), + PointsProperty = TArray("DebuggerTests.Point[]", "DebuggerTests.Point[2]"), + PointsField = TArray("DebuggerTests.Point[]", "DebuggerTests.Point[2]") }, "c" ); @@ -382,8 +382,8 @@ public async Task InspectValueTypeArrayLocalsStaticAsync(bool use_cfo) await CheckProps(frame_locals, new { call_other = TBool(false), - gvclass_arr = TArray("DebuggerTests.SimpleGenericStruct[]", 2), - gvclass_arr_empty = TArray("DebuggerTests.SimpleGenericStruct[]"), + gvclass_arr = TArray("DebuggerTests.SimpleGenericStruct[]", "DebuggerTests.SimpleGenericStruct[2]"), + gvclass_arr_empty = TArray("DebuggerTests.SimpleGenericStruct[]", "DebuggerTests.SimpleGenericStruct[0]"), gvclass_arr_null = TObject("DebuggerTests.SimpleGenericStruct[]", is_null: true), gvclass = TValueType("DebuggerTests.SimpleGenericStruct"), // BUG: this shouldn't be null! @@ -448,7 +448,7 @@ public async Task InspectValueTypeArrayLocalsInstanceAsync(bool use_cfo) { t1 = TObject("DebuggerTests.SimpleGenericStruct"), @this = TObject("DebuggerTests.ArrayTestsClass"), - point_arr = TArray("DebuggerTests.Point[]", 2), + point_arr = TArray("DebuggerTests.Point[]", "DebuggerTests.Point[2]"), point = TValueType("DebuggerTests.Point") }, "InspectValueTypeArrayLocalsInstanceAsync#locals"); @@ -642,6 +642,59 @@ public async Task InvalidAccessors() => await CheckInspectLocalsAtBreakpointSite AssertEqual("undefined", res.Value["result"]?["type"]?.ToString(), "Expected to get undefined result for non-existant accessor"); } }); + + [Theory] + [InlineData(false)] + [InlineData(true)] + public async Task InspectPrimitiveTypeMultiArrayLocals(bool use_cfo) + { + var debugger_test_loc = "dotnet://debugger-test.dll/debugger-array-test.cs"; + + var eval_expr = "window.setTimeout(function() { invoke_static_method (" + + $"'[debugger-test] DebuggerTests.MultiDimensionalArray:run'" + + "); }, 1);"; + var pause_location = await EvaluateAndCheck(eval_expr, debugger_test_loc, 343, 12, "run"); + + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + Assert.Equal(3, locals.Count()); + var int_arr_1 = !use_cfo ? + await GetProperties(locals[0]["value"]["objectId"].Value()) : + await GetObjectWithCFO((locals[0]["value"]["objectId"].Value())); + + CheckNumber(int_arr_1, "0", 0); + CheckNumber(int_arr_1, "1", 1); + var int_arr_2 = !use_cfo ? + await GetProperties(locals[1]["value"]["objectId"].Value()) : + await GetObjectWithCFO((locals[1]["value"]["objectId"].Value())); + CheckNumber(int_arr_2, "0, 0", 0); + CheckNumber(int_arr_2, "0, 1", 1); + CheckNumber(int_arr_2, "0, 2", 2); + CheckNumber(int_arr_2, "1, 0", 10); + CheckNumber(int_arr_2, "1, 1", 11); + CheckNumber(int_arr_2, "1, 2", 12); + + var int_arr_3 = !use_cfo ? + await GetProperties(locals[2]["value"]["objectId"].Value()) : + await GetObjectWithCFO((locals[2]["value"]["objectId"].Value())); + CheckNumber(int_arr_3, "0, 0, 0", 0); + CheckNumber(int_arr_3, "0, 0, 1", 1); + CheckNumber(int_arr_3, "0, 0, 2", 2); + CheckNumber(int_arr_3, "0, 1, 0", 10); + CheckNumber(int_arr_3, "0, 1, 1", 11); + CheckNumber(int_arr_3, "0, 1, 2", 12); + CheckNumber(int_arr_3, "0, 2, 0", 20); + CheckNumber(int_arr_3, "0, 2, 1", 21); + CheckNumber(int_arr_3, "0, 2, 2", 22); + CheckNumber(int_arr_3, "1, 0, 0", 100); + CheckNumber(int_arr_3, "1, 0, 1", 101); + CheckNumber(int_arr_3, "1, 0, 2", 102); + CheckNumber(int_arr_3, "1, 1, 0", 110); + CheckNumber(int_arr_3, "1, 1, 1", 111); + CheckNumber(int_arr_3, "1, 1, 2", 112); + CheckNumber(int_arr_3, "1, 2, 0", 120); + CheckNumber(int_arr_3, "1, 2, 1", 121); + CheckNumber(int_arr_3, "1, 2, 2", 122); + } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/AssignmentTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/AssignmentTests.cs index 1afa97939d5ef1..0601552db6b606 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/AssignmentTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/AssignmentTests.cs @@ -19,7 +19,7 @@ public class AssignmentTests : DebuggerTestBase { "MONO_TYPE_CHAR", TSymbol("0 '\u0000'"), TSymbol("97 'a'") }, { "MONO_TYPE_STRING", TString(default), TString("hello") }, { "MONO_TYPE_ENUM", TEnum("DebuggerTests.RGB", "Red"), TEnum("DebuggerTests.RGB", "Blue") }, - { "MONO_TYPE_ARRAY", TObject("byte[]", is_null: true), TArray("byte[]", 2) }, + { "MONO_TYPE_ARRAY", TObject("byte[]", is_null: true), TArray("byte[]", "byte[2]") }, { "MONO_TYPE_VALUETYPE", TValueType("DebuggerTests.Point"), TValueType("DebuggerTests.Point") }, { "MONO_TYPE_VALUETYPE2", TValueType("System.Decimal","0"), TValueType("System.Decimal", "1.1") }, { "MONO_TYPE_GENERICINST", TObject("System.Func", is_null: true), TDelegate("System.Func", "int Prepare ()") }, diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index db5fbf34b40c26..2c95d68eec9b22 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json.Linq; using System.IO; using Xunit; +using System.Threading; namespace DebuggerTests { @@ -131,11 +132,6 @@ public async Task CreateGoodBreakpointAndHit() { var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); - var eval_req = JObject.FromObject(new - { - expression = "window.setTimeout(function() { invoke_add(); }, 1);", - }); - await EvaluateAndCheck( "window.setTimeout(function() { invoke_add(); }, 1);", "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, @@ -448,5 +444,273 @@ await StepAndCheck(StepKind.Over, "dotnet://ApplyUpdateReferencedAssembly.dll/Me pause_location = await SendCommandAndCheck(JObject.FromObject(new { }), "Debugger.resume", "dotnet://ApplyUpdateReferencedAssembly.dll/MethodBody1.cs", 38, 8, "StaticMethod4"); locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); } + + [Fact] + public async Task ConditionalBreakpointInALoop() + { + var bp_conditional = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 4, condition:"i == 3"); + var bp_check = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 5); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] LoopClass:LoopToBreak'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 3); + } + ); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_check.Value["locations"][0]["lineNumber"].Value(), + bp_check.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak"); + } + + [Fact] + public async Task ConditionalBreakpointInALoopStopMoreThanOnce() + { + var bp_conditional = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 4, condition:"i % 3 == 0"); + var bp_check = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 5); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] LoopClass:LoopToBreak'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 0); + } + ); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 3); + }); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 6); + }); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 9); + }); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_check.Value["locations"][0]["lineNumber"].Value(), + bp_check.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak"); + } + + [Fact] + public async Task ConditionalBreakpointNoStopInALoop() + { + var bp_conditional = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 4, condition:"i == \"10\""); + var bp_check = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 5); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] LoopClass:LoopToBreak'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_check.Value["locations"][0]["lineNumber"].Value(), + bp_check.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak" + ); + } + + [Fact] + public async Task ConditionalBreakpointNotBooleanInALoop() + { + var bp_conditional = await SetBreakpointInMethod("debugger-test.dll", "LoopClass", "LoopToBreak", 4, condition:"i + 4"); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] LoopClass:LoopToBreak'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 0); + } + ); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 1); + }); + + await SendCommandAndCheck(null, "Debugger.resume", + null, + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "LoopToBreak", + locals_fn: (locals) => + { + CheckNumber(locals, "i", 2); + }); + } + + [Fact] + public async Task CreateGoodBreakpointAndHitGoToNonWasmPageComeBackAndHitAgain() + { + var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_add(); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "IntAdd"); + Assert.Equal("other", pause_location["reason"]?.Value()); + Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); + + var top_frame = pause_location["callFrames"][0]; + Assert.Equal("IntAdd", top_frame["functionName"].Value()); + Assert.Contains("debugger-test.cs", top_frame["url"].Value()); + + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]); + + //now check the scope + var scope = top_frame["scopeChain"][0]; + Assert.Equal("local", scope["type"]); + Assert.Equal("IntAdd", scope["name"]); + + Assert.Equal("object", scope["object"]["type"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]); + + await cli.SendCommand("Debugger.resume", null, token); + + var run_method = JObject.FromObject(new + { + expression = "window.setTimeout(function() { load_non_wasm_page(); }, 1);" + }); + await cli.SendCommand("Runtime.evaluate", run_method, token); + await Task.Delay(1000, token); + + run_method = JObject.FromObject(new + { + expression = "window.setTimeout(function() { reload_wasm_page(); }, 1);" + }); + await cli.SendCommand("Runtime.evaluate", run_method, token); + await insp.WaitFor(Inspector.READY); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_add(); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "IntAdd", + wait_for_event_fn: (pause_location) => + { + Assert.Equal("other", pause_location["reason"]?.Value()); + Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); + + var top_frame = pause_location["callFrames"][0]; + Assert.Equal("IntAdd", top_frame["functionName"].Value()); + Assert.Contains("debugger-test.cs", top_frame["url"].Value()); + + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]); + + //now check the scope + var scope = top_frame["scopeChain"][0]; + Assert.Equal("local", scope["type"]); + Assert.Equal("IntAdd", scope["name"]); + + Assert.Equal("object", scope["object"]["type"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]); + return Task.CompletedTask; + } + ); + } + + [Fact] + public async Task CreateGoodBreakpointAndHitGoToWasmPageWithoutAssetsComeBackAndHitAgain() + { + var bp = await SetBreakpoint("dotnet://debugger-test.dll/debugger-test.cs", 10, 8); + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_add(); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "IntAdd"); + Assert.Equal("other", pause_location["reason"]?.Value()); + Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); + + var top_frame = pause_location["callFrames"][0]; + Assert.Equal("IntAdd", top_frame["functionName"].Value()); + Assert.Contains("debugger-test.cs", top_frame["url"].Value()); + + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]); + + //now check the scope + var scope = top_frame["scopeChain"][0]; + Assert.Equal("local", scope["type"]); + Assert.Equal("IntAdd", scope["name"]); + + Assert.Equal("object", scope["object"]["type"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]); + + await cli.SendCommand("Debugger.resume", null, token); + + var run_method = JObject.FromObject(new + { + expression = "window.setTimeout(function() { load_wasm_page_without_assets(); }, 1);" + }); + await cli.SendCommand("Runtime.evaluate", run_method, token); + await Task.Delay(1000, token); + run_method = JObject.FromObject(new + { + expression = "window.setTimeout(function() { reload_wasm_page(); }, 1);" + }); + await cli.SendCommand("Runtime.evaluate", run_method, token); + await Task.Delay(1000, token); + await insp.WaitFor(Inspector.READY); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_add(); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 10, 8, + "IntAdd", + wait_for_event_fn: async (pause_location) => + { + Assert.Equal("other", pause_location["reason"]?.Value()); + Assert.Equal(bp.Value["breakpointId"]?.ToString(), pause_location["hitBreakpoints"]?[0]?.Value()); + + var top_frame = pause_location["callFrames"][0]; + Assert.Equal("IntAdd", top_frame["functionName"].Value()); + Assert.Contains("debugger-test.cs", top_frame["url"].Value()); + + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, top_frame["functionLocation"]); + + //now check the scope + var scope = top_frame["scopeChain"][0]; + Assert.Equal("local", scope["type"]); + Assert.Equal("IntAdd", scope["name"]); + + Assert.Equal("object", scope["object"]["type"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 8, 4, scripts, scope["startLocation"]); + CheckLocation("dotnet://debugger-test.dll/debugger-test.cs", 14, 4, scripts, scope["endLocation"]); + await Task.CompletedTask; + } + ); + } + } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs index 5b101f0236d040..e80fe46224695e 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/CallFunctionOnTests.cs @@ -361,7 +361,7 @@ public async Task RunOnJSObject(bool roundtrip) => await RunCallFunctionOn( await CheckProps(obj_own_val, new { a_obj = TObject("Object"), - b_arr = TArray("Array", 2) + b_arr = TArray("Array", "Array(2)") }, "obj_own"); }); @@ -641,7 +641,7 @@ public async Task PropertyGettersTest(string eval_fn, string method_name, int li // Check arrays through getters res = await InvokeGetter(obj, get_args_fn(new[] { "IntArray" }), cfo_fn); - await CheckValue(res.Value["result"], TArray("int[]", 2), $"{local_name}.IntArray"); + await CheckValue(res.Value["result"], TArray("int[]", "int[2]"), $"{local_name}.IntArray"); { var arr_elems = await GetProperties(res.Value["result"]?["objectId"]?.Value()); var exp_elems = new[] @@ -654,7 +654,7 @@ public async Task PropertyGettersTest(string eval_fn, string method_name, int li } res = await InvokeGetter(obj, get_args_fn(new[] { "DTArray" }), cfo_fn); - await CheckValue(res.Value["result"], TArray("System.DateTime[]", 2), $"{local_name}.DTArray"); + await CheckValue(res.Value["result"], TArray("System.DateTime[]", "System.DateTime[2]"), $"{local_name}.DTArray"); { var dt0 = new DateTime(6, 7, 8, 9, 10, 11); var dt1 = new DateTime(1, 2, 3, 4, 5, 6); @@ -944,7 +944,7 @@ async Task CheckCFOResult(Result result) if (res_array_len < 0) await CheckValue(result.Value["result"], TObject("Object"), $"cfo-res"); else - await CheckValue(result.Value["result"], TArray("Array", res_array_len), $"cfo-res"); + await CheckValue(result.Value["result"], TArray("Array", $"Array({res_array_len})"), $"cfo-res"); } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/CustomViewTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/CustomViewTests.cs index 09bee325d72c43..06516155b7d399 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/CustomViewTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/CustomViewTests.cs @@ -8,6 +8,7 @@ using Newtonsoft.Json.Linq; using System.Threading; using Xunit; +using System.Collections.Generic; namespace DebuggerTests { @@ -17,7 +18,7 @@ public class CustomViewTests : DebuggerTestBase [Fact] public async Task UsingDebuggerDisplay() { - var bp = await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.DebuggerCustomViewTest", "run", 6); + var bp = await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.DebuggerCustomViewTest", "run", 15); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.DebuggerCustomViewTest:run'); }, 1);", "dotnet://debugger-test.dll/debugger-custom-view-test.cs", @@ -29,12 +30,14 @@ public async Task UsingDebuggerDisplay() CheckObject(locals, "a", "DebuggerTests.WithDisplayString", description:"Some one Value 2 End"); CheckObject(locals, "c", "DebuggerTests.DebuggerDisplayMethodTest", description: "First Int:32 Second Int:43"); CheckObject(locals, "myList", "System.Collections.Generic.List", description: "Count = 4"); + CheckObject(locals, "person1", "DebuggerTests.Person", description: "FirstName: Anton, SurName: Mueller, Age: 44"); + CheckObject(locals, "person2", "DebuggerTests.Person", description: "FirstName: Lisa, SurName: Müller, Age: 41"); } [Fact] public async Task UsingDebuggerTypeProxy() { - var bp = await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.DebuggerCustomViewTest", "run", 6); + var bp = await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.DebuggerCustomViewTest", "run", 15); var pause_location = await EvaluateAndCheck( "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.DebuggerCustomViewTest:run'); }, 1);", "dotnet://debugger-test.dll/debugger-custom-view-test.cs", @@ -48,14 +51,54 @@ public async Task UsingDebuggerTypeProxy() var props = await GetObjectOnFrame(frame, "myList"); Assert.Equal(1, props.Count()); - CheckArray(props, "Items", "int[]", 4); + CheckArray(props, "Items", "int[]", "int[4]"); CheckObject(locals, "b", "DebuggerTests.WithProxy", description:"DebuggerTests.WithProxy"); props = await GetObjectOnFrame(frame, "b"); CheckString(props, "Val2", "one"); + CheckObject(locals, "openWith", "System.Collections.Generic.Dictionary", description: "Count = 3"); + props = await GetObjectOnFrame(frame, "openWith"); + Assert.Equal(1, props.Count()); + await EvaluateOnCallFrameAndCheck(frame["callFrameId"].Value(), ("listToTestToList.ToList()", TObject("System.Collections.Generic.List", description: "Count = 11"))); + + } + + [Fact] + public async Task UsingDebuggerDisplayConcurrent() + { + async Task CheckProperties(JObject pause_location) + { + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + var l = GetAndAssertObjectWithName(locals, "myList"); + var val = l["value"]; + if (val["description"].Value() != "Count = 0") + return false; + return true; + } + + var bp = await SetBreakpointInMethod("debugger-test.dll", "DebuggerTests.DebuggerCustomViewTest2", "run", 2); + var pause_location = await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.DebuggerCustomViewTest2:run'); }, 1);", + "dotnet://debugger-test.dll/debugger-custom-view-test.cs", + bp.Value["locations"][0]["lineNumber"].Value(), + bp.Value["locations"][0]["columnNumber"].Value(), + "run"); + + pause_location = await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-custom-view-test.cs", bp.Value["locations"][0]["lineNumber"].Value()+2, bp.Value["locations"][0]["columnNumber"].Value(), "run"); + + List> tasks = new(); + for (int i = 0 ; i < 10; i++) + { + var task = CheckProperties(pause_location); + tasks.Add(task); + } + foreach(Task task in tasks) + { + Assert.True(task.Result); + } } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs index 1d30086b6b2d9c..fb4c0cf63f05e8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DebuggerTestBase.cs @@ -352,10 +352,10 @@ internal JToken CheckEnum(JToken locals, string name, string class_name, string return l; } - internal void CheckArray(JToken locals, string name, string class_name, int length) + internal void CheckArray(JToken locals, string name, string class_name, string description) => CheckValue( GetAndAssertObjectWithName(locals, name)["value"], - TArray(class_name, length), name).Wait(); + TArray(class_name, description), name).Wait(); internal JToken GetAndAssertObjectWithName(JToken obj, string name, string label = "") { @@ -974,7 +974,7 @@ internal static JObject TObject(string className, string description = null, boo JObject.FromObject(new { type = "object", className = className, description = description ?? className, subtype = is_null ? "null" : null }) : JObject.FromObject(new { type = "object", className = className, description = description ?? className }); - internal static JObject TArray(string className, int length = 0) => JObject.FromObject(new { type = "object", className = className, description = $"{className}({length})", subtype = "array" }); + internal static JObject TArray(string className, string description) => JObject.FromObject(new { type = "object", className, description, subtype = "array" }); internal static JObject TBool(bool value) => JObject.FromObject(new { type = "boolean", value = @value, description = @value ? "true" : "false" }); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/DelegateTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/DelegateTests.cs index 2fc0fb52ce99f9..cdbee2079e72aa 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/DelegateTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/DelegateTests.cs @@ -32,19 +32,19 @@ await CheckInspectLocalsAtBreakpointSite( { fn_func = TDelegate("System.Func", "bool |(Math)"), fn_func_null = TObject("System.Func", is_null: true), - fn_func_arr = TArray("System.Func[]", 1), + fn_func_arr = TArray("System.Func[]", "System.Func[1]"), fn_del = TDelegate("Math.IsMathNull", "bool IsMathNullDelegateTarget (Math)"), fn_del_null = TObject("Math.IsMathNull", is_null: true), - fn_del_arr = TArray("Math.IsMathNull[]", 1), + fn_del_arr = TArray("Math.IsMathNull[]", "Math.IsMathNull[1]"), // Unused locals fn_func_unused = TDelegate("System.Func", "bool |(Math)"), fn_func_null_unused = TObject("System.Func", is_null: true), - fn_func_arr_unused = TArray("System.Func[]", 1), + fn_func_arr_unused = TArray("System.Func[]", "System.Func[1]"), fn_del_unused = TDelegate("Math.IsMathNull", "bool IsMathNullDelegateTarget (Math)"), fn_del_null_unused = TObject("Math.IsMathNull", is_null: true), - fn_del_arr_unused = TArray("Math.IsMathNull[]", 1), + fn_del_arr_unused = TArray("Math.IsMathNull[]", "Math.IsMathNull[1]"), res = TBool(false), m_obj = TObject("Math") @@ -105,7 +105,7 @@ public async Task InspectDelegateSignaturesWithFunc(int frame, int line, int col fn_func_null = TObject("System.Func>, Math.GenericStruct>", is_null: true), fn_func_only_ret = TDelegate("System.Func", "bool |()"), - fn_func_arr = TArray("System.Func>, Math.GenericStruct>[]", 1), + fn_func_arr = TArray("System.Func>, Math.GenericStruct>[]", "System.Func>, Math.GenericStruct>[1]"), fn_del = TDelegate("Math.DelegateForSignatureTest", "Math.GenericStruct DelegateTargetForSignatureTest (Math,Math.GenericStruct>)"), @@ -114,16 +114,16 @@ public async Task InspectDelegateSignaturesWithFunc(int frame, int line, int col "Math.GenericStruct |(Math,Math.GenericStruct>)"), fn_del_null = TObject("Math.DelegateForSignatureTest", is_null: true), - fn_del_arr = TArray("Math.DelegateForSignatureTest[]", 2), + fn_del_arr = TArray("Math.DelegateForSignatureTest[]", "Math.DelegateForSignatureTest[2]"), m_obj = TObject("Math"), gs_gs = TValueType("Math.GenericStruct>"), fn_void_del = TDelegate("Math.DelegateWithVoidReturn", "void DelegateTargetWithVoidReturn (Math.GenericStruct)"), - fn_void_del_arr = TArray("Math.DelegateWithVoidReturn[]", 1), + fn_void_del_arr = TArray("Math.DelegateWithVoidReturn[]", "Math.DelegateWithVoidReturn[1]"), fn_void_del_null = TObject("Math.DelegateWithVoidReturn", is_null: true), gs = TValueType("Math.GenericStruct"), - rets = TArray("Math.GenericStruct[]", 6) + rets = TArray("Math.GenericStruct[]", "Math.GenericStruct[6]") }, "locals"); await CompareObjectPropertiesFor(locals, "fn_func_arr", new[] @@ -176,7 +176,7 @@ public async Task ActionTSignatureTest(int frame, int line, int col, string bp_m fn_action_null = TObject("System.Action>", is_null: true), - fn_action_arr = TArray("System.Action>[]", 3), + fn_action_arr = TArray("System.Action>[]", "System.Action>[3]"), gs = TValueType("Math.GenericStruct"), }, "locals"); @@ -212,8 +212,8 @@ public async Task NestedDelegatesTest(int frame, int line, int col, string bp_me fn_func = TDelegate("System.Func, bool>", "bool |(Func)"), fn_func_null = TObject("System.Func, bool>", is_null: true), - fn_func_arr = TArray("System.Func, bool>[]", 1), - fn_del_arr = TArray("System.Func, bool>[]", 1), + fn_func_arr = TArray("System.Func, bool>[]", "System.Func, bool>[1]"), + fn_del_arr = TArray("System.Func, bool>[]", "System.Func, bool>[1]"), m_obj = TObject("Math"), fn_del_null = TObject("System.Func, bool>", is_null: true), @@ -253,7 +253,7 @@ public async Task DelegatesAsMethodArgsTest(int frame, int line, int col, string await CheckProps(locals, new { @this = TObject("Math"), - dst_arr = TArray("Math.DelegateForSignatureTest[]", 2), + dst_arr = TArray("Math.DelegateForSignatureTest[]", "Math.DelegateForSignatureTest[2]"), fn_func = TDelegate("System.Func", "bool |(char[])"), fn_action = TDelegate("System.Action[]>", @@ -284,7 +284,7 @@ public async Task MethodWithDelegatesAsyncTest(bool use_cfo) => await CheckInspe await CheckProps(locals, new { @this = TObject("Math"), - _dst_arr = TArray("Math.DelegateForSignatureTest[]", 2), + _dst_arr = TArray("Math.DelegateForSignatureTest[]", "Math.DelegateForSignatureTest[2]"), _fn_func = TDelegate("System.Func", "bool |(char[])"), _fn_action = TDelegate("System.Action[]>", diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs index 0b613dcca3370a..724648ccee9518 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/EvaluateOnCallFrameTests.cs @@ -641,6 +641,28 @@ await EvaluateOnCallFrameFail(id, ); }); + [Fact] + public async Task EvaluateStaticAttributeInAssemblyNotRelatedButLoaded() => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateTestsClass/TestEvaluate", "EvaluateLocalsFromAnotherAssembly", 5, "EvaluateLocalsFromAnotherAssembly", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateTestsClass:EvaluateLocalsFromAnotherAssembly'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrameAndCheck(id, + ("DebuggerTests.ClassToBreak.valueToCheck", TNumber(10))); + }); + + [Fact] + public async Task EvaluateLocalObjectFromAssemblyNotRelatedButLoaded() + => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTests.EvaluateTestsClass/TestEvaluate", "EvaluateLocalsFromAnotherAssembly", 5, "EvaluateLocalsFromAnotherAssembly", + "window.setTimeout(function() { invoke_static_method ('[debugger-test] DebuggerTests.EvaluateTestsClass:EvaluateLocalsFromAnotherAssembly'); })", + wait_for_event_fn: async (pause_location) => + { + var id = pause_location["callFrames"][0]["callFrameId"].Value(); + await EvaluateOnCallFrameAndCheck(id, + ("a.valueToCheck", TNumber(20))); + }); } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs index eb0ebe0cc0d540..33dbd2b6db64f8 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/ExceptionTests.cs @@ -232,10 +232,11 @@ await CheckValue(pause_location["data"], JObject.FromObject(new CheckString(exception_members, "message", "not implemented uncaught"); } - [Fact] - public async Task ExceptionTestAllWithReload() + [Theory] + [InlineData("[debugger-test] DebuggerTests.ExceptionTestsClassDefault:TestExceptions", "System.Exception", 76)] + [InlineData("[debugger-test] DebuggerTests.ExceptionTestsClass:TestExceptions", "DebuggerTests.CustomException", 28)] + public async Task ExceptionTestAllWithReload(string entry_method_name, string class_name, int line_number) { - string entry_method_name = "[debugger-test] DebuggerTests.ExceptionTestsClass:TestExceptions"; var debugger_test_loc = "dotnet://debugger-test.dll/debugger-exception-test.cs"; await SetPauseOnException("all"); @@ -255,7 +256,7 @@ public async Task ExceptionTestAllWithReload() i++; } - + var eval_expr = "window.setTimeout(function() { invoke_static_method (" + $"'{entry_method_name}'" + "); }, 1);"; @@ -270,29 +271,31 @@ await CheckValue(pause_location["data"], JObject.FromObject(new { type = "object", subtype = "error", - className = "DebuggerTests.CustomException", - uncaught = false + className = class_name, + uncaught = false, + description = "not implemented caught" }), "exception0.data"); var exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", "not implemented caught"); + CheckString(exception_members, "_message", "not implemented caught"); pause_location = await WaitForManagedException(null); AssertEqual("run", pause_location["callFrames"]?[0]?["functionName"]?.Value(), "pause1"); //stop in the uncaught exception - CheckLocation(debugger_test_loc, 28, 16, scripts, pause_location["callFrames"][0]["location"]); + CheckLocation(debugger_test_loc, line_number, 16, scripts, pause_location["callFrames"][0]["location"]); await CheckValue(pause_location["data"], JObject.FromObject(new { type = "object", subtype = "error", - className = "DebuggerTests.CustomException", - uncaught = true + className = class_name, + uncaught = true, + description = "not implemented uncaught" }), "exception1.data"); exception_members = await GetProperties(pause_location["data"]["objectId"]?.Value()); - CheckString(exception_members, "message", "not implemented uncaught"); + CheckString(exception_members, "_message", "not implemented uncaught"); } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/PointerTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/PointerTests.cs index ee703b29648bb1..891eea7352c8aa 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/PointerTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/PointerTests.cs @@ -81,7 +81,7 @@ public async Task InspectLocalPointerArrays(string eval_fn, string type, string var dt = new DateTime(5, 6, 7, 8, 9, 10); await CheckProps(locals, new { - ipa = TArray("int*[]", 3) + ipa = TArray("int*[]", "int*[3]") }, "locals", num_fields: 26); var ipa_elems = await CompareObjectPropertiesFor(locals, "ipa", new[] @@ -112,7 +112,7 @@ public async Task InspectLocalDoublePointerToPrimitiveTypeArrays(string eval_fn, var dt = new DateTime(5, 6, 7, 8, 9, 10); await CheckProps(locals, new { - ippa = TArray("int**[]", 5) + ippa = TArray("int**[]", "int**[5]") }, "locals", num_fields: 26); var ippa_elems = await CompareObjectPropertiesFor(locals, "ippa", new[] @@ -223,7 +223,7 @@ public async Task InspectLocalPointersToValueTypeArrays(string eval_fn, string t var dt = new DateTime(5, 6, 7, 8, 9, 10); await CheckProps(locals, new { - dtpa = TArray("System.DateTime*[]", 2) + dtpa = TArray("System.DateTime*[]", "System.DateTime*[2]") }, "locals", num_fields: 26); // dtpa @@ -256,7 +256,7 @@ public async Task InspectLocalPointersToGenericValueTypeArrays(string eval_fn, s var dt = new DateTime(5, 6, 7, 8, 9, 10); await CheckProps(locals, new { - gspa = TArray("DebuggerTests.GenericStructWithUnmanagedT*[]", 3), + gspa = TArray("DebuggerTests.GenericStructWithUnmanagedT*[]", "DebuggerTests.GenericStructWithUnmanagedT*[3]"), }, "locals", num_fields: 26); // dtpa @@ -323,7 +323,7 @@ public async Task InspectLocalDoublePointersToValueTypeArrays(string eval_fn, st var dt = new DateTime(5, 6, 7, 8, 9, 10); await CheckProps(locals, new { - dtppa = TArray("System.DateTime**[]", 3), + dtppa = TArray("System.DateTime**[]", "System.DateTime**[3]"), }, "locals", num_fields: 26); // DateTime**[] dtppa = new DateTime**[] { &dtp, &dtp_null, null }; @@ -395,8 +395,8 @@ public async Task InspectPrimitiveTypePointersAsMethodArgs(string eval_fn, strin { ip = TPointer("int*"), ipp = TPointer("int**"), - ipa = TArray("int*[]", 3), - ippa = TArray("int**[]", 5) + ipa = TArray("int*[]", "int*[3]"), + ippa = TArray("int**[]", "int**[5]") }, "locals", num_fields: 8); // ip @@ -468,8 +468,8 @@ public async Task InspectValueTypePointersAsMethodArgs(string eval_fn, string ty { dtp = TPointer("System.DateTime*"), dtpp = TPointer("System.DateTime**"), - dtpa = TArray("System.DateTime*[]", 2), - dtppa = TArray("System.DateTime**[]", 3) + dtpa = TArray("System.DateTime*[]", "System.DateTime*[2]"), + dtppa = TArray("System.DateTime**[]", "System.DateTime**[3]") }, "locals", num_fields: 8); // *dtp diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs index e64348bc675eb0..e1a4a46fd83ea4 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs @@ -354,7 +354,7 @@ public async Task InspectLocalsInAsyncMethods(bool use_cfo) CheckObject(locals, "this", "Math.NestedInMath"); //FIXME: check fields CheckValueType(locals, "ss", "Math.SimpleStruct"); - CheckArray(locals, "ss_arr", "Math.SimpleStruct[]", 0); + CheckArray(locals, "ss_arr", "Math.SimpleStruct[]", "Math.SimpleStruct[0]"); // TODO: struct fields } ); @@ -584,7 +584,7 @@ async Task CheckArrayElements(JToken pause_location, DateTime dt) var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); await CheckProps(locals, new { - ssta = TArray("DebuggerTests.StructForToStringTests[]", 1) + ssta = TArray("DebuggerTests.StructForToStringTests[]", "DebuggerTests.StructForToStringTests[1]") }, "locals"); var ssta = await GetObjectOnLocals(locals, "ssta"); @@ -928,5 +928,25 @@ await EvaluateAndCheck( await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 719, 8, "MoveNext"); await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 720, 4, "MoveNext"); } + + [Fact] + public async Task CheckResetFrameNumberForEachStep() + { + var bp_conditional = await SetBreakpointInMethod("debugger-test.dll", "SteppingInto", "MethodToStep", 1); + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] SteppingInto:MethodToStep'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", + bp_conditional.Value["locations"][0]["lineNumber"].Value(), + bp_conditional.Value["locations"][0]["columnNumber"].Value(), + "MethodToStep" + ); + var pause_location = await StepAndCheck(StepKind.Into, "dotnet://debugger-test.dll/debugger-test.cs", 799, 4, "Increment"); + pause_location = await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 800, 8, "Increment"); + Assert.Equal(pause_location["callFrames"][0]["callFrameId"], "dotnet:scope:1"); + pause_location = await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 801, 8, "Increment"); + Assert.Equal(pause_location["callFrames"][0]["callFrameId"], "dotnet:scope:1"); + pause_location = await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", 806, 8, "Increment"); + Assert.Equal(pause_location["callFrames"][0]["callFrameId"], "dotnet:scope:1"); + } } } diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs index 548b012901a5a3..9a7879190055d2 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs @@ -140,7 +140,7 @@ await CheckInspectLocalsAtBreakpointSite( str_spaces, str_esc, - strings = TArray("string[]", 4) + strings = TArray("string[]", "string[4]") }, "locals"); var strings_arr = await GetObjectOnLocals(locals, "strings"); @@ -204,14 +204,14 @@ await CheckInspectLocalsAtBreakpointSite( CheckObject(locals, "list", "System.Collections.Generic.Dictionary", description: "Count = 0"); CheckObject(locals, "list_null", "System.Collections.Generic.Dictionary", is_null: true); - CheckArray(locals, "list_arr", "System.Collections.Generic.Dictionary[]", 1); + CheckArray(locals, "list_arr", "System.Collections.Generic.Dictionary[]", "System.Collections.Generic.Dictionary[1]"); CheckObject(locals, "list_arr_null", "System.Collections.Generic.Dictionary[]", is_null: true); // Unused locals CheckObject(locals, "list_unused", "System.Collections.Generic.Dictionary", description: "Count = 0"); CheckObject(locals, "list_null_unused", "System.Collections.Generic.Dictionary", is_null: true); - CheckArray(locals, "list_arr_unused", "System.Collections.Generic.Dictionary[]", 1); + CheckArray(locals, "list_arr_unused", "System.Collections.Generic.Dictionary[]", "System.Collections.Generic.Dictionary[1]"); CheckObject(locals, "list_arr_null_unused", "System.Collections.Generic.Dictionary[]", is_null: true); } ); @@ -367,7 +367,7 @@ public async Task InspectBoxedLocals(string method_name, bool is_async) => await o_n_dt = TDateTime(dt), o_null = TObject("object", is_null: true), - o_ia = TArray("int[]", 2), + o_ia = TArray("int[]", "int[2]"), }, "locals"); foreach (var name in new[] { "n_gs", "o_gs", "o_n_gs" }) @@ -541,7 +541,7 @@ public async Task InspectLocalsForToStringDescriptions(int line, int col, string ts = TValueType("System.TimeSpan", ts.ToString()), dec = TValueType("System.Decimal", "123987123"), guid = TValueType("System.Guid", "3D36E07E-AC90-48C6-B7EC-A481E289D014"), - dts = TArray("System.DateTime[]", 2), + dts = TArray("System.DateTime[]", "System.DateTime[2]"), obj = TObject("DebuggerTests.ClassForToStringTests"), sst = TObject("DebuggerTests.StructForToStringTests") }, "locals#0"); @@ -712,7 +712,7 @@ public async Task PreviousFrameForAReflectedCall() => await CheckInspectLocalsAt mi = TObject("System.Reflection.RuntimeMethodInfo"), //this is what is returned when debugging desktop apps using VS dt = TDateTime(new DateTime(4210, 3, 4, 5, 6, 7)), i = TNumber(4), - strings = TArray("string[]", 1), + strings = TArray("string[]", "string[1]"), cs = TValueType("DebuggerTests.GetPropertiesTests.CloneableStruct"), num = TNumber(10), @@ -845,6 +845,49 @@ public async Task InspectTaskAtLocals() => await CheckInspectLocalsAtBreakpointS }, "t_props", num_fields: 53); }); + + [Fact] + public async Task InspectLocalsWithIndexAndPositionWithDifferentValues() //https://github.com/xamarin/xamarin-android/issues/6161 + { + await EvaluateAndCheck( + "window.setTimeout(function() { invoke_static_method('[debugger-test] MainPage:CallSetValue'); }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 758, 16, + "set_SomeValue", + locals_fn: (locals) => + { + CheckNumber(locals, "view", 150); + } + ); + } + + [Fact] + public async Task InspectLocalsUsingClassFromLibraryUsingDebugTypeFull() + { + byte[] bytes = File.ReadAllBytes(Path.Combine(DebuggerTestAppPath, "debugger-test-with-full-debug-type.dll")); + string asm_base64 = Convert.ToBase64String(bytes); + + string pdb_base64 = null; + bytes = File.ReadAllBytes(Path.Combine(DebuggerTestAppPath, "debugger-test-with-full-debug-type.pdb")); + pdb_base64 = Convert.ToBase64String(bytes); + + var expression = $"{{ let asm_b64 = '{asm_base64}'; let pdb_b64 = '{pdb_base64}'; invoke_static_method('[debugger-test] DebugTypeFull:CallToEvaluateLocal', asm_b64, pdb_b64); }}"; + + await EvaluateAndCheck( + "window.setTimeout(function() {" + expression + "; }, 1);", + "dotnet://debugger-test.dll/debugger-test.cs", 818, 8, + "CallToEvaluateLocal", + wait_for_event_fn: async (pause_location) => + { + var a_props = await GetObjectOnFrame(pause_location["callFrames"][0], "a"); + await CheckProps(a_props, new + { + a = TNumber(10), + b = TNumber(20), + c = TNumber(30) + }, "a"); + } + ); + } //TODO add tests covering basic stepping behavior as step in/out/over } } diff --git a/src/mono/wasm/debugger/tests/Directory.Build.props b/src/mono/wasm/debugger/tests/Directory.Build.props index 0cff1f10a52d40..ff8864839daf17 100644 --- a/src/mono/wasm/debugger/tests/Directory.Build.props +++ b/src/mono/wasm/debugger/tests/Directory.Build.props @@ -4,6 +4,7 @@ $(AspNetCoreAppCurrent) Library + true Debug Release diff --git a/src/mono/wasm/debugger/tests/debugger-test-with-full-debug-type/debugger-test-with-full-debug-type.csproj b/src/mono/wasm/debugger/tests/debugger-test-with-full-debug-type/debugger-test-with-full-debug-type.csproj new file mode 100644 index 00000000000000..5eb1be9d8ea299 --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test-with-full-debug-type/debugger-test-with-full-debug-type.csproj @@ -0,0 +1,5 @@ + + + full + + \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/debugger-test-with-full-debug-type/test.cs b/src/mono/wasm/debugger/tests/debugger-test-with-full-debug-type/test.cs new file mode 100644 index 00000000000000..64609af24a547f --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test-with-full-debug-type/test.cs @@ -0,0 +1,20 @@ +using System; + +namespace DebuggerTests +{ + public class ClassToInspectWithDebugTypeFull + { + int a; + int b; + int c; + public ClassToInspectWithDebugTypeFull() + { + a = 10; + b = 20; + c = 30; + Console.WriteLine(a); + Console.WriteLine(b); + Console.WriteLine(c); + } + } +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/debugger-test-with-source-link/test.cs b/src/mono/wasm/debugger/tests/debugger-test-with-source-link/test.cs index af90df3e9a05f4..53b80df37033bc 100644 --- a/src/mono/wasm/debugger/tests/debugger-test-with-source-link/test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test-with-source-link/test.cs @@ -8,5 +8,14 @@ public static int TestBreakpoint() { return 50; } + public static int valueToCheck = 10; } -} + public class ClassToCheckFieldValue + { + public int valueToCheck; + public ClassToCheckFieldValue() + { + valueToCheck = 20; + } + } +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-array-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-array-test.cs index 26acccf68dc767..f1a2b41bd18a48 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-array-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-array-test.cs @@ -305,4 +305,44 @@ public static void run() new Point { X = 90, Y = -4, Id = "point#Id", Color = RGB.Green }.GenericInstanceMethod(sc); } } + public class MultiDimensionalArray + { + public static void run() + { + var int_arr_1 = new int[2]; + int_arr_1[0] = 0; + int_arr_1[1] = 1; + + var int_arr_2 = new int[2, 3]; + int_arr_2[0, 0] = 0; + int_arr_2[0, 1] = 1; + int_arr_2[0, 2] = 2; + int_arr_2[1, 0] = 10; + int_arr_2[1, 1] = 11; + int_arr_2[1, 2] = 12; + + var int_arr_3 = new int[2, 3, 3]; + int_arr_3[0, 0, 0] = 0; + int_arr_3[0, 0, 1] = 1; + int_arr_3[0, 0, 2] = 2; + int_arr_3[0, 1, 0] = 10; + int_arr_3[0, 1, 1] = 11; + int_arr_3[0, 1, 2] = 12; + int_arr_3[0, 2, 0] = 20; + int_arr_3[0, 2, 1] = 21; + int_arr_3[0, 2, 2] = 22; + int_arr_3[1, 0, 0] = 100; + int_arr_3[1, 0, 1] = 101; + int_arr_3[1, 0, 2] = 102; + int_arr_3[1, 1, 0] = 110; + int_arr_3[1, 1, 1] = 111; + int_arr_3[1, 1, 2] = 112; + int_arr_3[1, 2, 0] = 120; + int_arr_3[1, 2, 1] = 121; + int_arr_3[1, 2, 2] = 122; + + System.Diagnostics.Debugger.Break(); + Console.WriteLine($"int_arr: {int_arr_3.Length}"); + } + } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-custom-view-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-custom-view-test.cs index ecdccf0251f9ff..e2d8163ee91ad9 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-custom-view-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-custom-view-test.cs @@ -58,6 +58,13 @@ string GetDebuggerDisplay () } } + [DebuggerDisplay("FirstName: {FirstName}, SurName: {SurName}, Age: {Age}")] + public class Person { + public string FirstName { get; set; } + public string SurName { get; set; } + public int Age { get; set; } + } + class DebuggerCustomViewTest { public static void run() @@ -67,7 +74,37 @@ public static void run() var c = new DebuggerDisplayMethodTest(); List myList = new List{ 1, 2, 3, 4 }; var listToTestToList = System.Linq.Enumerable.Range(1, 11); + + Dictionary openWith = new Dictionary(); + + openWith.Add("txt", "notepad"); + openWith.Add("bmp", "paint"); + openWith.Add("dib", "paint"); + var person1 = new Person { FirstName = "Anton", SurName="Mueller", Age = 44}; + var person2 = new Person { FirstName = "Lisa", SurName="Müller", Age = 41}; + + Console.WriteLine("break here"); + Console.WriteLine("break here"); } } + + class DebuggerCustomViewTest2 + { + public static void run() + { + List myList = new List (); + List myList2 = new List (); + + myList.Add(1); + myList.Add(2); + myList.Add(3); + myList.Add(4); + myList2.Add(1); + myList2.Add(1); + myList2.Add(1); + myList2.Add(1); + + } + } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html index b1bfcd859d0644..21e1f156966b73 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-driver.html @@ -1,8 +1,8 @@ - - - + + + - - - - Stuff goes here - - + function load_non_wasm_page () { + console.log("load_non_wasm_page") + window.location.replace("http://localhost:9400/non-wasm-page.html"); + } + function load_wasm_page_without_assets () { + console.log("load_wasm_page_without_assets") + window.location.replace("http://localhost:9400/wasm-page-without-assets.html"); + } + + + + + Stuff goes here + + diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs index 01bdda2868ddde..75e9631be7a58c 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-evaluate-test.cs @@ -28,6 +28,13 @@ public void run(int g, int h, string a, string valString, int this_a) b = b + 1; c = c + 1; } + public void EvaluateLocalsFromAnotherAssembly() + { + var asm = System.Reflection.Assembly.LoadFrom("debugger-test-with-source-link.dll"); + var myType = asm.GetType("DebuggerTests.ClassToCheckFieldValue"); + var myMethod = myType.GetConstructor(new Type[] { }); + var a = myMethod.Invoke(new object[]{}); + } } public static void EvaluateLocals() @@ -41,6 +48,11 @@ public static void EvaluateLocals() var f_g_s = new EvaluateTestsGenericStruct(); f_g_s.EvaluateTestsGenericStructInstanceMethod(100, 200, "test"); } + public static void EvaluateLocalsFromAnotherAssembly() + { + TestEvaluate eval = new TestEvaluate(); + eval.EvaluateLocalsFromAnotherAssembly(); + } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-exception-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-exception-test.cs index 86904ca27ea879..ebf82dc4909200 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-exception-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-exception-test.cs @@ -52,4 +52,40 @@ public CustomException(string message) this.message = message; } } + + public class ExceptionTestsClassDefault + { + public class TestCaughtException + { + public void run() + { + try + { + throw new Exception("not implemented caught"); + } + catch + { + Console.WriteLine("caught exception"); + } + } + } + + public class TestUncaughtException + { + public void run() + { + throw new Exception("not implemented uncaught"); + } + } + + public static void TestExceptions() + { + TestCaughtException f = new TestCaughtException(); + f.run(); + + TestUncaughtException g = new TestUncaughtException(); + g.run(); + } + + } } diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs index 4a893f9948feb2..df623485bf1576 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.cs @@ -725,5 +725,97 @@ public async System.Threading.Tasks.Task AsyncMethod() Console.WriteLine($"time for await"); return true; } + +} + +public class MainPage +{ + public MainPage() + { + } + + int count = 0; + private int someValue; + + public int SomeValue + { + get + { + return someValue; + } + set + { + someValue = value; + count++; + + if (count == 10) + { + var view = 150; + + if (view != 50) + { + + } + System.Diagnostics.Debugger.Break(); + } + + SomeValue = count; + } + } + + public static void CallSetValue() + { + var mainPage = new MainPage(); + mainPage.SomeValue = 10; + } } +public class LoopClass +{ + public static void LoopToBreak() + { + for (int i = 0; i < 10; i++) + { + Console.WriteLine($"should pause only on i == 3"); + } + Console.WriteLine("breakpoint to check"); + } +} + +public class SteppingInto +{ + static int currentCount = 0; + static MyIncrementer incrementer = new MyIncrementer(); + public static void MethodToStep() + { + currentCount = incrementer.Increment(currentCount); + } +} + +public class MyIncrementer +{ + private Func todayFunc = () => DateTime.Now; + + public int Increment(int count) + { + var today = todayFunc(); + if (today.DayOfWeek == DayOfWeek.Sunday) + { + return count + 2; + } + + return count + 1; + } +} + +public class DebugTypeFull +{ + public static void CallToEvaluateLocal(string asm_base64, string pdb_base64) + { + var asm = System.Reflection.Assembly.LoadFrom("debugger-test-with-full-debug-type.dll"); + var myType = asm.GetType("DebuggerTests.ClassToInspectWithDebugTypeFull"); + var myMethod = myType.GetConstructor(new Type[] { }); + var a = myMethod.Invoke(new object[]{}); + System.Diagnostics.Debugger.Break(); + } +} \ No newline at end of file diff --git a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj index 0503feaaff07e8..89a81f1b7cf094 100644 --- a/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj +++ b/src/mono/wasm/debugger/tests/debugger-test/debugger-test.csproj @@ -5,10 +5,13 @@ true false PrepareForWasmBuildApp;$(WasmBuildAppDependsOn) + true + + @@ -20,10 +23,12 @@ + + false $(AppDir) $(MonoProjectRoot)wasm\runtime-test.js @@ -35,6 +40,7 @@ + diff --git a/src/mono/wasm/debugger/tests/debugger-test/non-wasm-page.html b/src/mono/wasm/debugger/tests/debugger-test/non-wasm-page.html new file mode 100644 index 00000000000000..2894375a79c809 --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test/non-wasm-page.html @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html b/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html new file mode 100644 index 00000000000000..d8bfb820c0d427 --- /dev/null +++ b/src/mono/wasm/debugger/tests/debugger-test/wasm-page-without-assets.html @@ -0,0 +1,21 @@ + + + + + + + + + + Stuff goes here + + \ No newline at end of file diff --git a/src/mono/wasm/runtime/binding_support.js b/src/mono/wasm/runtime/binding_support.js index 6e2fb3c508d42d..11d50bfc9558b1 100644 --- a/src/mono/wasm/runtime/binding_support.js +++ b/src/mono/wasm/runtime/binding_support.js @@ -160,6 +160,16 @@ var BindingSupportLib = { return Promise.resolve(js_obj) === js_obj || ((typeof js_obj === "object" || typeof js_obj === "function") && typeof js_obj.then === "function") }; + this.isChromium = false; + if (globalThis.navigator) { + var nav = globalThis.navigator; + if (nav.userAgentData && nav.userAgentData.brands) { + this.isChromium = nav.userAgentData.brands.some((i) => i.brand == 'Chromium'); + } + else if (globalThis.navigator.userAgent) { + this.isChromium = nav.userAgent.includes("Chrome"); + } + } this._empty_string = ""; this._empty_string_ptr = 0; @@ -372,7 +382,7 @@ var BindingSupportLib = { return this._wrap_delegate_gc_handle_as_function(gc_handle); }, - _wrap_delegate_gc_handle_as_function: function (gc_handle) { + _wrap_delegate_gc_handle_as_function: function (gc_handle, after_listener_callback) { this.bindings_lazy_init (); // see if we have js owned instance for this gc_handle already @@ -384,7 +394,11 @@ var BindingSupportLib = { result = function() { const delegateRoot = MONO.mono_wasm_new_root (BINDING.get_js_owned_object_by_gc_handle(gc_handle)); try { - return BINDING.call_method (result[BINDING.delegate_invoke_symbol], delegateRoot.value, result[BINDING.delegate_invoke_signature_symbol], arguments); + const res = BINDING.call_method(result[BINDING.delegate_invoke_symbol], delegateRoot.value, result[BINDING.delegate_invoke_signature_symbol], arguments); + if (after_listener_callback) { + after_listener_callback(); + } + return res; } finally { delegateRoot.release(); } @@ -2042,7 +2056,12 @@ var BindingSupportLib = { var obj = BINDING.mono_wasm_get_jsobj_from_js_handle(objHandle); if (!obj) throw new Error("ERR09: Invalid JS object handle for '"+sName+"'"); - var listener = BINDING._wrap_delegate_gc_handle_as_function(listener_gc_handle); + + const prevent_timer_throttling = !BINDING.isChromium || obj.constructor.name !== 'WebSocket' + ? null + : () => MONO.prevent_timer_throttling(0); + + var listener = BINDING._wrap_delegate_gc_handle_as_function(listener_gc_handle, prevent_timer_throttling); if (!listener) throw new Error("ERR10: Invalid listener gc_handle"); diff --git a/src/mono/wasm/runtime/library_mono.js b/src/mono/wasm/runtime/library_mono.js index 8f8d4cbcfe537a..6c5dbe5e0d0d45 100644 --- a/src/mono/wasm/runtime/library_mono.js +++ b/src/mono/wasm/runtime/library_mono.js @@ -52,6 +52,7 @@ var MonoSupportLib = { $MONO: { pump_count: 0, timeout_queue: [], + spread_timers_maximum:0, _vt_stack: [], mono_wasm_runtime_is_ready : false, mono_wasm_ignore_pdb_load_errors: true, @@ -74,6 +75,8 @@ var MonoSupportLib = { export_functions: function (module) { module ["pump_message"] = MONO.pump_message.bind(MONO); + module ["prevent_timer_throttling"] = MONO.prevent_timer_throttling.bind(MONO); + module ["mono_wasm_set_timeout_exec"] = MONO.mono_wasm_set_timeout_exec.bind(MONO); module ["mono_load_runtime_and_bcl"] = MONO.mono_load_runtime_and_bcl.bind(MONO); module ["mono_load_runtime_and_bcl_args"] = MONO.mono_load_runtime_and_bcl_args.bind(MONO); module ["mono_wasm_load_bytes_into_heap"] = MONO.mono_wasm_load_bytes_into_heap.bind(MONO); @@ -578,11 +581,23 @@ var MonoSupportLib = { MONO.commands_received = buffer_obj; }, + mono_wasm_malloc_and_set_debug_buffer: function (command_parameters) + { + if (command_parameters.length > this._debugger_buffer_len) + { + if (this._debugger_buffer) + Module._free (this._debugger_buffer); + this._debugger_buffer_len = Math.max(command_parameters.length, this._debugger_buffer_len, 256); + this._debugger_buffer = Module._malloc (this._debugger_buffer_len); + } + this._debugger_heap_bytes = new Uint8Array (Module.HEAPU8.buffer, this._debugger_buffer, this._debugger_buffer_len); + this._debugger_heap_bytes.set(this._base64_to_uint8 (command_parameters)); + }, + mono_wasm_send_dbg_command_with_parms: function (id, command_set, command, command_parameters, length, valtype, newvalue) { - const dataHeap = new Uint8Array (Module.HEAPU8.buffer, command_parameters, command_parameters.length); - dataHeap.set (new Uint8Array (this._base64_to_uint8 (command_parameters))); - this._c_fn_table.mono_wasm_send_dbg_command_with_parms_wrapper (id, command_set, command, dataHeap.byteOffset, length, valtype, newvalue.toString()); + this.mono_wasm_malloc_and_set_debug_buffer(command_parameters); + this._c_fn_table.mono_wasm_send_dbg_command_with_parms_wrapper (id, command_set, command, this._debugger_buffer, length, valtype, newvalue.toString()); let { res_ok, res } = MONO.commands_received; if (!res_ok) throw new Error (`Failed on mono_wasm_invoke_method_debugger_agent_with_parms`); @@ -591,11 +606,8 @@ var MonoSupportLib = { mono_wasm_send_dbg_command: function (id, command_set, command, command_parameters) { - const dataHeap = new Uint8Array (Module.HEAPU8.buffer, command_parameters, command_parameters.length); - dataHeap.set (new Uint8Array (this._base64_to_uint8 (command_parameters))); - - this._c_fn_table.mono_wasm_send_dbg_command_wrapper (id, command_set, command, dataHeap.byteOffset, command_parameters.length); - + this.mono_wasm_malloc_and_set_debug_buffer(command_parameters); + this._c_fn_table.mono_wasm_send_dbg_command_wrapper (id, command_set, command, this._debugger_buffer, command_parameters.length); let { res_ok, res } = MONO.commands_received; if (!res_ok) throw new Error (`Failed on mono_wasm_send_dbg_command`); @@ -687,8 +699,11 @@ var MonoSupportLib = { _create_proxy_from_object_id: function (objectId, details) { if (objectId.startsWith ('dotnet:array:')) { - let ret = details.map (p => p.value); - return ret; + if (details.dimensionsDetails == undefined || details.dimensionsDetails.length == 1) + { + const ret = details.items.map (p => p.value); + return ret; + } } let proxy = {}; @@ -830,7 +845,7 @@ var MonoSupportLib = { this._c_fn_table = {}; this._register_c_fn ('mono_wasm_send_dbg_command', 'bool', [ 'number', 'number', 'number', 'number', 'number' ]); this._register_c_fn ('mono_wasm_send_dbg_command_with_parms', 'bool', [ 'number', 'number', 'number', 'number', 'number', 'number', 'string' ]); - + this._debugger_buffer_len = -1; // DO NOT REMOVE - magic debugger init function if (globalThis.dotnetDebugger) debugger; @@ -1289,15 +1304,15 @@ var MonoSupportLib = { try { if (asset.name === attemptUrl) { if (ctx.tracing) - console.log ("Attempting to fetch '" + attemptUrl + "'"); + console.log ("Attempting to fetch '%s'", attemptUrl); } else { if (ctx.tracing) - console.log ("Attempting to fetch '" + attemptUrl + "' for", asset.name); + console.log ("Attempting to fetch '%s' for '%s'", attemptUrl, asset.name); } var fetch_promise = fetch_file_cb (attemptUrl); fetch_promise.then (handleFetchResponse); } catch (exc) { - console.error ("MONO_WASM: Error fetching " + attemptUrl, exc); + console.error ("MONO_WASM: Error fetching '%s'\n%s", attemptUrl, exc); attemptNextSource (); } }; @@ -1457,6 +1472,28 @@ var MonoSupportLib = { } finally { Module.removeRunDependency(configFilePath); } + }, + mono_wasm_set_timeout_exec: function(id){ + if (!this.mono_set_timeout_exec) + this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", null, [ 'number' ]); + this.mono_set_timeout_exec (id); + }, + prevent_timer_throttling: function () { + // this will schedule timers every second for next 6 minutes, it should be called from WebSocket event, to make it work + // on next call, it would only extend the timers to cover yet uncovered future + let now = new Date().valueOf(); + const desired_reach_time = now + (1000 * 60 * 6); + const next_reach_time = Math.max(now + 1000, this.spread_timers_maximum); + const light_throttling_frequency = 1000; + for (var schedule = next_reach_time; schedule < desired_reach_time; schedule += light_throttling_frequency) { + const delay = schedule - now; + setTimeout(() => { + this.mono_wasm_set_timeout_exec(0); + MONO.pump_count++; + MONO.pump_message(); + }, delay); + } + this.spread_timers_maximum = desired_reach_time; } }, schedule_background_exec: function () { @@ -1467,17 +1504,19 @@ var MonoSupportLib = { }, mono_set_timeout: function (timeout, id) { - if (!this.mono_set_timeout_exec) - this.mono_set_timeout_exec = Module.cwrap ("mono_set_timeout_exec", null, [ 'number' ]); if (typeof globalThis.setTimeout === 'function') { - globalThis.setTimeout (function () { - this.mono_set_timeout_exec (id); + if (MONO.lastScheduleTimeoutId) { + globalThis.clearTimeout(MONO.lastScheduleTimeoutId); + MONO.lastScheduleTimeoutId = undefined; + } + MONO.lastScheduleTimeoutId = globalThis.setTimeout(function mono_wasm_set_timeout_exec () { + MONO.mono_wasm_set_timeout_exec(id); }, timeout); } else { ++MONO.pump_count; MONO.timeout_queue.push(function() { - this.mono_set_timeout_exec (id); + MONO.mono_wasm_set_timeout_exec (id); }) } }, diff --git a/src/mono/wasm/sln/WasmBuild.sln b/src/mono/wasm/sln/WasmBuild.sln new file mode 100755 index 00000000000000..10256d28e62648 --- /dev/null +++ b/src/mono/wasm/sln/WasmBuild.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31722.452 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WasmBuildTasks", "..\..\..\tasks\WasmBuildTasks\WasmBuildTasks.csproj", "{D5BD9C0C-8A05-493E-BE45-13AF8286CD92}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WasmAppBuilder", "..\..\..\tasks\WasmAppBuilder\WasmAppBuilder.csproj", "{8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MonoAOTCompiler", "..\..\..\tasks\AotCompilerTask\MonoAOTCompiler.csproj", "{A9C02284-0387-42E7-BF78-47DF13656D5E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wasm.Build.Tests", "..\..\..\tests\BuildWasmApps\Wasm.Build.Tests\Wasm.Build.Tests.csproj", "{94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DebuggerTestSuite", "..\debugger\DebuggerTestSuite\DebuggerTestSuite.csproj", "{4C0EE027-FC30-4167-B2CF-A6D18F00E08F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugHost", "..\debugger\BrowserDebugHost\BrowserDebugHost.csproj", "{292A88FD-795F-467A-8801-B5B791CEF96E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BrowserDebugProxy", "..\debugger\BrowserDebugProxy\BrowserDebugProxy.csproj", "{F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WasmAppHost", "..\host\WasmAppHost.csproj", "{C7099764-EC2E-4FAF-9057-0321893DE4F8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplyUpdateReferencedAssembly", "..\debugger\tests\ApplyUpdateReferencedAssembly\ApplyUpdateReferencedAssembly.csproj", "{75477B6F-DC8E-4002-88B8-017C992C568E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5BD9C0C-8A05-493E-BE45-13AF8286CD92}.Release|Any CPU.Build.0 = Release|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8DEBFDE2-B127-46D7-92CF-EEA6D1DA2554}.Release|Any CPU.Build.0 = Release|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9C02284-0387-42E7-BF78-47DF13656D5E}.Release|Any CPU.Build.0 = Release|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94E18644-B0E5-4DBB-9CE4-EA1515ACE4C2}.Release|Any CPU.Build.0 = Release|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C0EE027-FC30-4167-B2CF-A6D18F00E08F}.Release|Any CPU.Build.0 = Release|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {292A88FD-795F-467A-8801-B5B791CEF96E}.Release|Any CPU.Build.0 = Release|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F5AE2AF5-3C30-45E3-A0C6-D962C51FE5E7}.Release|Any CPU.Build.0 = Release|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75477B6F-DC8E-4002-88B8-017C992C568E}.Release|Any CPU.Build.0 = Release|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7099764-EC2E-4FAF-9057-0321893DE4F8}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2BDE8FDE-4261-4B4D-8B54-ACC88B06C8D1} + EndGlobalSection +EndGlobal diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 3eacc3e1307c13..7b37edbdb7fdc2 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -12,6 +12,7 @@ emcc $(ArtifactsObjDir)wasm <_EmccDefaultsRspPath>$(NativeBinDir)src\emcc-default.rsp + false @@ -81,7 +82,6 @@ <_EmccFlags Include="@(_EmccCommonFlags)" /> - <_EmccFlags Include="-s USE_ZLIB=1" /> -g -Os -s -DENABLE_NETCORE=1 -DDEBUG=1 - -Oz -DENABLE_NETCORE=1 + -O2 -DENABLE_NETCORE=1 "$(EMSDK_PATH)/upstream/bin/wasm-opt" --strip-dwarf "$(NativeBinDir)dotnet.wasm" -o "$(NativeBinDir)dotnet.wasm" $(ArtifactsObjDir)wasm $(WasmObjDir)\emcc-version.txt diff --git a/src/native/corehost/apphost/apphost.windows.cpp b/src/native/corehost/apphost/apphost.windows.cpp index b6c229e93086a1..7a3a94a960b398 100644 --- a/src/native/corehost/apphost/apphost.windows.cpp +++ b/src/native/corehost/apphost/apphost.windows.cpp @@ -52,11 +52,6 @@ namespace void show_error_dialog(const pal::char_t *executable_name, int error_code) { - // Show message dialog for UI apps with actionable errors - if (error_code != StatusCode::CoreHostLibMissingFailure // missing hostfxr - && error_code != StatusCode::FrameworkMissingFailure) // missing framework - return; - pal::string_t gui_errors_disabled; if (pal::getenv(_X("DOTNET_DISABLE_GUI_ERRORS"), &gui_errors_disabled) && pal::xtoi(gui_errors_disabled.c_str()) == 1) return; @@ -108,6 +103,25 @@ namespace } } } + else if (error_code == StatusCode::BundleExtractionFailure) + { + pal::string_t line; + pal::stringstream_t ss(g_buffered_errors); + while (std::getline(ss, line, _X('\n'))) { + if (starts_with(line, _X("Bundle header version compatibility check failed."), true)) + { + dialogMsg = pal::string_t(_X("To run this application, you must install .NET Desktop Runtime ")) + _STRINGIFY(COMMON_HOST_PKG_VER) + _X(" (") + get_arch() + _X(").\n\n"); + url = get_download_url(); + url.append(_X("&apphost_version=")); + url.append(_STRINGIFY(COMMON_HOST_PKG_VER)); + } + } + + if (dialogMsg.empty()) + return; + } + else + return; dialogMsg.append(_X("Would you like to download it now?")); diff --git a/src/native/corehost/apphost/standalone/CMakeLists.txt b/src/native/corehost/apphost/standalone/CMakeLists.txt index b17e63beaf4f1b..d7a52a8534f99f 100644 --- a/src/native/corehost/apphost/standalone/CMakeLists.txt +++ b/src/native/corehost/apphost/standalone/CMakeLists.txt @@ -49,5 +49,5 @@ endif() # Specify non-default Windows libs to be used for Arm/Arm64 builds if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) - target_link_libraries(apphost Advapi32.lib shell32.lib) + target_link_libraries(apphost shell32.lib) endif() diff --git a/src/native/corehost/apphost/static/CMakeLists.txt b/src/native/corehost/apphost/static/CMakeLists.txt index 0d9ae541c33b1d..a00c79139863fb 100644 --- a/src/native/corehost/apphost/static/CMakeLists.txt +++ b/src/native/corehost/apphost/static/CMakeLists.txt @@ -110,6 +110,9 @@ if(CLR_CMAKE_TARGET_WIN32) # Incremental linking results in the linker inserting extra padding and routing function calls via thunks that can break the # invariants (e.g. size of region between Jit_PatchedCodeLast-Jit_PatchCodeStart needs to fit in a page). add_linker_flag("/INCREMENTAL:NO") + + # Delay load libraries required for WinRT as that is not supported on all platforms. + add_linker_flag("/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll") endif() if(CLR_CMAKE_TARGET_WIN32) @@ -130,6 +133,7 @@ if(CLR_CMAKE_TARGET_WIN32) shell32.lib bcrypt.lib RuntimeObject.lib + delayimp.lib ) set(RUNTIMEINFO_LIB runtimeinfo) diff --git a/src/native/corehost/bundle/file_entry.cpp b/src/native/corehost/bundle/file_entry.cpp index ace0ef514927e6..a6610d7de97b92 100644 --- a/src/native/corehost/bundle/file_entry.cpp +++ b/src/native/corehost/bundle/file_entry.cpp @@ -19,15 +19,18 @@ file_entry_t file_entry_t::read(reader_t &reader, uint32_t bundle_major_version, // First read the fixed-sized portion of file-entry file_entry_fixed_t fixed_data; - fixed_data.offset = *(int64_t*)reader.read_direct(sizeof(int64_t)); - fixed_data.size = *(int64_t*)reader.read_direct(sizeof(int64_t)); + // NB: the file data is potentially unaligned, thus we use "read" to fetch 64bit values + reader.read(&fixed_data.offset, sizeof(int64_t)); + reader.read(&fixed_data.size, sizeof(int64_t)); // compressedSize is present only in v6+ headers - fixed_data.compressedSize = bundle_major_version >= 6 ? - *(int64_t*)reader.read_direct(sizeof(int64_t)) : - 0; + fixed_data.compressedSize = 0; + if (bundle_major_version >= 6) + { + reader.read(&fixed_data.compressedSize, sizeof(int64_t)); + } - fixed_data.type = *(file_type_t*)reader.read_direct(sizeof(file_type_t)); + fixed_data.type = (file_type_t)reader.read_byte(); file_entry_t entry(&fixed_data, force_extraction); diff --git a/src/native/corehost/bundle/header.cpp b/src/native/corehost/bundle/header.cpp index 268ef867146ae0..bc549f4c7af8c7 100644 --- a/src/native/corehost/bundle/header.cpp +++ b/src/native/corehost/bundle/header.cpp @@ -24,23 +24,23 @@ bool header_fixed_t::is_valid() const header_t header_t::read(reader_t& reader) { - const header_fixed_t* fixed_header = reinterpret_cast(reader.read_direct(sizeof(header_fixed_t))); + header_fixed_t fixed_header; + reader.read(&fixed_header, sizeof(header_fixed_t)); - if (!fixed_header->is_valid()) + if (!fixed_header.is_valid()) { trace::error(_X("Failure processing application bundle.")); - trace::error(_X("Bundle header version compatibility check failed.")); + trace::error(_X("Bundle header version compatibility check failed. Header version: %d.%d"), fixed_header.major_version, fixed_header.minor_version); throw StatusCode::BundleExtractionFailure; } - header_t header(fixed_header->major_version, fixed_header->minor_version, fixed_header->num_embedded_files); + header_t header(fixed_header.major_version, fixed_header.minor_version, fixed_header.num_embedded_files); // bundle_id is a component of the extraction path reader.read_path_string(header.m_bundle_id); - const header_fixed_v2_t *v2_header = reinterpret_cast(reader.read_direct(sizeof(header_fixed_v2_t))); - header.m_v2_header = *v2_header; + reader.read(&header.m_v2_header, sizeof(header_fixed_v2_t)); return header; } diff --git a/src/native/corehost/bundle/info.cpp b/src/native/corehost/bundle/info.cpp index 4d58a00ae647be..fd4a7d3f3b08b7 100644 --- a/src/native/corehost/bundle/info.cpp +++ b/src/native/corehost/bundle/info.cpp @@ -108,7 +108,14 @@ char* info_t::config_t::map(const pal::string_t& path, const location_t* &locati // * There is no performance limitation due to a larger sized mapping, since we actually only read the pages with relevant contents. // * Files that are too large to be mapped (ex: that exhaust 32-bit virtual address space) are not supported. +#ifdef _WIN32 + // Since we can't use in-situ parsing on Windows, as JSON data is encoded in + // UTF-8 and the host expects wide strings. + // We do not need COW and read-only mapping will be enough. + char* addr = (char*)pal::mmap_read(app->m_bundle_path); +#else // _WIN32 char* addr = (char*)pal::mmap_copy_on_write(app->m_bundle_path); +#endif // _WIN32 if (addr == nullptr) { trace::error(_X("Failure processing application bundle.")); diff --git a/src/native/corehost/bundle/reader.cpp b/src/native/corehost/bundle/reader.cpp index a7b5e580f0b562..8461e5db920be2 100644 --- a/src/native/corehost/bundle/reader.cpp +++ b/src/native/corehost/bundle/reader.cpp @@ -54,7 +54,7 @@ size_t reader_t::read_path_length() { size_t length = 0; - int8_t first_byte = read(); + int8_t first_byte = read_byte(); // If the high bit is set, it means there are more bytes to read. if ((first_byte & 0x80) == 0) @@ -63,7 +63,7 @@ size_t reader_t::read_path_length() } else { - int8_t second_byte = read(); + int8_t second_byte = read_byte(); if (second_byte & 0x80) { diff --git a/src/native/corehost/bundle/reader.h b/src/native/corehost/bundle/reader.h index 576ecd04c8e0fe..a4c1e07be19ece 100644 --- a/src/native/corehost/bundle/reader.h +++ b/src/native/corehost/bundle/reader.h @@ -81,7 +81,7 @@ namespace bundle return m_ptr; } - int8_t read() + int8_t read_byte() { bounds_check(); return *m_ptr++; @@ -100,16 +100,6 @@ namespace bundle m_ptr += len; } - // Return a pointer to the requested bytes within the memory-mapped file. - // Skip over len bytes. - const char* read_direct(int64_t len) - { - bounds_check(len); - const char *ptr = m_ptr; - m_ptr += len; - return ptr; - } - size_t read_path_length(); size_t read_path_string(pal::string_t &str); diff --git a/src/native/corehost/comhost/CMakeLists.txt b/src/native/corehost/comhost/CMakeLists.txt index 7517306cdc1d6b..36251ad79598ba 100644 --- a/src/native/corehost/comhost/CMakeLists.txt +++ b/src/native/corehost/comhost/CMakeLists.txt @@ -35,7 +35,7 @@ if (CLR_CMAKE_TARGET_WIN32) # Specify non-default Windows libs to be used for Arm/Arm64 builds if (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64) - list(APPEND WINLIBS Advapi32.lib Ole32.lib OleAut32.lib) + list(APPEND WINLIBS Ole32.lib OleAut32.lib) endif() target_link_libraries(comhost ${WINLIBS}) diff --git a/src/native/corehost/common.cmake b/src/native/corehost/common.cmake index eb5faa6b5602d7..717c3b5d89cf22 100644 --- a/src/native/corehost/common.cmake +++ b/src/native/corehost/common.cmake @@ -48,7 +48,7 @@ function(set_common_libs TargetType) # Specify the import library to link against for Arm32 build since the default set is minimal if (CLR_CMAKE_TARGET_ARCH_ARM) if (CLR_CMAKE_TARGET_WIN32) - target_link_libraries(${DOTNET_PROJECT_NAME} shell32.lib) + target_link_libraries(${DOTNET_PROJECT_NAME} shell32.lib advapi32.lib) else() target_link_libraries(${DOTNET_PROJECT_NAME} atomic.a) endif() diff --git a/src/native/corehost/fxr_resolver.cpp b/src/native/corehost/fxr_resolver.cpp index 6e1356457d49ae..b59c59f10fd80e 100644 --- a/src/native/corehost/fxr_resolver.cpp +++ b/src/native/corehost/fxr_resolver.cpp @@ -100,13 +100,8 @@ bool fxr_resolver::try_get_path(const pal::string_t& root_path, pal::string_t* o pal::get_default_installation_dir(&default_install_location); } - pal::string_t self_registered_config_location; - pal::string_t self_registered_message; - if (pal::get_dotnet_self_registered_config_location(&self_registered_config_location)) - { - self_registered_message = - pal::string_t(_X(" or register the runtime location in [") + self_registered_config_location + _X("]")); - } + pal::string_t self_registered_config_location = pal::get_dotnet_self_registered_config_location(); + pal::string_t self_registered_message = _X(" or register the runtime location in [") + self_registered_config_location + _X("]"); trace::error(_X("A fatal error occurred. The required library %s could not be found.\n" "If this is a self-contained application, that library should exist in [%s].\n" diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index b6622cd5dff52b..0932e0db5b60e3 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -287,7 +287,7 @@ namespace pal // Returns the globally registered install location (if any) bool get_dotnet_self_registered_dir(string_t* recv); // Returns name of the global registry location (for error messages) - bool get_dotnet_self_registered_config_location(string_t* recv); + string_t get_dotnet_self_registered_config_location(); // Returns the default install location for a given platform bool get_default_installation_dir(string_t* recv); diff --git a/src/native/corehost/hostmisc/pal.unix.cpp b/src/native/corehost/hostmisc/pal.unix.cpp index 4a3e86f2f567a8..59597646e03730 100644 --- a/src/native/corehost/hostmisc/pal.unix.cpp +++ b/src/native/corehost/hostmisc/pal.unix.cpp @@ -379,18 +379,16 @@ bool pal::get_global_dotnet_dirs(std::vector* recv) return false; } -bool pal::get_dotnet_self_registered_config_location(pal::string_t* recv) +pal::string_t pal::get_dotnet_self_registered_config_location() { - recv->assign(_X("/etc/dotnet/install_location")); - // ***Used only for testing*** pal::string_t environment_install_location_override; - if (test_only_getenv(_X("_DOTNET_TEST_INSTALL_LOCATION_FILE_PATH"), &environment_install_location_override)) + if (test_only_getenv(_X("_DOTNET_TEST_INSTALL_LOCATION_PATH"), &environment_install_location_override)) { - recv->assign(environment_install_location_override); + return environment_install_location_override; } - return true; + return _X("/etc/dotnet"); } namespace @@ -416,90 +414,80 @@ namespace } } -bool pal::get_dotnet_self_registered_dir(pal::string_t* recv) +bool get_install_location_from_file(const pal::string_t& file_path, bool& file_found, pal::string_t& install_location) { - recv->clear(); - - // ***Used only for testing*** - pal::string_t environment_override; - if (test_only_getenv(_X("_DOTNET_TEST_GLOBALLY_REGISTERED_PATH"), &environment_override)) + file_found = true; + bool install_location_found = false; + FILE* install_location_file = pal::file_open(file_path, "r"); + if (install_location_file != nullptr) { - recv->assign(environment_override); - return true; - } - // *************************** + if (!get_line_from_file(install_location_file, install_location)) + { + trace::warning(_X("Did not find any install location in '%s'."), file_path.c_str()); + } + else + { + install_location_found = true; + } - pal::string_t install_location_file_path; - if (!get_dotnet_self_registered_config_location(&install_location_file_path)) - { - return false; + fclose(install_location_file); + if (install_location_found) + return true; } - // *************************** - - trace::verbose(_X("Looking for install_location file in '%s'."), install_location_file_path.c_str()); - FILE* install_location_file = pal::file_open(install_location_file_path, "r"); - if (install_location_file == nullptr) + else { if (errno == ENOENT) { - trace::verbose(_X("The install_location file ['%s'] does not exist - skipping."), install_location_file_path.c_str()); + trace::verbose(_X("The install_location file ['%s'] does not exist - skipping."), file_path.c_str()); + file_found = false; } else { - trace::error(_X("The install_location file ['%s'] failed to open: %s."), install_location_file_path.c_str(), pal::strerror(errno)); + trace::error(_X("The install_location file ['%s'] failed to open: %s."), file_path.c_str(), pal::strerror(errno)); } + } - return false; + return false; +} + +bool pal::get_dotnet_self_registered_dir(pal::string_t* recv) +{ + recv->clear(); + + // ***Used only for testing*** + pal::string_t environment_override; + if (test_only_getenv(_X("_DOTNET_TEST_GLOBALLY_REGISTERED_PATH"), &environment_override)) + { + recv->assign(environment_override); + return true; } + // *************************** - pal::string_t install_location; - int current_line = 0; - bool is_first_line = true, install_location_found = false; + pal::string_t install_location_path = get_dotnet_self_registered_config_location(); + pal::string_t arch_specific_install_location_file_path = install_location_path; + append_path(&arch_specific_install_location_file_path, (_X("install_location_") + to_lower(get_arch())).c_str()); + trace::verbose(_X("Looking for architecture specific install_location file in '%s'."), arch_specific_install_location_file_path.c_str()); - while (get_line_from_file(install_location_file, install_location)) + pal::string_t install_location; + bool file_found = false; + if (!get_install_location_from_file(arch_specific_install_location_file_path, file_found, install_location)) { - current_line++; - size_t arch_sep = install_location.find(_X('=')); - if (arch_sep == pal::string_t::npos) + if (file_found) { - if (is_first_line) - { - recv->assign(install_location); - install_location_found = true; - trace::verbose(_X("Found install location path '%s'."), install_location.c_str()); - } - else - { - trace::warning(_X("Found unprefixed install location path '%s' on line %d."), install_location.c_str(), current_line); - trace::warning(_X("Only the first line in '%s' may not have an architecture prefix."), install_location_file_path.c_str()); - } - - is_first_line = false; - continue; + return false; } - pal::string_t arch_prefix = install_location.substr(0, arch_sep); - pal::string_t path_to_location = install_location.substr(arch_sep + 1); + pal::string_t legacy_install_location_file_path = install_location_path; + append_path(&legacy_install_location_file_path, _X("install_location")); + trace::verbose(_X("Looking for install_location file in '%s'."), legacy_install_location_file_path.c_str()); - trace::verbose(_X("Found architecture-specific install location path: '%s' ('%s')."), path_to_location.c_str(), arch_prefix.c_str()); - if (pal::strcasecmp(arch_prefix.c_str(), get_arch()) == 0) + if (!get_install_location_from_file(legacy_install_location_file_path, file_found, install_location)) { - recv->assign(path_to_location); - install_location_found = true; - trace::verbose(_X("Found architecture-specific install location path matching the current host architecture ('%s'): '%s'."), arch_prefix.c_str(), path_to_location.c_str()); - break; + return false; } - - is_first_line = false; - } - - fclose(install_location_file); - if (!install_location_found) - { - trace::warning(_X("Did not find any install location in '%s'."), install_location_file_path.c_str()); - return false; } + recv->assign(install_location); trace::verbose(_X("Using install location '%s'."), recv->c_str()); return true; } @@ -545,48 +533,47 @@ pal::string_t pal::get_current_os_rid_platform() pal::string_t ridOS; char str[256]; - - // There is no good way to get the visible version of OSX (i.e. something like 10.x.y) as - // certain APIs work till 10.9 and have been deprecated and others require linking against - // UI frameworks to get the data. - // - // We will, instead, use kern.osrelease and use its major version number - // as a means to formulate the OSX 10.X RID. - // size_t size = sizeof(str); - int ret = sysctlbyname("kern.osrelease", str, &size, nullptr, 0); + + // returns something like 10.5.2 or 11.6 + int ret = sysctlbyname("kern.osproductversion", str, &size, nullptr, 0); if (ret == 0) { - std::string release(str, size); - size_t pos = release.find('.'); - if (pos != std::string::npos) + // the value _should_ be null terminated but let's make sure + str[size - 1] = 0; + + char* pos = strchr(str, '.'); + if (pos != NULL) { - int majorVersion = stoi(release.substr(0, pos)); - // compat path with 10.x - if (majorVersion < 20) + int major = atoi(str); + if (major > 11) { - // Extract the major version and subtract 4 from it - // to get the Minor version used in OSX versioning scheme. - // That is, given a version 10.X.Y, we will get X below. - // - // macOS Cataline 10.15.5 has kernel 19.5.0 - int minorVersion = majorVersion - 4; - if (minorVersion < 10) - { - // On OSX, our minimum supported RID is 10.12. - minorVersion = 12; - } + // starting with 12.0 we track only major release + *pos = 0; - ridOS.append(_X("osx.10.")); - ridOS.append(pal::to_string(minorVersion)); + } + else if (major == 11) + { + // for 11.x we publish RID as 11.0 + // if we return anything else, it would break the RID graph processing + strcpy(str, "11.0"); } else { - // 11.0 shipped with kernel 20.0 - ridOS.append(_X("osx.11.")); - ridOS.append(pal::to_string(majorVersion - 20)); + // for 10.x the significant releases are actually the second digit + pos = strchr(pos + 1, '.'); + + if (pos != NULL) + { + // strip anything after second dot and return something like 10.5 + *pos = 0; + } } } + + std::string release(str, strlen(str)); + ridOS.append(_X("osx.")); + ridOS.append(release); } return ridOS; diff --git a/src/native/corehost/hostmisc/pal.windows.cpp b/src/native/corehost/hostmisc/pal.windows.cpp index 87a5508badbf59..6ce65baae47916 100644 --- a/src/native/corehost/hostmisc/pal.windows.cpp +++ b/src/native/corehost/hostmisc/pal.windows.cpp @@ -322,27 +322,18 @@ namespace } } -bool pal::get_dotnet_self_registered_config_location(pal::string_t* recv) +pal::string_t pal::get_dotnet_self_registered_config_location() { -#if !defined(TARGET_AMD64) && !defined(TARGET_X86) - return false; -#else HKEY key_hive; pal::string_t sub_key; const pal::char_t* value; get_dotnet_install_location_registry_path(&key_hive, &sub_key, &value); - recv->assign((key_hive == HKEY_CURRENT_USER ? _X("HKCU\\") : _X("HKLM\\")) + sub_key + _X("\\") + value); - return true; -#endif + return (key_hive == HKEY_CURRENT_USER ? _X("HKCU\\") : _X("HKLM\\")) + sub_key + _X("\\") + value; } bool pal::get_dotnet_self_registered_dir(pal::string_t* recv) { -#if !defined(TARGET_AMD64) && !defined(TARGET_X86) - // Self-registered SDK installation directory is only supported for x64 and x86 architectures. - return false; -#else recv->clear(); // ***Used only for testing*** @@ -392,7 +383,6 @@ bool pal::get_dotnet_self_registered_dir(pal::string_t* recv) recv->assign(buffer.data()); ::RegCloseKey(hkey); return true; -#endif } bool pal::get_global_dotnet_dirs(std::vector* dirs) @@ -402,11 +392,14 @@ bool pal::get_global_dotnet_dirs(std::vector* dirs) bool dir_found = false; if (pal::get_dotnet_self_registered_dir(&custom_dir)) { + remove_trailing_dir_seperator(&custom_dir); dirs->push_back(custom_dir); dir_found = true; } if (get_default_installation_dir(&default_dir)) { + remove_trailing_dir_seperator(&default_dir); + // Avoid duplicate global dirs. if (!dir_found || !are_paths_equal_with_normalized_casing(custom_dir, default_dir)) { diff --git a/src/native/corehost/hostpolicy.h b/src/native/corehost/hostpolicy.h index 27ada5fb18fc1b..8c152325c6a9b3 100644 --- a/src/native/corehost/hostpolicy.h +++ b/src/native/corehost/hostpolicy.h @@ -37,4 +37,15 @@ typedef int(HOSTPOLICY_CALLTYPE *corehost_initialize_fn)( uint32_t options, corehost_context_contract *handle); +typedef void(HOSTPOLICY_CALLTYPE* corehost_resolve_component_dependencies_result_fn)( + const pal::char_t* assembly_paths, + const pal::char_t* native_search_paths, + const pal::char_t* resource_search_paths); + +SHARED_API corehost_error_writer_fn HOSTPOLICY_CALLTYPE corehost_set_error_writer(corehost_error_writer_fn error_writer); + +SHARED_API int HOSTPOLICY_CALLTYPE corehost_resolve_component_dependencies( + const pal::char_t* component_main_assembly_path, + corehost_resolve_component_dependencies_result_fn result); + #endif //__HOSTPOLICY_H__ diff --git a/src/native/corehost/hostpolicy/hostpolicy.cpp b/src/native/corehost/hostpolicy/hostpolicy.cpp index c19a444794ba40..635fb26095ca21 100644 --- a/src/native/corehost/hostpolicy/hostpolicy.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy.cpp @@ -824,11 +824,6 @@ SHARED_API int HOSTPOLICY_CALLTYPE corehost_unload() return StatusCode::Success; } -typedef void(HOSTPOLICY_CALLTYPE *corehost_resolve_component_dependencies_result_fn)( - const pal::char_t* assembly_paths, - const pal::char_t* native_search_paths, - const pal::char_t* resource_search_paths); - SHARED_API int HOSTPOLICY_CALLTYPE corehost_resolve_component_dependencies( const pal::char_t *component_main_assembly_path, corehost_resolve_component_dependencies_result_fn result) diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index 2b9a953e28d533..e4165f01259a70 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "hostpolicy_context.h" +#include "hostpolicy.h" #include "deps_resolver.h" #include @@ -55,11 +56,15 @@ namespace const void* STDMETHODCALLTYPE pinvoke_override(const char* libraryName, const char* entrypointName) { #if defined(_WIN32) + const char* hostPolicyLib = "hostpolicy.dll"; + if (strcmp(libraryName, "System.IO.Compression.Native") == 0) { return CompressionResolveDllImport(entrypointName); } #else + const char* hostPolicyLib = "libhostpolicy"; + if (strcmp(libraryName, "libSystem.IO.Compression.Native") == 0) { return CompressionResolveDllImport(entrypointName); @@ -80,6 +85,19 @@ namespace return CryptoResolveDllImport(entrypointName); } #endif + // there are two PInvokes in the hostpolicy itself, redirect them here. + if (strcmp(libraryName, hostPolicyLib) == 0) + { + if (strcmp(entrypointName, "corehost_resolve_component_dependencies") == 0) + { + return (void*)corehost_resolve_component_dependencies; + } + + if (strcmp(entrypointName, "corehost_set_error_writer") == 0) + { + return (void*)corehost_set_error_writer; + } + } #if defined(TARGET_OSX) if (strcmp(libraryName, "libSystem.Security.Cryptography.Native.Apple") == 0) @@ -269,11 +287,16 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a pal::string_t startup_hooks; if (pal::getenv(_X("DOTNET_STARTUP_HOOKS"), &startup_hooks)) { - if (!coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str())) + const pal::char_t *config_startup_hooks; + if (coreclr_properties.try_get(common_property::StartUpHooks, &config_startup_hooks)) { - log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks)); - return StatusCode::LibHostDuplicateProperty; + // env startup hooks shoold have precedence over config startup hooks + // therefore append config_startup_hooks AFTER startup_hooks + startup_hooks.push_back(PATH_SEPARATOR); + startup_hooks.append(config_startup_hooks); } + + coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str()); } // Single-File Bundle Probe @@ -285,7 +308,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a if (!coreclr_properties.add(common_property::BundleProbe, ptr_stream.str().c_str())) { - log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks)); + log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::BundleProbe)); return StatusCode::LibHostDuplicateProperty; } } @@ -300,7 +323,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a if (!coreclr_properties.add(common_property::PInvokeOverride, ptr_stream.str().c_str())) { - log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks)); + log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::PInvokeOverride)); return StatusCode::LibHostDuplicateProperty; } } @@ -309,7 +332,7 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a #if defined(HOSTPOLICY_EMBEDDED) if (!coreclr_properties.add(common_property::HostPolicyEmbedded, _X("true"))) { - log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks)); + log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::HostPolicyEmbedded)); return StatusCode::LibHostDuplicateProperty; } #endif diff --git a/src/native/corehost/ijwhost/CMakeLists.txt b/src/native/corehost/ijwhost/CMakeLists.txt index d790b01709f12a..036ae1d386e4c9 100644 --- a/src/native/corehost/ijwhost/CMakeLists.txt +++ b/src/native/corehost/ijwhost/CMakeLists.txt @@ -49,7 +49,7 @@ include(../lib.cmake) # Specify non-default Windows libs to be used for Arm/Arm64 builds if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) - target_link_libraries(ijwhost Advapi32.lib Ole32.lib) + target_link_libraries(ijwhost Ole32.lib) endif() install_with_stripped_symbols(ijwhost TARGETS corehost) diff --git a/src/native/corehost/test/CMakeLists.txt b/src/native/corehost/test/CMakeLists.txt index 84b14039de91ee..a0ddc276223ed3 100644 --- a/src/native/corehost/test/CMakeLists.txt +++ b/src/native/corehost/test/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(fx_ver) add_subdirectory(mockcoreclr) -add_subdirectory(mockhostfxr) +add_subdirectory(mockhostfxr/2_2) +add_subdirectory(mockhostfxr/5_0) add_subdirectory(mockhostpolicy) add_subdirectory(nativehost) if (CLR_CMAKE_TARGET_WIN32) diff --git a/src/native/corehost/test/mockhostfxr/CMakeLists.txt b/src/native/corehost/test/mockhostfxr/2_2/CMakeLists.txt similarity index 76% rename from src/native/corehost/test/mockhostfxr/CMakeLists.txt rename to src/native/corehost/test/mockhostfxr/2_2/CMakeLists.txt index 8b5a55fe9b1772..096c3631afbc8c 100644 --- a/src/native/corehost/test/mockhostfxr/CMakeLists.txt +++ b/src/native/corehost/test/mockhostfxr/2_2/CMakeLists.txt @@ -5,10 +5,12 @@ project(mockhostfxr_2_2) set(DOTNET_PROJECT_NAME "mockhostfxr_2_2") +add_definitions(-D_MOCKHOSTFXR_2_2) + set(SOURCES - ./mockhostfxr.cpp + ./../mockhostfxr.cpp ) -include(../testlib.cmake) +include(../../testlib.cmake) install_with_stripped_symbols(mockhostfxr_2_2 TARGETS corehost_test) diff --git a/src/native/corehost/test/mockhostfxr/5_0/CMakeLists.txt b/src/native/corehost/test/mockhostfxr/5_0/CMakeLists.txt new file mode 100644 index 00000000000000..5f9f36c71852a5 --- /dev/null +++ b/src/native/corehost/test/mockhostfxr/5_0/CMakeLists.txt @@ -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. + +project(mockhostfxr_5_0) + +set(DOTNET_PROJECT_NAME "mockhostfxr_5_0") + +add_definitions(-DMOCKHOSTFXR_5_0) + +set(SOURCES + ./../mockhostfxr.cpp +) + +include(../../testlib.cmake) + +install_with_stripped_symbols(mockhostfxr_5_0 TARGETS corehost_test) diff --git a/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp b/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp index a85650bccbd057..46509a0f14d812 100644 --- a/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp +++ b/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp @@ -18,12 +18,36 @@ SHARED_API int HOSTFXR_CALLTYPE hostfxr_main_startupinfo(const int argc, const p { trace_hostfxr_entry_point(_X("hostfxr_main_startupinfo")); - const pal::string_t dotnet_folder = get_directory(dotnet_root); + const pal::string_t dotnet_folder = get_filename(dotnet_root); - if (pal::strcmp(dotnet_folder.c_str(), _X("hostfxrFrameworkMissingFailure"))) + if (pal::strcmp(dotnet_folder.c_str(), _X("mockhostfxrFrameworkMissingFailure")) == 0) { return StatusCode::FrameworkMissingFailure; } return StatusCode::Success; } + +#ifdef MOCKHOSTFXR_5_0 +SHARED_API hostfxr_error_writer_fn HOSTFXR_CALLTYPE hostfxr_set_error_writer(hostfxr_error_writer_fn error_writer) +{ + return trace::set_error_writer(error_writer); +} + +SHARED_API int HOSTFXR_CALLTYPE hostfxr_main_bundle_startupinfo(const int argc, const pal::char_t* argv[], const pal::char_t* host_path, const pal::char_t* dotnet_root, const pal::char_t* app_path, int64_t bundle_header_offset) +{ + trace_hostfxr_entry_point(_X("hostfxr_main_bundle_startupinfo")); + + const pal::string_t dotnet_folder = get_filename(dotnet_root); + + if (pal::strcmp(dotnet_folder.c_str(), _X("mockhostfxrBundleVersionFailure")) == 0) + { + trace::error(_X("Failure processing application bundle.")); + trace::error(_X("Bundle header version compatibility check failed.")); + + return StatusCode::BundleExtractionFailure; + } + + return StatusCode::Success; +} +#endif diff --git a/src/native/corehost/test/nativehost/CMakeLists.txt b/src/native/corehost/test/nativehost/CMakeLists.txt index 44282bc19e4322..c21e95a1c71d9d 100644 --- a/src/native/corehost/test/nativehost/CMakeLists.txt +++ b/src/native/corehost/test/nativehost/CMakeLists.txt @@ -56,5 +56,5 @@ endif() # Specify non-default Windows libs to be used for Arm/Arm64 builds if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)) - target_link_libraries(${DOTNET_PROJECT_NAME} Advapi32.lib Ole32.lib OleAut32.lib) + target_link_libraries(${DOTNET_PROJECT_NAME} Ole32.lib OleAut32.lib) endif() diff --git a/src/native/eventpipe/ds-dump-protocol.c b/src/native/eventpipe/ds-dump-protocol.c index 4e247c3aa0e1c9..0a933049d56b8e 100644 --- a/src/native/eventpipe/ds-dump-protocol.c +++ b/src/native/eventpipe/ds-dump-protocol.c @@ -51,7 +51,7 @@ generate_core_dump_command_try_parse_payload ( if (!ds_ipc_message_try_parse_string_utf16_t (&buffer_cursor, &buffer_cursor_len, &instance->dump_name ) || !ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &instance->dump_type) || - !ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &instance->diagnostics)) + !ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &instance->flags)) ep_raise_error (); ep_on_exit: @@ -106,6 +106,7 @@ dump_protocol_helper_generate_core_dump ( return false; bool result = false; + DiagnosticsDumpCommandId commandId = (DiagnosticsDumpCommandId)ds_ipc_header_get_commandid (ds_ipc_message_get_header_ref (message)); DiagnosticsGenerateCoreDumpCommandPayload *payload; payload = (DiagnosticsGenerateCoreDumpCommandPayload *)ds_ipc_message_try_parse_payload (message, generate_core_dump_command_try_parse_payload); @@ -115,8 +116,8 @@ dump_protocol_helper_generate_core_dump ( } ds_ipc_result_t ipc_result; - ipc_result = ds_rt_generate_core_dump (payload); - if (result != DS_IPC_S_OK) { + ipc_result = ds_rt_generate_core_dump (commandId, payload); + if (ipc_result != DS_IPC_S_OK) { ds_ipc_message_send_error (stream, result); ep_raise_error (); } else { @@ -147,6 +148,7 @@ ds_dump_protocol_helper_handle_ipc_message ( switch ((DiagnosticsDumpCommandId)ds_ipc_header_get_commandid (ds_ipc_message_get_header_ref (message))) { case DS_DUMP_COMMANDID_GENERATE_CORE_DUMP: + case DS_DUMP_COMMANDID_GENERATE_CORE_DUMP2: result = dump_protocol_helper_generate_core_dump (message, stream); break; default: diff --git a/src/native/eventpipe/ds-dump-protocol.h b/src/native/eventpipe/ds-dump-protocol.h index 22e429ab3e4979..8065e8cbd4d870 100644 --- a/src/native/eventpipe/ds-dump-protocol.h +++ b/src/native/eventpipe/ds-dump-protocol.h @@ -27,13 +27,13 @@ struct _DiagnosticsGenerateCoreDumpCommandPayload_Internal { // The protocol buffer is defined as: // string - dumpName (UTF16) // int - dumpType - // int - diagnostics + // uint32 - flags // returns // ulong - status const ep_char16_t *dump_name; uint32_t dump_type; - uint32_t diagnostics; + uint32_t flags; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_DUMP_PROTOCOL_GETTER_SETTER) @@ -44,7 +44,7 @@ struct _DiagnosticsGenerateCoreDumpCommandPayload { DS_DEFINE_GETTER(DiagnosticsGenerateCoreDumpCommandPayload *, generate_core_dump_command_payload, const ep_char16_t *, dump_name) DS_DEFINE_GETTER(DiagnosticsGenerateCoreDumpCommandPayload *, generate_core_dump_command_payload, uint32_t, dump_type) -DS_DEFINE_GETTER(DiagnosticsGenerateCoreDumpCommandPayload *, generate_core_dump_command_payload, uint32_t, diagnostics) +DS_DEFINE_GETTER(DiagnosticsGenerateCoreDumpCommandPayload *, generate_core_dump_command_payload, uint32_t, flags) DiagnosticsGenerateCoreDumpCommandPayload * ds_generate_core_dump_command_payload_alloc (void); diff --git a/src/native/eventpipe/ds-rt.h b/src/native/eventpipe/ds-rt.h index 81ddd3c2512cd7..8de71574463b9c 100644 --- a/src/native/eventpipe/ds-rt.h +++ b/src/native/eventpipe/ds-rt.h @@ -87,7 +87,7 @@ ds_rt_config_value_get_default_port_suspend (void); static ds_ipc_result_t -ds_rt_generate_core_dump (DiagnosticsGenerateCoreDumpCommandPayload *payload); +ds_rt_generate_core_dump (DiagnosticsDumpCommandId commandId, DiagnosticsGenerateCoreDumpCommandPayload *payload); /* * DiagnosticsIpc. diff --git a/src/native/eventpipe/ds-types.h b/src/native/eventpipe/ds-types.h index fc5d3e1a2ecccc..fba8ba8f2d2bbb 100644 --- a/src/native/eventpipe/ds-types.h +++ b/src/native/eventpipe/ds-types.h @@ -44,6 +44,7 @@ typedef struct _EventPipeStopTracingCommandPayload EventPipeStopTracingCommandPa typedef enum { DS_DUMP_COMMANDID_RESERVED = 0x00, DS_DUMP_COMMANDID_GENERATE_CORE_DUMP = 0x01, + DS_DUMP_COMMANDID_GENERATE_CORE_DUMP2 = 0x02, // future } DiagnosticsDumpCommandId; diff --git a/src/native/eventpipe/ep-config.c b/src/native/eventpipe/ep-config.c index 8b7b9a83471b05..489127b4885cde 100644 --- a/src/native/eventpipe/ep-config.c +++ b/src/native/eventpipe/ep-config.c @@ -113,6 +113,7 @@ config_register_provider ( EventPipeSessionProvider *session_provider = ep_rt_session_provider_list_find_by_name (ep_session_provider_list_get_providers_cref (providers), ep_provider_get_provider_name (provider)); if (session_provider) { EventPipeProviderCallbackData provider_callback_data; + memset (&provider_callback_data, 0, sizeof (provider_callback_data)); provider_set_config ( provider, keyword_for_all_sessions, @@ -124,6 +125,7 @@ config_register_provider ( &provider_callback_data); if (provider_callback_data_queue) ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, &provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); } } } @@ -179,6 +181,7 @@ ep_config_init (EventPipeConfiguration *config) while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) { ep_rt_prepare_provider_invoke_callback (&provider_callback_data); provider_invoke_callback (&provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); } // Create the metadata event. @@ -552,6 +555,7 @@ config_enable_disable ( int64_t keyword_for_all_sessions; EventPipeEventLevel level_for_all_sessions; EventPipeProviderCallbackData provider_callback_data; + memset (&provider_callback_data, 0, sizeof (provider_callback_data)); config_compute_keyword_and_level (config, provider, &keyword_for_all_sessions, &level_for_all_sessions); if (enable) { provider_set_config ( @@ -576,6 +580,7 @@ config_enable_disable ( } if (provider_callback_data_queue) ep_provider_callback_data_queue_enqueue (provider_callback_data_queue, &provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); } } } diff --git a/src/native/eventpipe/ep-sample-profiler.c b/src/native/eventpipe/ep-sample-profiler.c index 858d69ad5078b0..2414872cba9226 100644 --- a/src/native/eventpipe/ep-sample-profiler.c +++ b/src/native/eventpipe/ep-sample-profiler.c @@ -198,10 +198,7 @@ sample_profiler_enable (void) ep_requires_lock_held (); - const bool result = sample_profiler_load_dependecies (); - EP_ASSERT (result); - - if (result && !sample_profiler_load_profiling_enabled ()) { + if (!sample_profiler_load_profiling_enabled ()) { sample_profiler_store_profiling_enabled (true); EP_ASSERT (!ep_rt_wait_event_is_valid (&_thread_shutdown_event)); @@ -273,6 +270,8 @@ ep_sample_profiler_enable (void) if (!ep_event_is_enabled (_thread_time_event)) return; + sample_profiler_load_dependecies (); + if (_can_start_sampling) sample_profiler_enable (); diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 60a5fe0cb25832..dc3a259cae28ea 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -68,11 +68,10 @@ EP_RT_DEFINE_THREAD_FUNC (streaming_thread) ep_rt_thread_sleep (timeout_ns); } + session->streaming_thread = NULL; ep_rt_wait_event_set (&session->rt_thread_shutdown_event); EP_GCX_PREEMP_EXIT - session->streaming_thread = NULL; - if (!success) ep_disable ((EventPipeSessionID)session); diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 8bec5f127caeda..ffe7188b129b15 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -96,6 +96,9 @@ ep_provider_callback_data_alloc ( EventPipeProviderCallbackData * ep_provider_callback_data_alloc_copy (EventPipeProviderCallbackData *provider_callback_data_src); +EventPipeProviderCallbackData * +ep_provider_callback_data_alloc_move (EventPipeProviderCallbackData *provider_callback_data_src); + EventPipeProviderCallbackData * ep_provider_callback_data_init ( EventPipeProviderCallbackData *provider_callback_data, @@ -111,6 +114,11 @@ ep_provider_callback_data_init_copy ( EventPipeProviderCallbackData *provider_callback_data_dst, EventPipeProviderCallbackData *provider_callback_data_src); +EventPipeProviderCallbackData * +ep_provider_callback_data_init_move ( + EventPipeProviderCallbackData *provider_callback_data_dst, + EventPipeProviderCallbackData *provider_callback_data_src); + void ep_provider_callback_data_fini (EventPipeProviderCallbackData *provider_callback_data); diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index eb401dcaa414e6..ae8f3ce24f62fe 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -260,6 +260,26 @@ ep_provider_callback_data_alloc_copy (EventPipeProviderCallbackData *provider_ca ep_exit_error_handler (); } +EventPipeProviderCallbackData * +ep_provider_callback_data_alloc_move (EventPipeProviderCallbackData *provider_callback_data_src) +{ + EventPipeProviderCallbackData *instance = ep_rt_object_alloc (EventPipeProviderCallbackData); + ep_raise_error_if_nok (instance != NULL); + + if (provider_callback_data_src) { + *instance = *provider_callback_data_src; + memset (provider_callback_data_src, 0, sizeof (*provider_callback_data_src)); + } + +ep_on_exit: + return instance; + +ep_on_error: + ep_provider_callback_data_free (instance); + instance = NULL; + ep_exit_error_handler (); +} + EventPipeProviderCallbackData * ep_provider_callback_data_init ( EventPipeProviderCallbackData *provider_callback_data, @@ -295,6 +315,19 @@ ep_provider_callback_data_init_copy ( return provider_callback_data_dst; } +EventPipeProviderCallbackData * +ep_provider_callback_data_init_move ( + EventPipeProviderCallbackData *provider_callback_data_dst, + EventPipeProviderCallbackData *provider_callback_data_src) +{ + EP_ASSERT (provider_callback_data_dst != NULL); + EP_ASSERT (provider_callback_data_src != NULL); + + *provider_callback_data_dst = *provider_callback_data_src; + memset (provider_callback_data_src, 0, sizeof (*provider_callback_data_src)); + return provider_callback_data_dst; +} + void ep_provider_callback_data_fini (EventPipeProviderCallbackData *provider_callback_data) { @@ -621,6 +654,7 @@ disable_helper (EventPipeSessionID id) while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) { ep_rt_prepare_provider_invoke_callback (&provider_callback_data); provider_invoke_callback (&provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); } ep_provider_callback_data_queue_fini (provider_callback_data_queue); @@ -951,6 +985,7 @@ ep_enable ( while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) { ep_rt_prepare_provider_invoke_callback (&provider_callback_data); provider_invoke_callback (&provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); } ep_on_exit: @@ -1185,6 +1220,7 @@ ep_create_provider ( while (ep_provider_callback_data_queue_try_dequeue (provider_callback_data_queue, &provider_callback_data)) { ep_rt_prepare_provider_invoke_callback (&provider_callback_data); provider_invoke_callback (&provider_callback_data); + ep_provider_callback_data_fini (&provider_callback_data); } ep_rt_notify_profiler_provider_created (provider); @@ -1556,14 +1592,14 @@ ep_provider_callback_data_queue_enqueue ( EventPipeProviderCallbackData *provider_callback_data) { EP_ASSERT (provider_callback_data_queue != NULL); - EventPipeProviderCallbackData *provider_callback_data_copy = ep_provider_callback_data_alloc_copy (provider_callback_data); - ep_raise_error_if_nok (provider_callback_data_copy != NULL); - ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_push_tail (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), provider_callback_data_copy)); + EventPipeProviderCallbackData *provider_callback_data_move = ep_provider_callback_data_alloc_move (provider_callback_data); + ep_raise_error_if_nok (provider_callback_data_move != NULL); + ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_push_tail (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), provider_callback_data_move)); return true; ep_on_error: - ep_provider_callback_data_free (provider_callback_data_copy); + ep_provider_callback_data_free (provider_callback_data_move); return false; } @@ -1578,7 +1614,7 @@ ep_provider_callback_data_queue_try_dequeue ( EventPipeProviderCallbackData *value = NULL; ep_raise_error_if_nok (ep_rt_provider_callback_data_queue_pop_head (ep_provider_callback_data_queue_get_queue_ref (provider_callback_data_queue), &value)); - ep_provider_callback_data_init_copy (provider_callback_data, value); + ep_provider_callback_data_init_move (provider_callback_data, value); ep_provider_callback_data_free (value); return true; diff --git a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.csproj b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.csproj index de6a04a95f02b6..139d5672ee01a0 100644 --- a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.csproj +++ b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.csproj @@ -11,10 +11,7 @@ - - - - + diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index c69288218d69fc..84d34906680981 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -358,6 +359,10 @@ public ApkBuilder(TaskLoggingHelper logger) string javaActivityPath = Path.Combine(javaSrcFolder, "MainActivity.java"); string monoRunnerPath = Path.Combine(javaSrcFolder, "MonoRunner.java"); + Regex checkNumerics = new Regex(@"\.(\d)"); + if (!string.IsNullOrEmpty(ProjectName) && checkNumerics.IsMatch(ProjectName)) + ProjectName = checkNumerics.Replace(ProjectName, @"_$1"); + string packageId = $"net.dot.{ProjectName}"; File.WriteAllText(javaActivityPath, diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 6d0d5eeb1a49ba..c091df680d77ed 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -191,11 +191,42 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task /// public string? CacheFilePath { get; set; } + /// + /// Passes additional, custom arguments to --aot + /// + public string? AotArguments { get; set; } + + /// + /// Passes temp-path to the AOT compiler + /// + public string? TempPath { get; set; } + + /// + /// Passes ld-name to the AOT compiler, for use with UseLLVM=true + /// + public string? LdName { get; set; } + + /// + /// Passes ld-flags to the AOT compiler, for use with UseLLVM=true + /// + public string? LdFlags { get; set; } + + /// + /// Specify WorkingDirectory for the AOT compiler + /// + public string? WorkingDirectory { get; set; } + + [Required] + public string IntermediateOutputPath { get; set; } = string.Empty; + [Output] public string[]? FileWrites { get; private set; } + private static readonly Encoding s_utf8Encoding = new UTF8Encoding(false); + private List _fileWrites = new(); + private IList? _assembliesToCompile; private ConcurrentDictionary compiledAssemblies = new(); private MonoAotMode parsedAotMode; @@ -207,7 +238,7 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task private int _numCompiled; private int _totalNumAssemblies; - public override bool Execute() + private bool ProcessAndValidateArguments() { if (!File.Exists(CompilerBinaryPath)) { @@ -221,7 +252,9 @@ public override bool Execute() return false; } - if (!Path.IsPathRooted(OutputDir)) + // A relative path might be used along with WorkingDirectory, + // only call Path.GetFullPath() if WorkingDirectory is blank. + if (string.IsNullOrEmpty(WorkingDirectory) && !Path.IsPathRooted(OutputDir)) OutputDir = Path.GetFullPath(OutputDir); if (!Directory.Exists(OutputDir)) @@ -230,6 +263,9 @@ public override bool Execute() return false; } + if (!Directory.Exists(IntermediateOutputPath)) + Directory.CreateDirectory(IntermediateOutputPath); + if (AotProfilePath != null) { foreach (var path in AotProfilePath) @@ -246,7 +282,7 @@ public override bool Execute() { if (string.IsNullOrEmpty(LLVMPath)) // prevent using some random llc/opt from PATH (installed with clang) - throw new ArgumentException($"'{nameof(LLVMPath)}' is required when '{nameof(UseLLVM)}' is true.", nameof(LLVMPath)); + throw new LogAsErrorException($"'{nameof(LLVMPath)}' is required when '{nameof(UseLLVM)}' is true."); if (!Directory.Exists(LLVMPath)) { @@ -270,7 +306,7 @@ public override bool Execute() Log.LogWarning($"'{nameof(OutputType)}=Normal' is deprecated, use 'ObjectFile' instead."); parsedOutputType = MonoAotOutputType.ObjectFile; break; default: - throw new ArgumentException($"'{nameof(OutputType)}' must be one of: '{nameof(MonoAotOutputType.ObjectFile)}', '{nameof(MonoAotOutputType.AsmOnly)}', '{nameof(MonoAotOutputType.Library)}'. Received: '{OutputType}'.", nameof(OutputType)); + throw new LogAsErrorException($"'{nameof(OutputType)}' must be one of: '{nameof(MonoAotOutputType.ObjectFile)}', '{nameof(MonoAotOutputType.AsmOnly)}', '{nameof(MonoAotOutputType.Library)}'. Received: '{OutputType}'."); } switch (LibraryFormat) @@ -280,13 +316,13 @@ public override bool Execute() case "So": parsedLibraryFormat = MonoAotLibraryFormat.So; break; default: if (parsedOutputType == MonoAotOutputType.Library) - throw new ArgumentException($"'{nameof(LibraryFormat)}' must be one of: '{nameof(MonoAotLibraryFormat.Dll)}', '{nameof(MonoAotLibraryFormat.Dylib)}', '{nameof(MonoAotLibraryFormat.So)}'. Received: '{LibraryFormat}'.", nameof(LibraryFormat)); + throw new LogAsErrorException($"'{nameof(LibraryFormat)}' must be one of: '{nameof(MonoAotLibraryFormat.Dll)}', '{nameof(MonoAotLibraryFormat.Dylib)}', '{nameof(MonoAotLibraryFormat.So)}'. Received: '{LibraryFormat}'."); break; } if (parsedAotMode == MonoAotMode.LLVMOnly && !UseLLVM) { - throw new ArgumentException($"'{nameof(UseLLVM)}' must be true when '{nameof(Mode)}' is {nameof(MonoAotMode.LLVMOnly)}.", nameof(UseLLVM)); + throw new LogAsErrorException($"'{nameof(UseLLVM)}' must be true when '{nameof(Mode)}' is {nameof(MonoAotMode.LLVMOnly)}."); } switch (AotModulesTableLanguage) @@ -294,32 +330,69 @@ public override bool Execute() case "C": parsedAotModulesTableLanguage = MonoAotModulesTableLanguage.C; break; case "ObjC": parsedAotModulesTableLanguage = MonoAotModulesTableLanguage.ObjC; break; default: - throw new ArgumentException($"'{nameof(AotModulesTableLanguage)}' must be one of: '{nameof(MonoAotModulesTableLanguage.C)}', '{nameof(MonoAotModulesTableLanguage.ObjC)}'. Received: '{AotModulesTableLanguage}'.", nameof(AotModulesTableLanguage)); + throw new LogAsErrorException($"'{nameof(AotModulesTableLanguage)}' must be one of: '{nameof(MonoAotModulesTableLanguage.C)}', '{nameof(MonoAotModulesTableLanguage.ObjC)}'. Received: '{AotModulesTableLanguage}'."); } if (!string.IsNullOrEmpty(AotModulesTablePath)) { // AOT modules for static linking, needs the aot modules table UseStaticLinking = true; - - if (!GenerateAotModulesTable(Assemblies, Profilers, AotModulesTablePath)) - return false; } if (UseDirectIcalls && !UseStaticLinking) { - throw new ArgumentException($"'{nameof(UseDirectIcalls)}' can only be used with '{nameof(UseStaticLinking)}=true'.", nameof(UseDirectIcalls)); + throw new LogAsErrorException($"'{nameof(UseDirectIcalls)}' can only be used with '{nameof(UseStaticLinking)}=true'."); } if (UseDirectPInvoke && !UseStaticLinking) { - throw new ArgumentException($"'{nameof(UseDirectPInvoke)}' can only be used with '{nameof(UseStaticLinking)}=true'.", nameof(UseDirectPInvoke)); + throw new LogAsErrorException($"'{nameof(UseDirectPInvoke)}' can only be used with '{nameof(UseStaticLinking)}=true'."); } if (UseStaticLinking && (parsedOutputType == MonoAotOutputType.Library)) { - throw new ArgumentException($"'{nameof(OutputType)}=Library' can not be used with '{nameof(UseStaticLinking)}=true'.", nameof(OutputType)); + throw new LogAsErrorException($"'{nameof(OutputType)}=Library' can not be used with '{nameof(UseStaticLinking)}=true'."); + } + + foreach (var asmItem in Assemblies) + { + string? fullPath = asmItem.GetMetadata("FullPath"); + if (!File.Exists(fullPath)) + throw new LogAsErrorException($"Could not find {fullPath} to AOT"); + } + + return !Log.HasLoggedErrors; + } + + public override bool Execute() + { + try + { + return ExecuteInternal(); + } + catch (LogAsErrorException laee) + { + Log.LogError(laee.Message); + return false; + } + finally + { + if (_cache != null && _cache.Save(CacheFilePath!)) + _fileWrites.Add(CacheFilePath!); + FileWrites = _fileWrites.ToArray(); } + } + + private bool ExecuteInternal() + { + if (!ProcessAndValidateArguments()) + return false; + + _assembliesToCompile = EnsureAndGetAssembliesInTheSameDir(Assemblies); + _assembliesToCompile = FilterAssemblies(_assembliesToCompile); + + if (!string.IsNullOrEmpty(AotModulesTablePath) && !GenerateAotModulesTable(_assembliesToCompile, Profilers, AotModulesTablePath)) + return false; string? monoPaths = null; if (AdditionalAssemblySearchPaths != null) @@ -327,60 +400,136 @@ public override bool Execute() _cache = new FileCache(CacheFilePath, Log); - //FIXME: check the nothing changed at all case + List argsList = new(); + foreach (var assemblyItem in _assembliesToCompile) + argsList.Add(GetPrecompileArgumentsFor(assemblyItem, monoPaths)); - _totalNumAssemblies = Assemblies.Length; - int allowedParallelism = Math.Min(Assemblies.Length, Environment.ProcessorCount); - if (BuildEngine is IBuildEngine9 be9) - allowedParallelism = be9.RequestCores(allowedParallelism); - - if (DisableParallelAot || allowedParallelism == 1) + _totalNumAssemblies = _assembliesToCompile.Count; + if (CheckAllUpToDate(argsList)) { - foreach (var assemblyItem in Assemblies) - { - if (!PrecompileLibrarySerial(assemblyItem, monoPaths)) - return !Log.HasLoggedErrors; - } + Log.LogMessage(MessageImportance.High, "Everything is up-to-date, nothing to precompile"); + + _fileWrites.AddRange(argsList.SelectMany(args => args.ProxyFiles).Select(pf => pf.TargetFile)); + foreach (var args in argsList) + compiledAssemblies.GetOrAdd(args.AOTAssembly.ItemSpec, args.AOTAssembly); } else { + int allowedParallelism = DisableParallelAot ? 1 : Math.Min(_assembliesToCompile.Count, Environment.ProcessorCount); + if (BuildEngine is IBuildEngine9 be9) + allowedParallelism = be9.RequestCores(allowedParallelism); + ParallelLoopResult result = Parallel.ForEach( - Assemblies, - new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, - (assemblyItem, state) => PrecompileLibraryParallel(assemblyItem, monoPaths, state)); + argsList, + new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, + (args, state) => PrecompileLibraryParallel(args, state)); - if (!result.IsCompleted) + if (result.IsCompleted) + { + int numUnchanged = _totalNumAssemblies - _numCompiled; + if (numUnchanged > 0 && numUnchanged != _totalNumAssemblies) + Log.LogMessage(MessageImportance.High, $"[{numUnchanged}/{_totalNumAssemblies}] skipped unchanged assemblies."); + } + else if (!Log.HasLoggedErrors) { - if (!Log.HasLoggedErrors) - Log.LogError("Unknown failed occured while compiling"); + Log.LogError($"Precompiling failed due to unknown reasons. Check log for more info"); + } + } + + CompiledAssemblies = ConvertAssembliesDictToOrderedList(compiledAssemblies, _assembliesToCompile).ToArray(); + return !Log.HasLoggedErrors; + } + private bool CheckAllUpToDate(IList argsList) + { + foreach (var args in argsList) + { + // compare original assembly vs it's outputs.. all it's outputs! + string assemblyPath = args.AOTAssembly.GetMetadata("FullPath"); + if (args.ProxyFiles.Any(pf => IsNewerThanOutput(assemblyPath, pf.TargetFile))) return false; + } + + return true; + + static bool IsNewerThanOutput(string inFile, string outFile) + => !File.Exists(inFile) || !File.Exists(outFile) || + (File.GetLastWriteTimeUtc(inFile) > File.GetLastWriteTimeUtc(outFile)); + } + + private IList FilterAssemblies(IEnumerable assemblies) + { + List filteredAssemblies = new(); + foreach (var asmItem in assemblies) + { + if (ShouldSkip(asmItem)) + { + if (parsedAotMode == MonoAotMode.LLVMOnly) + throw new LogAsErrorException($"Building in AOTMode=LLVMonly is not compatible with excluding any assemblies for AOT. Excluded assembly: {asmItem.ItemSpec}"); + + Log.LogMessage(MessageImportance.Low, $"Skipping {asmItem.ItemSpec} because it has %(AOT_InternalForceToInterpret)=true"); + continue; } + + string assemblyPath = asmItem.GetMetadata("FullPath"); + using var assemblyFile = File.OpenRead(assemblyPath); + using PEReader reader = new(assemblyFile, PEStreamOptions.Default); + if (!reader.HasMetadata) + { + Log.LogWarning($"Skipping unmanaged {assemblyPath} for AOT"); + continue; + } + + filteredAssemblies.Add(asmItem); } - int numUnchanged = _totalNumAssemblies - _numCompiled; - if (numUnchanged > 0 && numUnchanged != _totalNumAssemblies) - Log.LogMessage(MessageImportance.High, $"[{numUnchanged}/{_totalNumAssemblies}] skipped unchanged assemblies."); + return filteredAssemblies; - if (_cache.Save(CacheFilePath!)) - _fileWrites.Add(CacheFilePath!); + static bool ShouldSkip(ITaskItem asmItem) + => bool.TryParse(asmItem.GetMetadata("AOT_InternalForceToInterpret"), out bool skip) && skip; + } - CompiledAssemblies = ConvertAssembliesDictToOrderedList(compiledAssemblies, Assemblies).ToArray(); - FileWrites = _fileWrites.ToArray(); + private IList EnsureAndGetAssembliesInTheSameDir(IList assemblies) + { + string firstAsmDir = Path.GetDirectoryName(assemblies.First().GetMetadata("FullPath")) ?? string.Empty; + bool allInSameDir = assemblies.All(asm => Path.GetDirectoryName(asm.GetMetadata("FullPath")) == firstAsmDir); + if (allInSameDir) + return assemblies; - return !Log.HasLoggedErrors; + // Copy to aot-in + + string aotInPath = Path.Combine(IntermediateOutputPath, "aot-in"); + Directory.CreateDirectory(aotInPath); + + List newAssemblies = new(); + foreach (var asmItem in assemblies) + { + string asmPath = asmItem.GetMetadata("FullPath"); + string newPath = Path.Combine(aotInPath, Path.GetFileName(asmPath)); + + // FIXME: delete files not in originalAssemblies though + // FIXME: or .. just delete the whole dir? + if (Utils.CopyIfDifferent(asmPath, newPath, useHash: true)) + Log.LogMessage(MessageImportance.Low, $"Copying {asmPath} to {newPath}"); + _fileWrites.Add(newPath); + + ITaskItem newAsm = new TaskItem(newPath); + asmItem.CopyMetadataTo(newAsm); + newAssemblies.Add(newAsm); + } + + return newAssemblies; } - private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) + private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, string? monoPaths) { - string assembly = assemblyItem.ItemSpec; + string assembly = assemblyItem.GetMetadata("FullPath"); string assemblyDir = Path.GetDirectoryName(assembly)!; var aotAssembly = new TaskItem(assembly); var aotArgs = new List(); var processArgs = new List(); bool isDedup = assembly == DedupAssembly; List proxyFiles = new(capacity: 5); - string msgPrefix = $"[{Path.GetFileName(assembly)}] "; var a = assemblyItem.GetMetadata("AotArguments"); if (a != null) @@ -562,63 +711,84 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) } } + if (!string.IsNullOrEmpty(AotArguments)) + { + aotArgs.Add(AotArguments); + } + + if (!string.IsNullOrEmpty(TempPath)) + { + aotArgs.Add($"temp-path={TempPath}"); + } + + if (!string.IsNullOrEmpty(LdName)) + { + aotArgs.Add($"ld-name={LdName}"); + } + + if (!string.IsNullOrEmpty(LdFlags)) + { + aotArgs.Add($"ld-flags={LdFlags}"); + } + // we need to quote the entire --aot arguments here to make sure it is parsed // on Windows as one argument. Otherwise it will be split up into multiple // values, which wont work. processArgs.Add($"\"--aot={string.Join(",", aotArgs)}\""); - string paths = ""; if (isDedup) { - StringBuilder sb = new StringBuilder(); - HashSet allPaths = new HashSet(); - foreach (var aItem in Assemblies) - { - string filename = aItem.ItemSpec; - processArgs.Add(filename); - string dir = Path.GetDirectoryName(filename)!; - if (!allPaths.Contains(dir)) - { - allPaths.Add(dir); - if (sb.Length > 0) - sb.Append(Path.PathSeparator); - sb.Append(dir); - } - } - if (sb.Length > 0) - sb.Append(Path.PathSeparator); - sb.Append(monoPaths); - paths = sb.ToString(); + foreach (var aItem in _assembliesToCompile!) + processArgs.Add(aItem.ItemSpec); } else { - paths = $"{assemblyDir}{Path.PathSeparator}{monoPaths}"; - processArgs.Add('"' + assemblyFilename + '"'); + if (string.IsNullOrEmpty(WorkingDirectory)) + { + processArgs.Add('"' + assemblyFilename + '"'); + } + else + { + // If WorkingDirectory is supplied, the caller could be passing in a relative path + // Use the original ItemSpec that was passed in. + processArgs.Add('"' + assemblyItem.ItemSpec + '"'); + } } + monoPaths = $"{assemblyDir}{Path.PathSeparator}{monoPaths}"; var envVariables = new Dictionary { - {"MONO_PATH", paths}, + {"MONO_PATH", monoPaths }, {"MONO_ENV_OPTIONS", string.Empty} // we do not want options to be provided out of band to the cross compilers }; var responseFileContent = string.Join(" ", processArgs); var responseFilePath = Path.GetTempFileName(); - using (var sw = new StreamWriter(responseFilePath, append: false, encoding: new UTF8Encoding(false))) + using (var sw = new StreamWriter(responseFilePath, append: false, encoding: s_utf8Encoding)) { sw.WriteLine(responseFileContent); } - string workingDir = assemblyDir; + return new PrecompileArguments(ResponseFilePath: responseFilePath, + EnvironmentVariables: envVariables, + WorkingDir: string.IsNullOrEmpty(WorkingDirectory) ? assemblyDir : WorkingDirectory, + AOTAssembly: aotAssembly, + ProxyFiles: proxyFiles); + } + private bool PrecompileLibrary(PrecompileArguments args) + { + string assembly = args.AOTAssembly.GetMetadata("FullPath"); try { + string msgPrefix = $"[{Path.GetFileName(assembly)}] "; + // run the AOT compiler (int exitCode, string output) = Utils.TryRunProcess(Log, CompilerBinaryPath, - $"--response=\"{responseFilePath}\"", - envVariables, - workingDir, + $"--response=\"{args.ResponseFilePath}\"", + args.EnvironmentVariables, + args.WorkingDir, silent: true, debugMessageImportance: MessageImportance.Low, label: Path.GetFileName(assembly)); @@ -627,18 +797,18 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) // Log the command in a compact format which can be copy pasted { StringBuilder envStr = new StringBuilder(string.Empty); - foreach (KeyValuePair kvp in envVariables) + foreach (KeyValuePair kvp in args.EnvironmentVariables) envStr.Append($"{kvp.Key}={kvp.Value} "); - Log.LogMessage(importance, $"{msgPrefix}Exec (with response file contents expanded) in {workingDir}: {envStr}{CompilerBinaryPath} {responseFileContent}"); + Log.LogMessage(importance, $"{msgPrefix}Exec (with response file contents expanded) in {args.WorkingDir}: {envStr}{CompilerBinaryPath} {File.ReadAllText(args.ResponseFilePath, s_utf8Encoding)}"); } - Log.LogMessage(importance, output); - if (exitCode != 0) { - Log.LogError($"Precompiling failed for {assembly}"); + Log.LogError($"Precompiling failed for {assembly}.{Environment.NewLine}{output}"); return false; } + + Log.LogMessage(importance, output); } catch (Exception ex) { @@ -646,70 +816,52 @@ private bool PrecompileLibrary(ITaskItem assemblyItem, string? monoPaths) Log.LogError($"Precompiling failed for {assembly}: {ex.Message}"); return false; } - + finally + { + File.Delete(args.ResponseFilePath); + } bool copied = false; - foreach (var proxyFile in proxyFiles) + foreach (var proxyFile in args.ProxyFiles) { - if (!File.Exists(proxyFile.TempFile)) - { - Log.LogError($"Precompiling failed for {assembly}. Could not find output file {proxyFile.TempFile}"); - return false; - } - copied |= proxyFile.CopyOutputFileIfChanged(); _fileWrites.Add(proxyFile.TargetFile); } if (copied) { - string copiedFiles = string.Join(", ", proxyFiles.Select(tf => Path.GetFileName(tf.TargetFile))); + string copiedFiles = string.Join(", ", args.ProxyFiles.Select(tf => Path.GetFileName(tf.TargetFile))); int count = Interlocked.Increment(ref _numCompiled); Log.LogMessage(MessageImportance.High, $"[{count}/{_totalNumAssemblies}] {Path.GetFileName(assembly)} -> {copiedFiles}"); } - File.Delete(responseFilePath); - compiledAssemblies.GetOrAdd(aotAssembly.ItemSpec, aotAssembly); + compiledAssemblies.GetOrAdd(args.AOTAssembly.ItemSpec, args.AOTAssembly); return true; } - private bool PrecompileLibrarySerial(ITaskItem assemblyItem, string? monoPaths) + private void PrecompileLibraryParallel(PrecompileArguments args, ParallelLoopState state) { try { - if (!PrecompileLibrary(assemblyItem, monoPaths)) - return !Log.HasLoggedErrors; - return true; + if (PrecompileLibrary(args)) + return; } - catch (Exception ex) + catch (LogAsErrorException laee) { - if (Log.HasLoggedErrors) - Log.LogMessage(MessageImportance.Low, $"Precompile failed for {assemblyItem}: {ex}"); - else - Log.LogError($"Precompile failed for {assemblyItem}: {ex}"); - - return false; - } - } - - private void PrecompileLibraryParallel(ITaskItem assemblyItem, string? monoPaths, ParallelLoopState state) - { - try - { - if (!PrecompileLibrary(assemblyItem, monoPaths)) - state.Break(); + Log.LogError($"Precompiling failed for {args.AOTAssembly}: {laee.Message}"); } catch (Exception ex) { if (Log.HasLoggedErrors) - Log.LogMessage(MessageImportance.Low, $"Precompile failed for {assemblyItem}: {ex}"); + Log.LogMessage(MessageImportance.Low, $"Precompile failed for {args.AOTAssembly}: {ex}"); else - Log.LogError($"Precompile failed for {assemblyItem}: {ex}"); - state.Break(); + Log.LogError($"Precompiling failed for {args.AOTAssembly}: {ex}"); } + + state.Break(); } - private bool GenerateAotModulesTable(ITaskItem[] assemblies, string[]? profilers, string outputFile) + private bool GenerateAotModulesTable(IEnumerable assemblies, string[]? profilers, string outputFile) { var symbols = new List(); foreach (var asm in assemblies) @@ -827,18 +979,34 @@ private bool TryGetAssemblyName(string asmPath, [NotNullWhen(true)] out string? } } - private IList ConvertAssembliesDictToOrderedList(ConcurrentDictionary dict, ITaskItem[] items) + private static IList ConvertAssembliesDictToOrderedList(ConcurrentDictionary dict, IList originalAssemblies) { - List outItems = new(items.Length); - foreach (ITaskItem item in items) + List outItems = new(originalAssemblies.Count); + foreach (ITaskItem item in originalAssemblies) { - if (!dict.TryGetValue(item.ItemSpec, out ITaskItem? dictItem)) - throw new LogAsErrorException($"Bug: Could not find item in the dict with key {item.ItemSpec}"); - - outItems.Add(dictItem); + if (dict.TryGetValue(item.GetMetadata("FullPath"), out ITaskItem? dictItem)) + outItems.Add(dictItem); } return outItems; } + + internal class PrecompileArguments + { + public PrecompileArguments(string ResponseFilePath, IDictionary EnvironmentVariables, string WorkingDir, ITaskItem AOTAssembly, IList ProxyFiles) + { + this.ResponseFilePath = ResponseFilePath; + this.EnvironmentVariables = EnvironmentVariables; + this.WorkingDir = WorkingDir; + this.AOTAssembly = AOTAssembly; + this.ProxyFiles = ProxyFiles; + } + + public string ResponseFilePath { get; private set; } + public IDictionary EnvironmentVariables { get; private set; } + public string WorkingDir { get; private set; } + public ITaskItem AOTAssembly { get; private set; } + public IList ProxyFiles { get; private set; } + } } internal class FileCache @@ -867,7 +1035,7 @@ public FileCache(string? cacheFilePath, TaskLoggingHelper log) } _oldCache ??= new(); - _newCache = new(); + _newCache = new(_oldCache.FileHashes); } public bool ShouldCopy(ProxyFile proxyFile, [NotNullWhen(true)] out string? cause) @@ -927,21 +1095,28 @@ public bool CopyOutputFileIfChanged() if (!_cache.Enabled) return true; - if (!_cache.ShouldCopy(this, out string? cause)) + try { - _cache.Log.LogMessage(MessageImportance.Low, $"Skipping copying over {TargetFile} as the contents are unchanged"); - return false; - } + if (!_cache.ShouldCopy(this, out string? cause)) + { + _cache.Log.LogMessage(MessageImportance.Low, $"Skipping copying over {TargetFile} as the contents are unchanged"); + return false; + } - if (File.Exists(TargetFile)) - File.Delete(TargetFile); + if (File.Exists(TargetFile)) + File.Delete(TargetFile); - File.Copy(TempFile, TargetFile); - File.Delete(TempFile); + File.Copy(TempFile, TargetFile); - _cache.Log.LogMessage(MessageImportance.Low, $"Copying {TempFile} to {TargetFile} because {cause}"); - return true; + _cache.Log.LogMessage(MessageImportance.Low, $"Copying {TempFile} to {TargetFile} because {cause}"); + return true; + } + finally + { + File.Delete(TempFile); + } } + } public enum MonoAotMode @@ -977,6 +1152,10 @@ public enum MonoAotModulesTableLanguage internal class CompilerCache { + public CompilerCache() => FileHashes = new(); + public CompilerCache(IDictionary oldHashes) + => FileHashes = new(oldHashes); + [JsonPropertyName("file_hashes")] - public ConcurrentDictionary FileHashes { get; set; } = new(); + public ConcurrentDictionary FileHashes { get; set; } } diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj b/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj index 6371df56223568..caf34787a2d4a4 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.csproj @@ -11,10 +11,8 @@ $(NoWarn),CS8604,CS8602 - - - - + + @@ -36,6 +34,7 @@ <_PublishFramework Include="$(TargetFrameworks)" /> + diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.props b/src/tasks/AotCompilerTask/MonoAOTCompiler.props index 4f2721d7483cef..6ef2f973eb8140 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.props +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.props @@ -1,8 +1,10 @@ - + + - + + @@ -20,7 +22,8 @@ - + + diff --git a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs index 9127192f9f6c4f..bd0a775ce55109 100644 --- a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs +++ b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs @@ -15,7 +15,7 @@ public class AppleAppBuilderTask : Task private string targetOS = TargetNames.iOS; /// - /// The Apple OS we are targeting (iOS or tvOS) + /// The Apple OS we are targeting (ios, tvos, iossimulator, tvossimulator) /// [Required] public string TargetOS @@ -64,7 +64,7 @@ public string TargetOS public ITaskItem[] Assemblies { get; set; } = Array.Empty(); /// - /// Target arch, can be "arm64" (device) or "x64" (simulator) at the moment + /// Target arch, can be "arm64", "arm" or "x64" at the moment /// [Required] public string Arch { get; set; } = ""!; @@ -106,6 +106,11 @@ public string TargetOS /// public bool GenerateXcodeProject { get; set; } + /// + /// Generate CMake project + /// + public bool GenerateCMakeProject { get; set; } + /// /// Files to be ignored in AppDir /// @@ -153,6 +158,11 @@ public string TargetOS /// public bool EnableRuntimeLogging { get; set; } + /// + /// Enables App Sandbox for Mac Catalyst apps + /// + public bool EnableAppSandbox { get; set; } + public override bool Execute() { bool isDevice = (TargetOS == TargetNames.iOS || TargetOS == TargetNames.tvOS); @@ -224,14 +234,17 @@ public override bool Execute() throw new ArgumentException("Using DiagnosticPorts require diagnostics_tracing runtime component."); } - if (GenerateXcodeProject) + if (EnableAppSandbox && (string.IsNullOrEmpty(DevTeamProvisioning) || DevTeamProvisioning == "-")) { - Xcode generator = new Xcode(Log, TargetOS, Arch); - generator.EnableRuntimeLogging = EnableRuntimeLogging; - generator.DiagnosticPorts = DiagnosticPorts; + throw new ArgumentException("DevTeamProvisioning must be set to a valid value when App Sandbox is enabled, using '-' is not supported."); + } + + var generator = new Xcode(Log, TargetOS, Arch); + if (GenerateXcodeProject) + { XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles, assemblerFilesToLink, - AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, RuntimeComponents, NativeMainSource); + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource); if (BuildAppBundle) { @@ -242,10 +255,15 @@ public override bool Execute() } else { - AppBundlePath = generator.BuildAppBundle(XcodeProjectPath, Arch, Optimized, DevTeamProvisioning); + AppBundlePath = generator.BuildAppBundle(XcodeProjectPath, Optimized, DevTeamProvisioning); } } } + else if (GenerateCMakeProject) + { + generator.GenerateCMake(ProjectName, MainLibraryFileName, assemblerFiles, assemblerFilesToLink, + AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource); + } return true; } diff --git a/src/tasks/AppleAppBuilder/AppleAppBuilder.csproj b/src/tasks/AppleAppBuilder/AppleAppBuilder.csproj index 7ceb4480e1ce78..e28dafef5d8fd5 100644 --- a/src/tasks/AppleAppBuilder/AppleAppBuilder.csproj +++ b/src/tasks/AppleAppBuilder/AppleAppBuilder.csproj @@ -11,10 +11,7 @@ - - - - + diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index 2e938d8ea0e36b..36f9d3ab732acc 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -9,10 +9,111 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; +public class XcodeCreateProject : Task +{ + private string targetOS = TargetNames.iOS; + + /// + /// The Apple OS we are targeting (ios, tvos, iossimulator, tvossimulator) + /// + [Required] + public string TargetOS + { + get + { + return targetOS; + } + + set + { + targetOS = value.ToLower(); + } + } + + /// + /// Target arch, can be "arm64", "arm" or "x64" at the moment + /// + [Required] + public string Arch { get; set; } = ""!; + + /// + /// Path to the directory with the CMakeLists.txt to create a project for. + /// + [Required] + public string CMakeListsDirectory { get; set; } = ""!; + + /// + /// Name of the generated project. + /// + [Required] + public string ProjectName { get; set; } = ""!; + + public override bool Execute() + { + new Xcode(Log, TargetOS, Arch).CreateXcodeProject(ProjectName, CMakeListsDirectory); + + return true; + } +} + +public class XcodeBuildApp : Task +{ + private string targetOS = TargetNames.iOS; + + /// + /// The Apple OS we are targeting (ios, tvos, iossimulator, tvossimulator) + /// + [Required] + public string TargetOS + { + get + { + return targetOS; + } + + set + { + targetOS = value.ToLower(); + } + } + + /// + /// Target arch, can be "arm64", "arm" or "x64" at the moment + /// + [Required] + public string Arch { get; set; } = ""!; + + /// + /// Path to the .xcodeproj file + /// + [Required] + public string XcodeProjectPath { get; set; } = ""!; + + /// + /// DEVELOPER_TEAM provisioning, needed for arm64 builds. + /// + public string? DevTeamProvisioning { get; set; } + + /// + /// Produce optimized binaries and use 'Release' config in xcode + /// + public bool Optimized { get; set; } + + /// Path to the directory where the .app should be created + /// + public string? DestinationFolder { get; set; } + + public override bool Execute() + { + new Xcode(Log, TargetOS, Arch).BuildAppBundle(XcodeProjectPath, Optimized, DevTeamProvisioning, DestinationFolder); + + return true; + } +} + internal class Xcode { private string RuntimeIdentifier { get; set; } - private string SysRoot { get; set; } private string Target { get; set; } private string XcodeArch { get; set; } private TaskLoggingHelper Logger { get; set; } @@ -21,33 +122,72 @@ public Xcode(TaskLoggingHelper logger, string target, string arch) { Logger = logger; Target = target; - XcodeArch = (arch == "x64") ? "x86_64" : arch; + RuntimeIdentifier = $"{Target}-{arch}"; + XcodeArch = arch switch { + "x64" => "x86_64", + "arm" => "armv7", + _ => arch + }; + } + + public string GenerateXCode( + string projectName, + string entryPointLib, + IEnumerable asmFiles, + IEnumerable asmLinkFiles, + string workspace, + string binDir, + string monoInclude, + bool preferDylibs, + bool useConsoleUiTemplate, + bool forceAOT, + bool forceInterpreter, + bool invariantGlobalization, + bool optimized, + bool enableRuntimeLogging, + bool enableAppSandbox, + string? diagnosticPorts, + string? runtimeComponents=null, + string? nativeMainSource = null) + { + var cmakeDirectoryPath = GenerateCMake(projectName, entryPointLib, asmFiles, asmLinkFiles, workspace, binDir, monoInclude, preferDylibs, useConsoleUiTemplate, forceAOT, forceInterpreter, invariantGlobalization, optimized, enableRuntimeLogging, enableAppSandbox, diagnosticPorts, runtimeComponents, nativeMainSource); + CreateXcodeProject(projectName, cmakeDirectoryPath); + return Path.Combine(binDir, projectName, projectName + ".xcodeproj"); + } + + public void CreateXcodeProject(string projectName, string cmakeDirectoryPath) + { + string targetName; switch (Target) { - case TargetNames.iOS: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk iphoneos --show-sdk-path"); + case TargetNames.MacCatalyst: + targetName = "Darwin"; break; + case TargetNames.iOS: case TargetNames.iOSsim: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk iphonesimulator --show-sdk-path"); + targetName = "iOS"; break; case TargetNames.tvOS: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk appletvos --show-sdk-path"); - break; case TargetNames.tvOSsim: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk appletvsimulator --show-sdk-path"); + targetName = "tvOS"; break; default: - SysRoot = Utils.RunProcess(Logger, "xcrun", "--sdk macosx --show-sdk-path"); + targetName = Target.ToString(); break; } + var deployTarget = (Target == TargetNames.MacCatalyst) ? " -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch : " -DCMAKE_OSX_DEPLOYMENT_TARGET=10.1"; + var cmakeArgs = new StringBuilder(); + cmakeArgs + .Append("-S.") + .Append(" -B").Append(projectName) + .Append(" -GXcode") + .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName) + .Append(deployTarget); - RuntimeIdentifier = $"{Target}-{arch}"; + Utils.RunProcess(Logger, "cmake", cmakeArgs.ToString(), workingDir: cmakeDirectoryPath); } - public bool EnableRuntimeLogging { get; set; } - public string? DiagnosticPorts { get; set; } = ""!; - - public string GenerateXCode( + public string GenerateCMake( string projectName, string entryPointLib, IEnumerable asmFiles, @@ -60,13 +200,16 @@ public string GenerateXCode( bool forceAOT, bool forceInterpreter, bool invariantGlobalization, - bool stripDebugSymbols, + bool optimized, + bool enableRuntimeLogging, + bool enableAppSandbox, + string? diagnosticPorts, string? runtimeComponents=null, string? nativeMainSource = null) { // bundle everything as resources excluding native files var excludes = new List { ".dll.o", ".dll.s", ".dwarf", ".m", ".h", ".a", ".bc", "libmonosgen-2.0.dylib", "libcoreclr.dylib" }; - if (stripDebugSymbols) + if (optimized) { excludes.Add(".pdb"); } @@ -95,7 +238,8 @@ public string GenerateXCode( var entitlements = new List>(); bool hardenedRuntime = false; - if (Target == TargetNames.MacCatalyst && !forceAOT) { + if (Target == TargetNames.MacCatalyst && !forceAOT) + { hardenedRuntime = true; /* for mmmap MAP_JIT */ @@ -104,6 +248,15 @@ public string GenerateXCode( entitlements.Add (KeyValuePair.Create ("com.apple.security.cs.disable-library-validation", "")); } + if (enableAppSandbox) + { + hardenedRuntime = true; + entitlements.Add (KeyValuePair.Create ("com.apple.security.app-sandbox", "")); + + // the networking entitlement is necessary to enable communication between the test app and xharness + entitlements.Add (KeyValuePair.Create ("com.apple.security.network.client", "")); + } + string cmakeLists = Utils.GetEmbeddedResource("CMakeLists.txt.template") .Replace("%ProjectName%", projectName) .Replace("%AppResources%", string.Join(Environment.NewLine, resources.Where(r => !r.EndsWith("-llvm.o")).Select(r => " " + Path.GetRelativePath(binDir, r)))) @@ -181,9 +334,9 @@ public string GenerateXCode( { // these libraries are linked via modules.m var name = Path.GetFileNameWithoutExtension(asm); - aotSources += $"add_library({name} OBJECT {asm}){Environment.NewLine}"; - toLink += $" {name}{Environment.NewLine}"; - aotList += $" {name}"; + aotSources += $"add_library({projectName}_{name} OBJECT {asm}){Environment.NewLine}"; + toLink += $" {projectName}_{name}{Environment.NewLine}"; + aotList += $" {projectName}_{name}"; } foreach (string asmLinkFile in asmLinkFiles) @@ -219,14 +372,14 @@ public string GenerateXCode( defines.AppendLine("add_definitions(-DINVARIANT_GLOBALIZATION=1)"); } - if (EnableRuntimeLogging) + if (enableRuntimeLogging) { defines.AppendLine("add_definitions(-DENABLE_RUNTIME_LOGGING=1)"); } - if (!string.IsNullOrEmpty(DiagnosticPorts)) + if (!string.IsNullOrEmpty(diagnosticPorts)) { - defines.AppendLine($"\nadd_definitions(-DDIAGNOSTIC_PORTS=\"{DiagnosticPorts}\")"); + defines.AppendLine($"\nadd_definitions(-DDIAGNOSTIC_PORTS=\"{diagnosticPorts}\")"); } cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString()); @@ -252,33 +405,6 @@ public string GenerateXCode( File.WriteAllText(Path.Combine(binDir, "app.entitlements"), entitlementsTemplate.Replace("%Entitlements%", ent.ToString())); } - string targetName; - switch (Target) - { - case TargetNames.MacCatalyst: - targetName = "Darwin"; - break; - case TargetNames.iOS: - case TargetNames.iOSsim: - targetName = "iOS"; - break; - case TargetNames.tvOS: - case TargetNames.tvOSsim: - targetName = "tvOS"; - break; - default: - targetName = Target.ToString(); - break; - } - var deployTarget = (Target == TargetNames.MacCatalyst) ? " -DCMAKE_OSX_ARCHITECTURES=" + XcodeArch : " -DCMAKE_OSX_DEPLOYMENT_TARGET=10.1"; - var cmakeArgs = new StringBuilder(); - cmakeArgs - .Append("-S.") - .Append(" -B").Append(projectName) - .Append(" -GXcode") - .Append(" -DCMAKE_SYSTEM_NAME=").Append(targetName) - .Append(deployTarget); - File.WriteAllText(Path.Combine(binDir, "runtime.h"), Utils.GetEmbeddedResource("runtime.h")); @@ -302,13 +428,11 @@ public string GenerateXCode( .Replace("//%APPLE_RUNTIME_IDENTIFIER%", RuntimeIdentifier) .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib))); - Utils.RunProcess(Logger, "cmake", cmakeArgs.ToString(), workingDir: binDir); - - return Path.Combine(binDir, projectName, projectName + ".xcodeproj"); + return binDir; } public string BuildAppBundle( - string xcodePrjPath, string architecture, bool optimized, string? devTeamProvisioning = null) + string xcodePrjPath, bool optimized, string? devTeamProvisioning = null, string? destination = null) { string sdk = ""; var args = new StringBuilder(); @@ -330,29 +454,28 @@ public string BuildAppBundle( .Append(" DEVELOPMENT_TEAM=").Append(devTeamProvisioning); } - - if (architecture == "arm64") + if (XcodeArch == "arm64" || XcodeArch == "armv7") { switch (Target) { case TargetNames.iOS: sdk = "iphoneos"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.iOSsim: sdk = "iphonesimulator"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.tvOS: sdk = "appletvos"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.tvOSsim: sdk = "appletvsimulator"; - args.Append(" -arch arm64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; default: @@ -372,12 +495,12 @@ public string BuildAppBundle( { case TargetNames.iOSsim: sdk = "iphonesimulator"; - args.Append(" -arch x86_64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; case TargetNames.tvOSsim: sdk = "appletvsimulator"; - args.Append(" -arch x86_64") + args.Append(" -arch " + XcodeArch) .Append(" -sdk ").Append(sdk); break; default: @@ -400,6 +523,13 @@ public string BuildAppBundle( string appPath = Path.Combine(Path.GetDirectoryName(xcodePrjPath)!, config + "-" + sdk, Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); + if (destination != null) + { + var newAppPath = Path.Combine(destination, Path.GetFileNameWithoutExtension(xcodePrjPath) + ".app"); + Directory.Move(appPath, newAppPath); + appPath = newAppPath; + } + long appSize = new DirectoryInfo(appPath) .EnumerateFiles("*", SearchOption.AllDirectories) .Sum(file => file.Length); diff --git a/src/tasks/Common/Utils.cs b/src/tasks/Common/Utils.cs index 2c1a8b49370c7a..2c624214937d66 100644 --- a/src/tasks/Common/Utils.cs +++ b/src/tasks/Common/Utils.cs @@ -212,7 +212,7 @@ public static bool CopyIfDifferent(string src, string dst, bool useHash) throw new ArgumentException($"Cannot find {src} file to copy", nameof(src)); bool areDifferent = !File.Exists(dst) || - (useHash && Utils.ComputeHash(src) != Utils.ComputeHash(dst)) || + (useHash && ComputeHash(src) != ComputeHash(dst)) || (File.ReadAllText(src) != File.ReadAllText(dst)); if (areDifferent) diff --git a/src/tasks/Crossgen2Tasks/Crossgen2Tasks.csproj b/src/tasks/Crossgen2Tasks/Crossgen2Tasks.csproj index fcd5b20ab2cf31..ddddfadb59358e 100644 --- a/src/tasks/Crossgen2Tasks/Crossgen2Tasks.csproj +++ b/src/tasks/Crossgen2Tasks/Crossgen2Tasks.csproj @@ -9,11 +9,8 @@ $(NoWarn),CS8604,CS8602 - - - - - + + diff --git a/src/tasks/Directory.Build.props b/src/tasks/Directory.Build.props index 695833da3dbcd7..887be3a86036fb 100644 --- a/src/tasks/Directory.Build.props +++ b/src/tasks/Directory.Build.props @@ -3,6 +3,9 @@ net472 + + + net6.0 diff --git a/src/tasks/ILStripTask/ILStrip.cs b/src/tasks/ILStripTask/ILStrip.cs index 7ce5a5ecc07cf1..8086e68b91785f 100644 --- a/src/tasks/ILStripTask/ILStrip.cs +++ b/src/tasks/ILStripTask/ILStrip.cs @@ -8,10 +8,10 @@ using System.Threading.Tasks; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; -using Mono.Cecil; -using Mono.Cecil.Binary; -using Mono.Cecil.Cil; -using Mono.Cecil.Metadata; +using CilStrip.Mono.Cecil; +using CilStrip.Mono.Cecil.Binary; +using CilStrip.Mono.Cecil.Cil; +using CilStrip.Mono.Cecil.Metadata; public class ILStrip : Microsoft.Build.Utilities.Task { diff --git a/src/tasks/ILStripTask/ILStrip.csproj b/src/tasks/ILStripTask/ILStrip.csproj index 879c56f26ae262..91b63a8c0a63cc 100644 --- a/src/tasks/ILStripTask/ILStrip.csproj +++ b/src/tasks/ILStripTask/ILStrip.csproj @@ -8,10 +8,7 @@ false - - - - + @@ -27,6 +24,7 @@ <_PublishFramework Include="$(TargetFrameworks)" /> + diff --git a/src/tasks/JsonToItemsTaskFactory/JsonToItemsTaskFactory.csproj b/src/tasks/JsonToItemsTaskFactory/JsonToItemsTaskFactory.csproj index d6df214fce7963..579682fd84f704 100644 --- a/src/tasks/JsonToItemsTaskFactory/JsonToItemsTaskFactory.csproj +++ b/src/tasks/JsonToItemsTaskFactory/JsonToItemsTaskFactory.csproj @@ -9,12 +9,15 @@ - - - - + + + + + + + @@ -26,6 +29,7 @@ <_PublishFramework Include="$(TargetFrameworks)" /> + diff --git a/src/tasks/RuntimeConfigParser/RuntimeConfigParser.csproj b/src/tasks/RuntimeConfigParser/RuntimeConfigParser.csproj index 2fb35e649eed73..074f89c415ac35 100644 --- a/src/tasks/RuntimeConfigParser/RuntimeConfigParser.csproj +++ b/src/tasks/RuntimeConfigParser/RuntimeConfigParser.csproj @@ -10,10 +10,8 @@ $(NoWarn),CS8604,CS8602 - - - - + + @@ -33,6 +31,7 @@ <_PublishFramework Include="$(TargetFrameworks)" /> + diff --git a/src/tasks/WasmAppBuilder/EmccCompile.cs b/src/tasks/WasmAppBuilder/EmccCompile.cs index e869e98e8564ff..66d4743d81b4d4 100644 --- a/src/tasks/WasmAppBuilder/EmccCompile.cs +++ b/src/tasks/WasmAppBuilder/EmccCompile.cs @@ -44,6 +44,19 @@ public class EmccCompile : Microsoft.Build.Utilities.Task private int _numCompiled; public override bool Execute() + { + try + { + return ExecuteActual(); + } + catch (LogAsErrorException laee) + { + Log.LogError(laee.Message); + return false; + } + } + + private bool ExecuteActual() { if (SourceFiles.Length == 0) { @@ -82,6 +95,7 @@ public override bool Execute() if (!ShouldCompile(srcFile, objFile, depFiles, out string reason)) { Log.LogMessage(MessageImportance.Low, $"Skipping {srcFile} because {reason}."); + outputItems.Add(CreateOutputItemFor(srcFile, objFile)); } else { @@ -94,7 +108,8 @@ public override bool Execute() if (_numCompiled == _totalFiles) { // nothing to do! - return true; + OutputFiles = outputItems.ToArray(); + return !Log.HasLoggedErrors; } if (_numCompiled > 0) @@ -110,31 +125,20 @@ public override bool Execute() _tempPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(_tempPath); - int allowedParallelism = Math.Min(SourceFiles.Length, Environment.ProcessorCount); + int allowedParallelism = DisableParallelCompile ? 1 : Math.Min(SourceFiles.Length, Environment.ProcessorCount); if (BuildEngine is IBuildEngine9 be9) allowedParallelism = be9.RequestCores(allowedParallelism); - if (DisableParallelCompile || allowedParallelism == 1) + ParallelLoopResult result = Parallel.ForEach(filesToCompile, + new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, + (toCompile, state) => { - foreach ((string srcFile, string outFile) in filesToCompile) - { - if (!ProcessSourceFile(srcFile, outFile)) - return false; - } - } - else - { - ParallelLoopResult result = Parallel.ForEach(filesToCompile, - new ParallelOptions { MaxDegreeOfParallelism = allowedParallelism }, - (toCompile, state) => - { - if (!ProcessSourceFile(toCompile.Item1, toCompile.Item2)) - state.Stop(); - }); + if (!ProcessSourceFile(toCompile.Item1, toCompile.Item2)) + state.Stop(); + }); - if (!result.IsCompleted && !Log.HasLoggedErrors) - Log.LogError("Unknown failed occured while compiling"); - } + if (!result.IsCompleted && !Log.HasLoggedErrors) + Log.LogError("Unknown failure occured while compiling. Check logs to get more details."); if (!Log.HasLoggedErrors) { @@ -187,9 +191,7 @@ bool ProcessSourceFile(string srcFile, string objFile) else Log.LogMessage(MessageImportance.Low, $"Copied {tmpObjFile} to {objFile}"); - ITaskItem newItem = new TaskItem(objFile); - newItem.SetMetadata("SourceFile", srcFile); - outputItems.Add(newItem); + outputItems.Add(CreateOutputItemFor(srcFile, objFile)); int count = Interlocked.Increment(ref _numCompiled); Log.LogMessage(MessageImportance.High, $"[{count}/{_totalFiles}] {Path.GetFileName(srcFile)} -> {Path.GetFileName(objFile)} [took {elapsedSecs:F}s]"); @@ -206,12 +208,19 @@ bool ProcessSourceFile(string srcFile, string objFile) File.Delete(tmpObjFile); } } + + ITaskItem CreateOutputItemFor(string srcFile, string objFile) + { + ITaskItem newItem = new TaskItem(objFile); + newItem.SetMetadata("SourceFile", srcFile); + return newItem; + } } private bool ShouldCompile(string srcFile, string objFile, string[] depFiles, out string reason) { if (!File.Exists(srcFile)) - throw new ArgumentException($"Could not find source file {srcFile}"); + throw new LogAsErrorException($"Could not find source file {srcFile}"); if (!File.Exists(objFile)) { @@ -228,7 +237,7 @@ private bool ShouldCompile(string srcFile, string objFile, string[] depFiles, ou return true; } - reason = "everything is up-to-date."; + reason = "everything is up-to-date"; return false; bool IsNewerThanOutput(string inFile, string outFile, out string reason) diff --git a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs index 13c75c39bc64cd..a9f5f95161575d 100644 --- a/src/tasks/WasmAppBuilder/IcallTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/IcallTableGenerator.cs @@ -23,6 +23,9 @@ public class IcallTableGenerator : Task [Required, NotNull] public string? OutputPath { get; set; } + [Output] + public string? FileWrites { get; private set; } = ""; + private List _icalls = new List (); private Dictionary _runtimeIcalls = new Dictionary (); @@ -42,7 +45,7 @@ public void GenIcallTable(string runtimeIcallTableFile, string[] assemblies) { ReadTable (runtimeIcallTableFile); var resolver = new PathAssemblyResolver(assemblies); - var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); + using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); foreach (var aname in assemblies) { var a = mlc.LoadFromAssemblyPath(aname); @@ -58,6 +61,7 @@ public void GenIcallTable(string runtimeIcallTableFile, string[] assemblies) Log.LogMessage(MessageImportance.Low, $"Generating icall table to '{OutputPath}'."); else Log.LogMessage(MessageImportance.Low, $"Icall table in {OutputPath} is unchanged."); + FileWrites = OutputPath; File.Delete(tmpFileName); } @@ -103,11 +107,8 @@ private void EmitTable (StreamWriter w) // Read the icall table generated by mono --print-icall-table private void ReadTable (string filename) { - JsonDocument json; - using (var stream = File.Open (filename, FileMode.Open)) - { - json = JsonDocument.Parse (stream); - } + using var stream = File.OpenRead (filename); + using JsonDocument json = JsonDocument.Parse (stream); var arr = json.RootElement; foreach (var v in arr.EnumerateArray ()) diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index f6b89533f98632..c1c0d70a302db8 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -3,33 +3,53 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; -using System.Text.Json; using System.Reflection; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; public class PInvokeTableGenerator : Task { - [Required] - public ITaskItem[]? Modules { get; set; } - [Required] - public ITaskItem[]? Assemblies { get; set; } + [Required, NotNull] + public string[]? Modules { get; set; } + [Required, NotNull] + public string[]? Assemblies { get; set; } [Required, NotNull] public string? OutputPath { get; set; } - private static char[] s_charsToReplace = new[] { '.', '-', }; + [Output] + public string FileWrites { get; private set; } = string.Empty; + + private static char[] s_charsToReplace = new[] { '.', '-', '+' }; public override bool Execute() { - GenPInvokeTable(Modules!.Select(item => item.ItemSpec).ToArray(), Assemblies!.Select(item => item.ItemSpec).ToArray()); - return true; + if (Assemblies.Length == 0) + { + Log.LogError($"No assemblies given to scan for pinvokes"); + return false; + } + + if (Modules.Length == 0) + { + Log.LogError($"{nameof(PInvokeTableGenerator)}.{nameof(Modules)} cannot be empty"); + return false; + } + + try + { + GenPInvokeTable(Modules, Assemblies); + return !Log.HasLoggedErrors; + } + catch (LogAsErrorException laee) + { + Log.LogError(laee.Message); + return false; + } } public void GenPInvokeTable(string[] pinvokeModules, string[] assemblies) @@ -42,7 +62,7 @@ public void GenPInvokeTable(string[] pinvokeModules, string[] assemblies) var callbacks = new List(); var resolver = new PathAssemblyResolver(assemblies); - var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); + using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); foreach (var aname in assemblies) { var a = mlc.LoadFromAssemblyPath(aname); @@ -61,13 +81,28 @@ public void GenPInvokeTable(string[] pinvokeModules, string[] assemblies) Log.LogMessage(MessageImportance.Low, $"Generating pinvoke table to '{OutputPath}'."); else Log.LogMessage(MessageImportance.Low, $"PInvoke table in {OutputPath} is unchanged."); + FileWrites = OutputPath; File.Delete(tmpFileName); } private void CollectPInvokes(List pinvokes, List callbacks, Type type) { - foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance)) { + foreach (var method in type.GetMethods(BindingFlags.DeclaredOnly|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static|BindingFlags.Instance)) + { + try + { + CollectPInvokesForMethod(method); + } + catch (Exception ex) + { + Log.LogMessage(MessageImportance.Low, $"Could not get pinvoke, or callbacks for method {method.Name}: {ex}"); + continue; + } + } + + void CollectPInvokesForMethod(MethodInfo method) + { if ((method.Attributes & MethodAttributes.PinvokeImpl) != 0) { var dllimport = method.CustomAttributes.First(attr => attr.AttributeType.Name == "DllImportAttribute"); @@ -97,25 +132,40 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary modules w.WriteLine("// GENERATED FILE, DO NOT MODIFY"); w.WriteLine(); - var decls = new HashSet(); - foreach (var pinvoke in pinvokes.OrderBy(l => l.EntryPoint)) + var pinvokesGroupedByEntryPoint = pinvokes + .Where(l => modules.ContainsKey(l.Module)) + .OrderBy(l => l.EntryPoint) + .GroupBy(l => l.EntryPoint); + + var comparer = new PInvokeComparer(); + foreach (IGrouping group in pinvokesGroupedByEntryPoint) { - if (modules.ContainsKey(pinvoke.Module)) { - try - { - var decl = GenPInvokeDecl(pinvoke); - if (decls.Contains(decl)) - continue; + var candidates = group.Distinct(comparer).ToArray(); + PInvoke first = candidates[0]; + if (ShouldTreatAsVariadic(candidates)) + { + string imports = string.Join(Environment.NewLine, + candidates.Select( + p => $" {p.Method} (in [{p.Method.DeclaringType?.Assembly.GetName().Name}] {p.Method.DeclaringType})")); + Log.LogWarning($"Found a native function ({first.EntryPoint}) with varargs in {first.Module}." + + " Calling such functions is not supported, and will fail at runtime." + + $" Managed DllImports: {Environment.NewLine}{imports}"); - w.WriteLine(decl); - decls.Add(decl); - } - catch (NotSupportedException) - { - // See the FIXME in GenPInvokeDecl - Log.LogWarning($"Cannot handle function pointer arguments/return value in pinvoke method '{pinvoke.Method}' in type '{pinvoke.Method.DeclaringType}'."); - pinvoke.Skip = true; - } + foreach (var c in candidates) + c.Skip = true; + + continue; + } + + var decls = new HashSet(); + foreach (var candidate in candidates) + { + var decl = GenPInvokeDecl(candidate); + if (decl == null || decls.Contains(decl)) + continue; + + w.WriteLine(decl); + decls.Add(decl); } } @@ -128,7 +178,8 @@ private void EmitPInvokeTable(StreamWriter w, Dictionary modules Where(l => l.Module == module && !l.Skip). OrderBy(l => l.EntryPoint). GroupBy(d => d.EntryPoint). - Select (l => "{\"" + l.Key + "\", " + l.Key + "}, // " + string.Join (", ", l.Select(c => c.Method.DeclaringType!.Module!.Assembly!.GetName ()!.Name!).Distinct().OrderBy(n => n))); + Select (l => "{\"" + FixupSymbolName(l.Key) + "\", " + FixupSymbolName(l.Key) + "}, " + + "// " + string.Join (", ", l.Select(c => c.Method.DeclaringType!.Module!.Assembly!.GetName ()!.Name!).Distinct().OrderBy(n => n))); foreach (var pinvoke in assemblies_pinvokes) { w.WriteLine (pinvoke); @@ -162,6 +213,61 @@ static string ModuleNameToId(string name) return fixedName; } + + static bool ShouldTreatAsVariadic(PInvoke[] candidates) + { + if (candidates.Length < 2) + return false; + + PInvoke first = candidates[0]; + if (TryIsMethodGetParametersUnsupported(first.Method, out _)) + return false; + + int firstNumArgs = first.Method.GetParameters().Length; + return candidates + .Skip(1) + .Any(c => !TryIsMethodGetParametersUnsupported(c.Method, out _) && + c.Method.GetParameters().Length != firstNumArgs); + } + } + + private static string FixupSymbolName(string name) + { + UTF8Encoding utf8 = new(); + byte[] bytes = utf8.GetBytes(name); + StringBuilder sb = new(); + + foreach (byte b in bytes) + { + if ((b >= (byte)'0' && b <= (byte)'9') || + (b >= (byte)'a' && b <= (byte)'z') || + (b >= (byte)'A' && b <= (byte)'Z') || + (b == (byte)'_')) + { + sb.Append((char) b); + } + else if (s_charsToReplace.Contains((char) b)) + { + sb.Append('_'); + } + else + { + sb.Append($"_{b:X}_"); + } + } + + return sb.ToString(); + } + + private static string SymbolNameForMethod(MethodInfo method) + { + StringBuilder sb = new(); + Type? type = method.DeclaringType; + sb.Append($"{type!.Module!.Assembly!.GetName()!.Name!}_"); + sb.Append($"{(type!.IsNested ? type!.FullName : type!.Name)}_"); + sb.Append(method.Name); + + return FixupSymbolName(sb.ToString()); } private string MapType (Type t) @@ -181,18 +287,48 @@ private string MapType (Type t) return "int"; } - private string GenPInvokeDecl(PInvoke pinvoke) + // FIXME: System.Reflection.MetadataLoadContext can't decode function pointer types + // https://github.com/dotnet/runtime/issues/43791 + private static bool TryIsMethodGetParametersUnsupported(MethodInfo method, [NotNullWhen(true)] out string? reason) + { + try + { + method.GetParameters(); + } + catch (NotSupportedException nse) + { + reason = nse.Message; + return true; + } + catch + { + // not concerned with other exceptions + } + + reason = null; + return false; + } + + private string? GenPInvokeDecl(PInvoke pinvoke) { var sb = new StringBuilder(); var method = pinvoke.Method; if (method.Name == "EnumCalendarInfo") { // FIXME: System.Reflection.MetadataLoadContext can't decode function pointer types // https://github.com/dotnet/runtime/issues/43791 - sb.Append($"int {pinvoke.EntryPoint} (int, int, int, int, int);"); + sb.Append($"int {FixupSymbolName(pinvoke.EntryPoint)} (int, int, int, int, int);"); return sb.ToString(); } + + if (TryIsMethodGetParametersUnsupported(pinvoke.Method, out string? reason)) + { + Log.LogWarning($"Skipping the following DllImport because '{reason}'. {Environment.NewLine} {pinvoke.Method}"); + pinvoke.Skip = true; + return null; + } + sb.Append(MapType(method.ReturnType)); - sb.Append($" {pinvoke.EntryPoint} ("); + sb.Append($" {FixupSymbolName(pinvoke.EntryPoint)} ("); int pindex = 0; var pars = method.GetParameters(); foreach (var p in pars) { @@ -244,7 +380,7 @@ private void EmitNativeToInterp(StreamWriter w, List callbacks) sb.Append($" (*WasmInterpEntrySig_{cb_index}) ("); int pindex = 0; if (method.ReturnType.Name != "Void") { - sb.Append("int"); + sb.Append("int*"); pindex++; } foreach (var p in method.GetParameters()) { @@ -333,20 +469,16 @@ private void EmitNativeToInterp(StreamWriter w, List callbacks) private static bool IsBlittable (Type type) { - if (type.IsPrimitive || type.IsByRef || type.IsPointer) + if (type.IsPrimitive || type.IsByRef || type.IsPointer || type.IsEnum) return true; else return false; } - private static void Error (string msg) - { - // FIXME: - throw new Exception(msg); - } + private static void Error (string msg) => throw new LogAsErrorException(msg); } -internal class PInvoke +internal class PInvoke : IEquatable { public PInvoke(string entryPoint, string module, MethodInfo method) { @@ -359,6 +491,30 @@ public PInvoke(string entryPoint, string module, MethodInfo method) public string Module; public MethodInfo Method; public bool Skip; + + public bool Equals(PInvoke? other) + => other != null && + string.Equals(EntryPoint, other.EntryPoint, StringComparison.Ordinal) && + string.Equals(Module, other.Module, StringComparison.Ordinal) && + string.Equals(Method.ToString(), other.Method.ToString(), StringComparison.Ordinal); + + public override string ToString() => $"{{ EntryPoint: {EntryPoint}, Module: {Module}, Method: {Method}, Skip: {Skip} }}"; +} + +internal class PInvokeComparer : IEqualityComparer +{ + public bool Equals(PInvoke? x, PInvoke? y) + { + if (x == null && y == null) + return true; + if (x == null || y == null) + return false; + + return x.Equals(y); + } + + public int GetHashCode(PInvoke pinvoke) + => $"{pinvoke.EntryPoint}{pinvoke.Module}{pinvoke.Method}".GetHashCode(); } internal class PInvokeCallback diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index 57cb7c383f107a..58b4b9259e629c 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -117,11 +117,24 @@ public IcuData(string name) : base(name, "icu") {} } public override bool Execute () + { + try + { + return ExecuteInternal(); + } + catch (LogAsErrorException laee) + { + Log.LogError(laee.Message); + return false; + } + } + + private bool ExecuteInternal () { if (!File.Exists(MainJS)) - throw new ArgumentException($"File MainJS='{MainJS}' doesn't exist."); + throw new LogAsErrorException($"File MainJS='{MainJS}' doesn't exist."); if (!InvariantGlobalization && string.IsNullOrEmpty(IcuDataFileName)) - throw new ArgumentException("IcuDataFileName property shouldn't be empty if InvariantGlobalization=false"); + throw new LogAsErrorException("IcuDataFileName property shouldn't be empty if InvariantGlobalization=false"); if (Assemblies?.Length == 0) { @@ -162,8 +175,12 @@ public override bool Execute () } FileCopyChecked(MainJS!, Path.Combine(AppDir, "runtime.js"), string.Empty); - var html = @""; - File.WriteAllText(Path.Combine(AppDir, "index.html"), html); + string indexHtmlPath = Path.Combine(AppDir, "index.html"); + if (!File.Exists(indexHtmlPath)) + { + var html = @""; + File.WriteAllText(indexHtmlPath, html); + } foreach (var assembly in _assemblies) { diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj index 3c93ab5d643ac8..358de5541e354d 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -6,6 +6,7 @@ $(NoWarn),CS8604,CS8602 false + true @@ -15,37 +16,35 @@ + - - - - - + + - + + + - - - <_PublishFramework Include="$(TargetFrameworks)" /> - - - + + + + + + + + - <_PublishFramework Remove="@(_PublishFramework)" /> - <_PublishFramework Include="$(TargetFrameworks)" /> - - - diff --git a/src/tasks/WasmBuildTasks/WasmBuildTasks.csproj b/src/tasks/WasmBuildTasks/WasmBuildTasks.csproj index 0f8b6c93993a47..fd88116ca0a855 100644 --- a/src/tasks/WasmBuildTasks/WasmBuildTasks.csproj +++ b/src/tasks/WasmBuildTasks/WasmBuildTasks.csproj @@ -6,10 +6,7 @@ $(NoWarn),CA1050 - - - - + (); - public override bool Execute() { if (!HasMetadata(WorkloadId, nameof(WorkloadId), "Version") || @@ -48,6 +46,12 @@ public override bool Execute() return false; } + if (!File.Exists(NuGetConfigFile)) + { + Log.LogError($"Cannot find NuGetConfigFile={NuGetConfigFile}"); + return false; + } + Log.LogMessage(MessageImportance.High, $"{Environment.NewLine}** Installing workload manifest {WorkloadId.ItemSpec} **{Environment.NewLine}"); string nugetConfigContents = GetNuGetConfig(); @@ -84,32 +88,11 @@ public override bool Execute() return !Log.HasLoggedErrors; } - private string GetNuGetConfig() - { - StringBuilder nugetConfigBuilder = new(); - nugetConfigBuilder.AppendLine($"{Environment.NewLine}"); - - nugetConfigBuilder.AppendLine($@""); - foreach (ITaskItem source in ExtraNuGetSources) - { - string key = source.ItemSpec; - string value = source.GetMetadata("Value"); - if (string.IsNullOrEmpty(value)) - { - Log.LogWarning($"ExtraNuGetSource {key} is missing Value metadata"); - continue; - } - - nugetConfigBuilder.AppendLine($@""); - } - - nugetConfigBuilder.AppendLine($"{Environment.NewLine}"); - return nugetConfigBuilder.ToString(); - } + private string GetNuGetConfig() => File.ReadAllText(NuGetConfigFile); private bool InstallWorkloadManifest(string name, string version, string nugetConfigContents, bool stopOnMissing) { - Log.LogMessage(MessageImportance.High, $"Installing workload manifest for {name}/{version}"); + Log.LogMessage(MessageImportance.High, $"Installing workload manifest for {name}/{version} for sdk band {VersionBand}"); // Find any existing directory with the manifest name, ignoring the case // Multiple directories for a manifest, differing only in case causes @@ -162,7 +145,15 @@ private bool InstallWorkloadManifest(string name, string version, string nugetCo { if (!InstallWorkloadManifest(depName, depVersion, nugetConfigContents, stopOnMissing: false)) { - Log.LogWarning($"Could not install manifest {depName}/{depVersion}. This can be ignored if the workload {WorkloadId.ItemSpec} doesn't depend on it."); + Log.LogMessage(MessageImportance.High, + $" ***** warning ******{Environment.NewLine}" + + Environment.NewLine + + $"Could not install a dependent manifest {depName}/{depVersion} for sdk band {VersionBand}.{Environment.NewLine}" + + $"If this is because this manifest doesn't have a package for sdk band {VersionBand}, " + + $"then the workload resolver will automatically fallback to the older one, and this message can be ignored.{Environment.NewLine}" + + $"This can also be safely ignored if the workload {WorkloadId.ItemSpec} doesn't use the dependency.{Environment.NewLine}" + + Environment.NewLine + + $" ********************{Environment.NewLine}"); continue; } } diff --git a/src/tasks/WorkloadBuildTasks/PackageInstaller.cs b/src/tasks/WorkloadBuildTasks/PackageInstaller.cs index 227dcb4fbf9b70..d656b1f1d5750e 100644 --- a/src/tasks/WorkloadBuildTasks/PackageInstaller.cs +++ b/src/tasks/WorkloadBuildTasks/PackageInstaller.cs @@ -63,7 +63,7 @@ private bool InstallActual(PackageReference[] references, bool stopOnMissing) (int exitCode, string output) = Utils.TryRunProcess(_logger, "dotnet", args, silent: false, debugMessageImportance: MessageImportance.Low); if (exitCode != 0) { - LogErrorOrWarning($"Restoring packages failed with exit code: {exitCode}. Output:{Environment.NewLine}{output}", stopOnMissing); + LogFailure($"Restoring packages failed with exit code: {exitCode}. Output:{Environment.NewLine}{output}", stopOnMissing); return false; } @@ -76,7 +76,7 @@ private bool InstallActual(PackageReference[] references, bool stopOnMissing) { _logger.LogMessage(MessageImportance.Normal, output); foreach ((PackageReference pkgRef, string pkgDir) in failedToRestore) - LogErrorOrWarning($"Could not restore {pkgRef.Name}/{pkgRef.Version} (can't find {pkgDir})", stopOnMissing); + LogFailure($"Could not restore {pkgRef.Name}/{pkgRef.Version} (can't find {pkgDir})", stopOnMissing); return false; } @@ -91,7 +91,7 @@ private bool LayoutPackages(IEnumerable references, bool stopO var source = Path.Combine(_packagesDir, pkgRef.Name.ToLower(), pkgRef.Version, pkgRef.relativeSourceDir); if (!Directory.Exists(source)) { - LogErrorOrWarning($"Failed to restore {pkgRef.Name}/{pkgRef.Version} (could not find {source})", stopOnMissing); + LogFailure($"Failed to restore {pkgRef.Name}/{pkgRef.Version} (could not find {source})", stopOnMissing); if (stopOnMissing) return false; } @@ -152,12 +152,12 @@ private bool CopyDirectoryAfresh(string srcDir, string destDir) } } - private void LogErrorOrWarning(string msg, bool stopOnMissing) + private void LogFailure(string msg, bool asError) { - if (stopOnMissing) + if (asError) _logger.LogError(msg); else - _logger.LogWarning(msg); + _logger.LogMessage(MessageImportance.High, $"warning: {msg}"); } } } diff --git a/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj b/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj index 537418ef31dc6d..bec88895f4c28a 100644 --- a/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj +++ b/src/tasks/WorkloadBuildTasks/WorkloadBuildTasks.csproj @@ -8,10 +8,7 @@ - - - - + - $(TargetFrameworkForNETCoreTasks);net461 + $(NetCoreAppToolCurrent);$(NetFrameworkToolCurrent) false false - + - - - + + + - + diff --git a/src/tasks/tasks.proj b/src/tasks/tasks.proj index 9c62f8b76b989f..03a049e1bf46f9 100644 --- a/src/tasks/tasks.proj +++ b/src/tasks/tasks.proj @@ -1,6 +1,11 @@ + + + + - + false + $(ProductVersion) @@ -36,8 +36,8 @@ - - + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs index 412bf4a3da2eae..d5df20a90ff547 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmBuildAppTest.cs @@ -110,13 +110,14 @@ public void PropertiesFromRuntimeConfigJson(BuildArgs buildArgs, RunHost host, s }"; BuildProject(buildArgs, - initProject: () => - { - File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); - File.WriteAllText(Path.Combine(_projectDir!, "runtimeconfig.template.json"), runtimeConfigTemplateJson); - }, - id: id, - dotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release")); + id: id, + new BuildProjectOptions( + InitProject: () => + { + File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); + File.WriteAllText(Path.Combine(_projectDir!, "runtimeconfig.template.json"), runtimeConfigTemplateJson); + }, + DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("test_runtimeconfig_json: 25", output), host: host, id: id); @@ -139,12 +140,13 @@ public void PropertiesFromCsproj(BuildArgs buildArgs, RunHost host, string id) "; BuildProject(buildArgs, - initProject: () => - { - File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); - }, - id: id, - dotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release")); + id: id, + new BuildProjectOptions( + InitProject: () => + { + File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText); + }, + DotnetWasmFromRuntimePack: !(buildArgs.AOT || buildArgs.Config == "Release"))); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("System.Threading.ThreadPool.MaxThreads: 20", output), host: host, id: id); @@ -165,9 +167,10 @@ void TestMain(string projectName, dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); BuildProject(buildArgs, - initProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), - id: id, - dotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack); + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); RunAndTestWasmApp(buildArgs, expectedExitCode: 42, test: output => Assert.Contains("Hello, World!", output), host: host, id: id); diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs new file mode 100644 index 00000000000000..00674bf4630dcc --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/WasmNativeDefaultsTests.cs @@ -0,0 +1,103 @@ +// 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.IO; +using Xunit; +using Xunit.Abstractions; +using Xunit.Sdk; + +#nullable enable + +namespace Wasm.Build.Tests +{ + public class WasmNativeDefaultsTests : BuildTestBase + { + public WasmNativeDefaultsTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [Theory] + /* relink by default for publish+Release */ + [InlineData("Release", "", /*aot*/ false, /*build*/ false, /*publish*/ true)] + /* NO relink by default for publish+Release, even when not trimming */ + [InlineData("Release", "false", /*aot*/ false, /*build*/ false, /*publish*/ false)] + + [InlineData("Debug", "", /*aot*/ false, /*build*/ false, /*publish*/ false)] + + /* AOT */ + [InlineData("Release", "", /*aot*/ true, /*build*/ false, /*publish*/ true)] + [InlineData("Debug", "", /*aot*/ true, /*build*/ false, /*publish*/ true)] + // FIXME: separate test + // [InlineData("Release", "true", + // /*aot*/ true, /*build*/ true, /*publish*/ true)] + + /* AOT not affected by trimming */ + [InlineData("Release", "false", /*aot*/ true, /*build*/ false, /*publish*/ true)] + [InlineData("Debug", "false", /*aot*/ true, /*build*/ false, /*publish*/ true)] + public void Defaults(string config, string extraProperties, bool aot, bool buildValue, bool publishValue) + { + string output = CheckWasmNativeDefaultValue("native_defaults_publish", config, extraProperties, aot, dotnetWasmFromRuntimePack: !publishValue); + + Assert.Contains($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output); + Assert.Contains($"** WasmBuildNative: '{publishValue.ToString().ToLower()}', WasmBuildingForNestedPublish: 'true'", output); + Assert.Contains("Stopping the build", output); + } + + [Theory] + /* always relink */ + [InlineData("Release", "", /*build*/ true, /*publish*/ true)] + [InlineData("Debug", "", /*build*/ true, /*publish*/ true)] + [InlineData("Release", "false", /*build*/ true, /*publish*/ true)] + public void WithNativeReference(string config, string extraProperties, bool buildValue, bool publishValue) + { + string nativeLibPath = Path.Combine(BuildEnvironment.TestAssetsPath, "native-libs", "native-lib.o"); + string nativeRefItem = @$""; + string output = CheckWasmNativeDefaultValue("native_defaults_publish", + config, + extraProperties, + aot: false, + dotnetWasmFromRuntimePack: !publishValue, + extraItems: nativeRefItem); + + Assert.Contains($"** WasmBuildNative: '{buildValue.ToString().ToLower()}', WasmBuildingForNestedPublish: ''", output); + Assert.Contains($"** WasmBuildNative: '{publishValue.ToString().ToLower()}', WasmBuildingForNestedPublish: 'true'", output); + Assert.Contains("Stopping the build", output); + } + + private string CheckWasmNativeDefaultValue(string projectName, + string config, + string extraProperties, + bool aot, + bool dotnetWasmFromRuntimePack, + string extraItems = "") + { + // builds with -O0 + extraProperties += "<_WasmDevel>true"; + + string printValueTarget = @" + + + + "; + + BuildArgs buildArgs = new(ProjectName: projectName, Config: config, AOT: aot, string.Empty, null); + buildArgs = ExpandBuildArgs(buildArgs, + extraProperties: extraProperties, + extraItems: extraItems, + insertAtEnd: printValueTarget); + + (_, string output) = BuildProject(buildArgs, + id: Path.GetRandomFileName(), + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), s_mainReturns42), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + ExpectSuccess: false, + UseCache: false, + BuildOnlyAfterPublish: false)); + + return output; + } + } +} diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets index f77fc96c48d059..5cef9821d8f805 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Directory.Build.targets @@ -10,7 +10,8 @@ + AfterTargets="ProcessFrameworkReferences" + Condition="'$(WasmNativeWorkload)' == 'true'"> @@ -21,7 +22,8 @@ + AfterTargets="ResolveFrameworkReferences" + Condition="'$(WasmNativeWorkload)' == 'true'"> + AfterTargets="ResolveTargetingPackAssets" + Condition="'$(WasmNativeWorkload)' == 'true'"> @@ -56,7 +59,7 @@ diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.props b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.props new file mode 100644 index 00000000000000..909ea0382ba0ef --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.props @@ -0,0 +1,11 @@ + + + $(RuntimeSrcDir)\artifacts\bin\ + $([MSBuild]::NormalizeDirectory($(ArtifactsBinDir), 'microsoft.netcore.app.runtime.browser-wasm', $(RuntimeConfig))) + + + + $(WasmBuildSupportDir)\ + $([MSBuild]::NormalizeDirectory($(BuildBaseDir), 'microsoft.netcore.app.runtime.browser-wasm')) + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets new file mode 100644 index 00000000000000..639a8413dc3f6a --- /dev/null +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Blazor.Local.Directory.Build.targets @@ -0,0 +1,36 @@ + + + <_MicrosoftNetCoreAppRefDir>$(AppRefDir)\ + + + + + + + + + + + + + + + + + diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.props b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.props index 1a9c112e747d9b..6d53e53b3bf551 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.props +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.props @@ -7,8 +7,4 @@ - - - PrepareForWasmBuild;$(WasmBuildAppDependsOn) - diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.targets index 65f76e4fc8582c..b327d1e91f6eb8 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Local.Directory.Build.targets @@ -16,12 +16,6 @@ Text="%24(WasmMainJS) is set when %24(WasmGenerateAppBundle) is not true: it won't be used because an app bundle is not being generated. Possible build authoring error" /> - - - - - - diff --git a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets index 105c0a74c08757..34eeeaeee7bd7c 100644 --- a/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets +++ b/src/tests/BuildWasmApps/Wasm.Build.Tests/data/Workloads.Directory.Build.targets @@ -1,15 +1,8 @@ - PrepareForWasmBuild;$(WasmBuildAppDependsOn) <_MicrosoftNetCoreAppRefDir>$(AppRefDir)\ - - - - - - diff --git a/src/tests/BuildWasmApps/testassets/native-libs/variadic.c b/src/tests/BuildWasmApps/testassets/native-libs/variadic.c new file mode 100644 index 00000000000000..cd4009439d19da --- /dev/null +++ b/src/tests/BuildWasmApps/testassets/native-libs/variadic.c @@ -0,0 +1,14 @@ +#include + +int sum(int n, ...) +{ + int result = 0; + va_list ptr; + va_start(ptr, n); + + for (int i = 0; i < n; i++) + result += va_arg(ptr, int); + + va_end(ptr); + return result; +} diff --git a/src/tests/BuildWasmApps/testassets/native-libs/variadic.o b/src/tests/BuildWasmApps/testassets/native-libs/variadic.o new file mode 100644 index 00000000000000..b4558ce3519793 Binary files /dev/null and b/src/tests/BuildWasmApps/testassets/native-libs/variadic.o differ diff --git a/src/tests/Common/CLRTest.CrossGen.targets b/src/tests/Common/CLRTest.CrossGen.targets index 94c6c403f8411f..4d3e8ea07d3ac3 100644 --- a/src/tests/Common/CLRTest.CrossGen.targets +++ b/src/tests/Common/CLRTest.CrossGen.targets @@ -225,6 +225,7 @@ if defined RunCrossGen2 ( echo -o:!__OutputFile!>>!__ResponseFile! echo --targetarch:$(TargetArchitecture)>>!__ResponseFile! echo --verify-type-and-field-layout>>!__ResponseFile! + echo --method-layout:random>>!__ResponseFile! echo -r:!CORE_ROOT!\System.*.dll>>!__ResponseFile! echo -r:!CORE_ROOT!\Microsoft.*.dll>>!__ResponseFile! echo -r:!CORE_ROOT!\mscorlib.dll>>!__ResponseFile! diff --git a/src/tests/Common/Directory.Build.targets b/src/tests/Common/Directory.Build.targets index ed56d4d011b722..6ffee68f72477b 100644 --- a/src/tests/Common/Directory.Build.targets +++ b/src/tests/Common/Directory.Build.targets @@ -143,7 +143,7 @@ - $(PackageRID) + $(OutputRid) diff --git a/src/tests/Common/publishdependency.targets b/src/tests/Common/publishdependency.targets index 596e4573756df1..de7913a8c6afeb 100644 --- a/src/tests/Common/publishdependency.targets +++ b/src/tests/Common/publishdependency.targets @@ -28,7 +28,7 @@ + Properties="Language=C#;RuntimeIdentifier=$(OutputRid)" /> diff --git a/src/tests/Common/test_dependencies/test_dependencies.csproj b/src/tests/Common/test_dependencies/test_dependencies.csproj index 22f94efd8f2f5f..d20bbec28869cd 100644 --- a/src/tests/Common/test_dependencies/test_dependencies.csproj +++ b/src/tests/Common/test_dependencies/test_dependencies.csproj @@ -5,7 +5,7 @@ $(NetCoreAppToolCurrent) true true - win-arm;win-arm64;win-x64;win-x86;$(PackageRID) + win-arm;win-arm64;win-x64;win-x86;$(OutputRid) true diff --git a/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj b/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj index c23ba6368a498a..196db8eabec630 100644 --- a/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj +++ b/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj @@ -5,7 +5,7 @@ $(NetCoreAppToolCurrent) true true - win-arm;win-arm64;win-x64;win-x86;$(PackageRID) + win-arm;win-arm64;win-x64;win-x86;$(OutputRid) true diff --git a/src/tests/Common/wasm-test-runner/WasmTestRunner.proj b/src/tests/Common/wasm-test-runner/WasmTestRunner.proj index 5f4d4f084d13be..e2eda44d7ffc02 100644 --- a/src/tests/Common/wasm-test-runner/WasmTestRunner.proj +++ b/src/tests/Common/wasm-test-runner/WasmTestRunner.proj @@ -10,14 +10,17 @@ $(MSBuildThisFileDirectory)\obj\$(Configuration)\wasm $(TestBinDir)/WasmApp/ 99.0 + true + true $(CORE_ROOT)\WasmAppBuilder\WasmAppBuilder.dll $(CORE_ROOT)\MonoAOTCompiler\MonoAOTCompiler.dll $(CORE_ROOT)\JsonToItemsTaskFactory\JsonToItemsTaskFactory.dll $(CORE_ROOT)\RuntimeConfigParser\RuntimeConfigParser.dll + BuildApp;$(WasmBuildAppDependsOn) - + $(TestAssemblyFileName) $(AppDir) diff --git a/src/tests/Directory.Build.props b/src/tests/Directory.Build.props index 6841b4938e70b2..93868bfab8586b 100644 --- a/src/tests/Directory.Build.props +++ b/src/tests/Directory.Build.props @@ -115,7 +115,7 @@ - true + true C# F# IL diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index 8ab2ab3cd31210..086f8806513d8a 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -369,7 +369,7 @@ diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj index 2ba05527c2a42d..d9dbaa2ebd4443 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj @@ -16,13 +16,10 @@ Always + - - - - diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj b/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj index 4efa17aab45d9b..35e9eec2cae877 100644 --- a/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj +++ b/src/tests/FunctionalTests/WebAssembly/Browser/RuntimeConfig/WebAssembly.Browser.RuntimeConfig.Test.csproj @@ -5,13 +5,9 @@ 42 runtime.js - + + - - - - - diff --git a/src/tests/FunctionalTests/WebAssembly/Directory.Build.targets b/src/tests/FunctionalTests/WebAssembly/Directory.Build.targets index b0d320fabe3776..802f2525e58808 100644 --- a/src/tests/FunctionalTests/WebAssembly/Directory.Build.targets +++ b/src/tests/FunctionalTests/WebAssembly/Directory.Build.targets @@ -2,13 +2,6 @@ - PrepareForWasmBuild;$(WasmBuildAppDependsOn) $(OutputPath)\$(Configuration)\AppBundle\ - - - - - - diff --git a/src/tests/Interop/COM/ComWrappers/API/Program.cs b/src/tests/Interop/COM/ComWrappers/API/Program.cs index 52da8f8d060cfd..98f09ac4d00a70 100644 --- a/src/tests/Interop/COM/ComWrappers/API/Program.cs +++ b/src/tests/Interop/COM/ComWrappers/API/Program.cs @@ -624,6 +624,9 @@ static int Main(string[] doNotUse) ValidateQueryInterfaceAfterManagedObjectCollected(); ValidateAggregationWithComObject(); ValidateAggregationWithReferenceTrackerObject(); + + // Ensure all objects have been cleaned up. + ForceGC(); } catch (Exception e) { diff --git a/src/tests/Interop/COM/ComWrappers/Common.cs b/src/tests/Interop/COM/ComWrappers/Common.cs index d100744cb271fc..bd4e7404ef2027 100644 --- a/src/tests/Interop/COM/ComWrappers/Common.cs +++ b/src/tests/Interop/COM/ComWrappers/Common.cs @@ -156,6 +156,12 @@ public static AllocationCountResult CountTrackerObjectAllocations() [DllImport(nameof(MockReferenceTrackerRuntime))] extern public static int TrackerTarget_ReleaseFromReferenceTracker(IntPtr ptr); + + // Suppressing the GC transition here as we want to make sure we are in-sync + // with the GC which is setting the connected value. + [SuppressGCTransition] + [DllImport(nameof(MockReferenceTrackerRuntime))] + extern public static byte IsTrackerObjectConnected(IntPtr instance); } [Guid("42951130-245C-485E-B60B-4ED4254256F8")] @@ -219,6 +225,12 @@ static IntPtr CreateInstance(IntPtr outer, out IntPtr inner) } else { + byte isConnected = MockReferenceTrackerRuntime.IsTrackerObjectConnected(this.classNative.Instance); + if (isConnected != 0) + { + throw new Exception("TrackerObject should be disconnected prior to finalization"); + } + ComWrappersHelper.Cleanup(ref this.classNative); } } diff --git a/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs b/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs index 7a358a972f2da6..38c25329315968 100644 --- a/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs +++ b/src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs @@ -171,6 +171,11 @@ protected override object CreateObject(IntPtr externalComObject, CreateObjectFla protected override void ReleaseObjects(IEnumerable objects) { + foreach (object o in objects) + { + Assert.IsNotNull(o); + } + throw new Exception() { HResult = ReleaseObjectsCallAck }; } diff --git a/src/tests/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp b/src/tests/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp index 63a013b5cb484b..cacd112eb7afb5 100644 --- a/src/tests/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp +++ b/src/tests/Interop/COM/ComWrappers/MockReferenceTrackerRuntime/ReferenceTrackerRuntime.cpp @@ -218,6 +218,11 @@ namespace } } + bool IsConnected() + { + return _connected; + } + STDMETHOD(AddObjectRef)(_In_ IUnknown* c, _Out_ int* id) { assert(c != nullptr && id != nullptr); @@ -546,6 +551,12 @@ extern "C" DLL_EXPORT int STDMETHODCALLTYPE Trigger_NotifyEndOfReferenceTracking return TrackerRuntimeManager.NotifyEndOfReferenceTrackingOnThread(); } +extern "C" DLL_EXPORT bool STDMETHODCALLTYPE IsTrackerObjectConnected(IUnknown* inst) +{ + auto trackerObject = reinterpret_cast(inst); + return trackerObject->IsConnected(); +} + extern "C" DLL_EXPORT void* STDMETHODCALLTYPE TrackerTarget_AddRefFromReferenceTrackerAndReturn(IUnknown *obj) { assert(obj != nullptr); diff --git a/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp b/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp index 89a0b996f88eab..1b521366f21e70 100644 --- a/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp +++ b/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp @@ -167,8 +167,122 @@ namespace return UnknownImpl::DoRelease(); } }; + + struct WeakReferenceSource : public IWeakReferenceSource, public IInspectable + { + private: + IUnknown* _outerUnknown; + ComSmartPtr _weakReference; + public: + WeakReferenceSource(IUnknown* outerUnknown) + :_outerUnknown(outerUnknown), + _weakReference(new WeakReference(this, 1)) + { + } + + STDMETHOD(GetWeakReference)(IWeakReference** ppWeakReference) + { + _weakReference->AddRef(); + *ppWeakReference = _weakReference; + return S_OK; + } + + STDMETHOD(QueryInterface)( + /* [in] */ REFIID riid, + /* [iid_is][out] */ void ** ppvObject) + { + if (riid == __uuidof(IWeakReferenceSource)) + { + *ppvObject = static_cast(this); + _weakReference->AddStrongRef(); + return S_OK; + } + return _outerUnknown->QueryInterface(riid, ppvObject); + } + STDMETHOD_(ULONG, AddRef)(void) + { + return _weakReference->AddStrongRef(); + } + STDMETHOD_(ULONG, Release)(void) + { + return _weakReference->ReleaseStrongRef(); + } + + STDMETHOD(GetRuntimeClassName)(HSTRING* pRuntimeClassName) + { + return E_NOTIMPL; + } + + STDMETHOD(GetIids)( + ULONG *iidCount, + IID **iids) + { + return E_NOTIMPL; + } + + STDMETHOD(GetTrustLevel)(TrustLevel *trustLevel) + { + *trustLevel = FullTrust; + return S_OK; + } + }; + + struct AggregatedWeakReferenceSource : IInspectable + { + private: + IUnknown* _outerUnknown; + ComSmartPtr _weakReference; + public: + AggregatedWeakReferenceSource(IUnknown* outerUnknown) + :_outerUnknown(outerUnknown), + _weakReference(new WeakReferenceSource(outerUnknown)) + { + } + + STDMETHOD(GetRuntimeClassName)(HSTRING* pRuntimeClassName) + { + return E_NOTIMPL; + } + + STDMETHOD(GetIids)( + ULONG *iidCount, + IID **iids) + { + return E_NOTIMPL; + } + + STDMETHOD(GetTrustLevel)(TrustLevel *trustLevel) + { + *trustLevel = FullTrust; + return S_OK; + } + + STDMETHOD(QueryInterface)( + /* [in] */ REFIID riid, + /* [iid_is][out] */ void ** ppvObject) + { + if (riid == __uuidof(IWeakReferenceSource)) + { + return _weakReference->QueryInterface(riid, ppvObject); + } + return _outerUnknown->QueryInterface(riid, ppvObject); + } + STDMETHOD_(ULONG, AddRef)(void) + { + return _outerUnknown->AddRef(); + } + STDMETHOD_(ULONG, Release)(void) + { + return _outerUnknown->Release(); + } + }; } extern "C" DLL_EXPORT WeakReferencableObject* STDMETHODCALLTYPE CreateWeakReferencableObject() { return new WeakReferencableObject(); } + +extern "C" DLL_EXPORT AggregatedWeakReferenceSource* STDMETHODCALLTYPE CreateAggregatedWeakReferenceObject(IUnknown* pOuter) +{ + return new AggregatedWeakReferenceSource(pOuter); +} diff --git a/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs b/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs index 38e40d129243f6..1d2ebe821ace3d 100644 --- a/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs +++ b/src/tests/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs @@ -14,6 +14,9 @@ static class WeakReferenceNative { [DllImport(nameof(WeakReferenceNative))] public static extern IntPtr CreateWeakReferencableObject(); + + [DllImport(nameof(WeakReferenceNative))] + public static extern IntPtr CreateAggregatedWeakReferenceObject(IntPtr outer); } public struct VtblPtr @@ -28,71 +31,96 @@ public enum WrapperRegistration Marshalling, } - public class WeakReferenceableWrapper + public unsafe class WeakReferenceableWrapper { private struct Vtbl { - public IntPtr QueryInterface; - public _AddRef AddRef; - public _Release Release; + public delegate* unmanaged QueryInterface; + public delegate* unmanaged AddRef; + public delegate* unmanaged Release; } - private delegate int _AddRef(IntPtr This); - private delegate int _Release(IntPtr This); - private readonly IntPtr instance; private readonly Vtbl vtable; + private readonly bool releaseInFinalizer; public WrapperRegistration Registration { get; } - public WeakReferenceableWrapper(IntPtr instance, WrapperRegistration reg) + public WeakReferenceableWrapper(IntPtr instance, WrapperRegistration reg, bool releaseInFinalizer = true) { var inst = Marshal.PtrToStructure(instance); this.vtable = Marshal.PtrToStructure(inst.Vtbl); this.instance = instance; + this.releaseInFinalizer = releaseInFinalizer; Registration = reg; } + public int QueryInterface(Guid iid, out IntPtr ptr) + { + fixed(IntPtr* ppv = &ptr) + { + return this.vtable.QueryInterface(this.instance, &iid, ppv); + } + } + ~WeakReferenceableWrapper() { - if (this.instance != IntPtr.Zero) + if (this.instance != IntPtr.Zero && this.releaseInFinalizer) { this.vtable.Release(this.instance); } } } - class Program + class DerivedObject : ICustomQueryInterface { - class TestComWrappers : ComWrappers + private WeakReferenceableWrapper inner; + public DerivedObject(TestComWrappers comWrappersInstance) { - public WrapperRegistration Registration { get; } + IntPtr innerInstance = WeakReferenceNative.CreateAggregatedWeakReferenceObject( + comWrappersInstance.GetOrCreateComInterfaceForObject(this, CreateComInterfaceFlags.None)); + inner = new WeakReferenceableWrapper(innerInstance, comWrappersInstance.Registration, releaseInFinalizer: false); + comWrappersInstance.GetOrRegisterObjectForComInstance(innerInstance, CreateObjectFlags.Aggregation, this); + } - public TestComWrappers(WrapperRegistration reg = WrapperRegistration.Local) - { - Registration = reg; - } + public CustomQueryInterfaceResult GetInterface(ref Guid iid, out IntPtr ppv) + { + return inner.QueryInterface(iid, out ppv) == 0 ? CustomQueryInterfaceResult.Handled : CustomQueryInterfaceResult.Failed; + } + } - protected unsafe override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) - { - count = 0; - return null; - } + class TestComWrappers : ComWrappers + { + public WrapperRegistration Registration { get; } - protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flag) - { - Marshal.AddRef(externalComObject); - return new WeakReferenceableWrapper(externalComObject, Registration); - } + public TestComWrappers(WrapperRegistration reg = WrapperRegistration.Local) + { + Registration = reg; + } - protected override void ReleaseObjects(IEnumerable objects) - { - } + protected unsafe override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + count = 0; + return null; + } + + protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flag) + { + Marshal.AddRef(externalComObject); + return new WeakReferenceableWrapper(externalComObject, Registration); + } - public static readonly TestComWrappers TrackerSupportInstance = new TestComWrappers(WrapperRegistration.TrackerSupport); - public static readonly TestComWrappers MarshallingInstance = new TestComWrappers(WrapperRegistration.Marshalling); + protected override void ReleaseObjects(IEnumerable objects) + { } + public static readonly TestComWrappers TrackerSupportInstance = new TestComWrappers(WrapperRegistration.TrackerSupport); + public static readonly TestComWrappers MarshallingInstance = new TestComWrappers(WrapperRegistration.Marshalling); + } + + class Program + { + private static void ValidateWeakReferenceState(WeakReference wr, bool expectedIsAlive, TestComWrappers sourceWrappers = null) { WeakReferenceableWrapper target; @@ -135,7 +163,7 @@ private static void ValidateNativeWeakReference(TestComWrappers cw) // a global ComWrappers instance. If the RCW was created throug a local ComWrappers instance, the weak // reference should be dead and stay dead once the RCW is collected. bool supportsRehydration = cw.Registration != WrapperRegistration.Local; - + Console.WriteLine($" -- Validate RCW recreation"); ValidateWeakReferenceState(weakRef, expectedIsAlive: supportsRehydration, cw); @@ -221,6 +249,26 @@ bool HasTarget(WeakReference wr) Assert.IsNull(weakRef.Target); } + static void ValidateAggregatedWeakReference() + { + Console.WriteLine("Validate weak reference with aggregation."); + var (handle, weakRef) = GetWeakReference(); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + + Assert.IsNull(handle.Target); + Assert.IsFalse(weakRef.TryGetTarget(out _)); + + static (GCHandle handle, WeakReference) GetWeakReference() + { + DerivedObject obj = new DerivedObject(TestComWrappers.TrackerSupportInstance); + // We use an explicit weak GC handle here to enable us to validate that we are using "weak" GCHandle + // semantics with the weak reference. + return (GCHandle.Alloc(obj, GCHandleType.Weak), new WeakReference(obj)); + } + } + static int Main(string[] doNotUse) { try @@ -235,6 +283,7 @@ static int Main(string[] doNotUse) ComWrappers.RegisterForTrackerSupport(TestComWrappers.TrackerSupportInstance); ValidateGlobalInstanceTrackerSupport(); + ValidateAggregatedWeakReference(); ValidateLocalInstance(); } diff --git a/src/tests/Interop/IDynamicInterfaceCastable/Program.cs b/src/tests/Interop/IDynamicInterfaceCastable/Program.cs index 00e9863d451493..73febecafdb7ed 100644 --- a/src/tests/Interop/IDynamicInterfaceCastable/Program.cs +++ b/src/tests/Interop/IDynamicInterfaceCastable/Program.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using TestLibrary; @@ -26,9 +27,9 @@ public interface ITest int CallImplemented(ImplementationToCall toCall); } - public interface ITestGeneric + public interface ITestGeneric { - T ReturnArg(T t); + U ReturnArg(T t); } public interface IDirectlyImplemented @@ -115,18 +116,24 @@ Type ITest.GetMyType() } [DynamicInterfaceCastableImplementation] - public interface ITestGenericImpl: ITestGeneric + public interface ITestGenericImpl: ITestGeneric { - T ITestGeneric.ReturnArg(T t) + U ITestGeneric.ReturnArg(T t) { - return t; + if (!typeof(T).IsAssignableTo(typeof(U)) + && !t.GetType().IsAssignableTo(typeof(U))) + { + throw new Exception($"Invalid covariance conversion from {typeof(T)} or {t.GetType()} to {typeof(U)}"); + } + + return Unsafe.As(ref t); } } [DynamicInterfaceCastableImplementation] - public interface ITestGenericIntImpl: ITestGeneric + public interface ITestGenericIntImpl: ITestGeneric { - int ITestGeneric.ReturnArg(int i) + int ITestGeneric.ReturnArg(int i) { return i; } @@ -312,27 +319,34 @@ private static void ValidateGenericInterface() Console.WriteLine($"Running {nameof(ValidateGenericInterface)}"); object castableObj = new DynamicInterfaceCastable(new Dictionary { - { typeof(ITestGeneric), typeof(ITestGenericIntImpl) }, - { typeof(ITestGeneric), typeof(ITestGenericImpl) }, + { typeof(ITestGeneric), typeof(ITestGenericIntImpl) }, + { typeof(ITestGeneric), typeof(ITestGenericImpl) }, + { typeof(ITestGeneric), typeof(ITestGenericImpl) }, }); Console.WriteLine(" -- Validate cast"); - // ITestGeneric -> ITestGenericIntImpl - Assert.IsTrue(castableObj is ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via is"); - Assert.IsNotNull(castableObj as ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via as"); - ITestGeneric testInt = (ITestGeneric)castableObj; + // ITestGeneric -> ITestGenericIntImpl + Assert.IsTrue(castableObj is ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via is"); + Assert.IsNotNull(castableObj as ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via as"); + ITestGeneric testInt = (ITestGeneric)castableObj; + + // ITestGeneric -> ITestGenericImpl + Assert.IsTrue(castableObj is ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via is"); + Assert.IsNotNull(castableObj as ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via as"); + ITestGeneric testStr = (ITestGeneric)castableObj; - // ITestGeneric -> ITestGenericImpl - Assert.IsTrue(castableObj is ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via is"); - Assert.IsNotNull(castableObj as ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via as"); - ITestGeneric testStr = (ITestGeneric)castableObj; + // Validate Variance + // ITestGeneric -> ITestGenericImpl + Assert.IsTrue(castableObj is ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via is"); + Assert.IsNotNull(castableObj as ITestGeneric, $"Should be castable to {nameof(ITestGeneric)} via as"); + ITestGeneric testVar = (ITestGeneric)castableObj; - // ITestGeneric is not recognized - Assert.IsFalse(castableObj is ITestGeneric, $"Should not be castable to {nameof(ITestGeneric)} via is"); - Assert.IsNull(castableObj as ITestGeneric, $"Should not be castable to {nameof(ITestGeneric)} via as"); - var ex = Assert.Throws(() => { var _ = (ITestGeneric)castableObj; }); - Assert.AreEqual(string.Format(DynamicInterfaceCastableException.ErrorFormat, typeof(ITestGeneric)), ex.Message); + // ITestGeneric is not recognized + Assert.IsFalse(castableObj is ITestGeneric, $"Should not be castable to {nameof(ITestGeneric)} via is"); + Assert.IsNull(castableObj as ITestGeneric, $"Should not be castable to {nameof(ITestGeneric)} via as"); + var ex = Assert.Throws(() => { var _ = (ITestGeneric)castableObj; }); + Assert.AreEqual(string.Format(DynamicInterfaceCastableException.ErrorFormat, typeof(ITestGeneric)), ex.Message); int expectedInt = 42; string expectedStr = "str"; @@ -340,12 +354,15 @@ private static void ValidateGenericInterface() Console.WriteLine(" -- Validate method call"); Assert.AreEqual(expectedInt, testInt.ReturnArg(42)); Assert.AreEqual(expectedStr, testStr.ReturnArg(expectedStr)); + Assert.AreEqual(expectedStr, testVar.ReturnArg(expectedStr)); Console.WriteLine(" -- Validate delegate call"); Func funcInt = new Func(testInt.ReturnArg); Assert.AreEqual(expectedInt, funcInt(expectedInt)); Func funcStr = new Func(testStr.ReturnArg); Assert.AreEqual(expectedStr, funcStr(expectedStr)); + Func funcVar = new Func(testVar.ReturnArg); + Assert.AreEqual(expectedStr, funcVar(expectedStr)); } private static void ValidateOverriddenInterface() diff --git a/src/tests/Interop/IJW/IJW.cmake b/src/tests/Interop/IJW/IJW.cmake index 1ba007427185c2..0e94553450b0d3 100644 --- a/src/tests/Interop/IJW/IJW.cmake +++ b/src/tests/Interop/IJW/IJW.cmake @@ -32,7 +32,7 @@ if (CLR_CMAKE_HOST_WIN32) string(REPLACE "/GR-" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") endif() - set(CLR_SDK_REF_PACK "") + set(CLR_SDK_REF_PACK_OUTPUT "") set(CLR_SDK_REF_PACK_DISCOVERY_ERROR "") set(CLR_SDK_REF_PACK_DISCOVERY_RESULT 0) @@ -40,14 +40,14 @@ if (CLR_CMAKE_HOST_WIN32) message("Using live-built ref assemblies for C++/CLI runtime tests.") execute_process( COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_LIST_DIR}/getRefPackFolderFromArtifacts.ps1" - OUTPUT_VARIABLE CLR_SDK_REF_PACK + OUTPUT_VARIABLE CLR_SDK_REF_PACK_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_ERROR RESULT_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_RESULT) else() execute_process( COMMAND powershell -ExecutionPolicy ByPass -NoProfile "${CMAKE_CURRENT_LIST_DIR}/getRefPackFolderFromSdk.ps1" - OUTPUT_VARIABLE CLR_SDK_REF_PACK + OUTPUT_VARIABLE CLR_SDK_REF_PACK_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_ERROR RESULT_VARIABLE CLR_SDK_REF_PACK_DISCOVERY_RESULT) @@ -57,6 +57,8 @@ if (CLR_CMAKE_HOST_WIN32) message(FATAL_ERROR "Unable to find reference assemblies: ${CLR_SDK_REF_PACK_DISCOVERY_ERROR}") endif() + string(REGEX REPLACE ".*refPackPath=(.*)" "\\1" CLR_SDK_REF_PACK ${CLR_SDK_REF_PACK_OUTPUT}) + add_compile_options(/AI${CLR_SDK_REF_PACK}) list(APPEND LINK_LIBRARIES_ADDITIONAL ijwhost) diff --git a/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 b/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 index aaf5e93661ae3a..98242949f440b4 100644 --- a/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 +++ b/src/tests/Interop/IJW/getRefPackFolderFromArtifacts.ps1 @@ -18,4 +18,4 @@ if (-not (Test-Path $refPackPath)) return 1 } -Write-Output $refPackPath +Write-Output "refPackPath=$refPackPath" diff --git a/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 b/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 index bb2404d27a6265..0b94bca5e10721 100644 --- a/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 +++ b/src/tests/Interop/IJW/getRefPackFolderFromSdk.ps1 @@ -25,4 +25,4 @@ if (-not (Test-Path $refPackPath)) return 1 } -Write-Output $refPackPath +Write-Output "refPackPath=$refPackPath" diff --git a/src/tests/JIT/Directed/debugging/poison.cs b/src/tests/JIT/Directed/debugging/poison.cs index 463894a4e6a35d..81c669a8037282 100644 --- a/src/tests/JIT/Directed/debugging/poison.cs +++ b/src/tests/JIT/Directed/debugging/poison.cs @@ -19,6 +19,24 @@ public static unsafe int Main() WithoutGCRef poisoned2; Unsafe.SkipInit(out poisoned2); result &= VerifyPoison(&poisoned2, sizeof(WithoutGCRef)); + + Massive notPoisoned; + Unsafe.SkipInit(out notPoisoned); + // too large to be poisoned, just expose it but don't check return value + VerifyPoison(¬Poisoned, sizeof(Massive)); + + WithoutGCRef poisoned4; + Unsafe.SkipInit(out poisoned4); + result &= VerifyPoison(&poisoned4, sizeof(WithoutGCRef)); + + Massive notPoisoned2; + Unsafe.SkipInit(out notPoisoned2); + // too large to be poisoned, just expose it but don't check return value + VerifyPoison(¬Poisoned2, sizeof(Massive)); + + GCRef zeroed2; + Unsafe.SkipInit(out zeroed2); + result &= VerifyZero(Unsafe.AsPointer(ref zeroed2), Unsafe.SizeOf()); return result ? 100 : 101; } @@ -53,4 +71,9 @@ private struct WithoutGCRef public int ANumber; public float AFloat; } -} + + private unsafe struct Massive + { + public fixed byte Bytes[0x10008]; + } +} \ No newline at end of file diff --git a/src/tests/JIT/Directed/nullabletypes/gettype.cs b/src/tests/JIT/Directed/nullabletypes/gettype.cs new file mode 100644 index 00000000000000..15bbef729d26f9 --- /dev/null +++ b/src/tests/JIT/Directed/nullabletypes/gettype.cs @@ -0,0 +1,48 @@ +// 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.Linq; +using System.Collections.Generic; + +class C +{ + public IEnumerable Data { get; set; } + + public C() { } + + public bool Check() + { + return Data.ElementAt(0).GetType() == typeof(bool); + } +} + +public class P +{ + public static int Main() + { + C c = new(); + + // Try a nullable with value + c.Data = new List { true }; + if(!c.Check()) + return 666; + + // Try a nullable without value. Should throw NRE + c.Data = new List { new Nullable() }; + + bool thrown = false; + try + { + c.Check(); + } + catch(NullReferenceException) + { + thrown = true; + } + if(!thrown) + return 667; + return 100; + } +} + diff --git a/src/tests/JIT/Directed/nullabletypes/gettype_d.csproj b/src/tests/JIT/Directed/nullabletypes/gettype_d.csproj new file mode 100644 index 00000000000000..749b1f23c89758 --- /dev/null +++ b/src/tests/JIT/Directed/nullabletypes/gettype_d.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + Full + False + + + + + diff --git a/src/tests/JIT/Directed/nullabletypes/gettype_do.csproj b/src/tests/JIT/Directed/nullabletypes/gettype_do.csproj new file mode 100644 index 00000000000000..34744812c89277 --- /dev/null +++ b/src/tests/JIT/Directed/nullabletypes/gettype_do.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + Full + True + + + + + diff --git a/src/tests/JIT/Directed/nullabletypes/gettype_r.csproj b/src/tests/JIT/Directed/nullabletypes/gettype_r.csproj new file mode 100644 index 00000000000000..fea75d031b0ed3 --- /dev/null +++ b/src/tests/JIT/Directed/nullabletypes/gettype_r.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + None + False + + + + + diff --git a/src/tests/JIT/Directed/nullabletypes/gettype_ro.csproj b/src/tests/JIT/Directed/nullabletypes/gettype_ro.csproj new file mode 100644 index 00000000000000..f51b4298ce4d6e --- /dev/null +++ b/src/tests/JIT/Directed/nullabletypes/gettype_ro.csproj @@ -0,0 +1,13 @@ + + + Exe + 1 + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_54102/Runtime_54102.cs b/src/tests/JIT/Regression/JitBlue/Runtime_54102/Runtime_54102.cs new file mode 100644 index 00000000000000..8afef4323c2fbd --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_54102/Runtime_54102.cs @@ -0,0 +1,52 @@ +// 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.Runtime.CompilerServices; + +// Generated by Fuzzlyn v1.1 on 2021-06-12 11:06:35 +// Seed: 8276490119048877745 +// Reduced from 962.5 KiB to 0.6 KiB in 00:05:32 +// Debug: Outputs 0 +// Release: Outputs 1 + +struct S0 +{ + public ushort F1; + public uint F2; + public byte F3; + public int F5; + public S0(byte f3): this() + { + F3 = f3; + } +} + +struct S1 +{ + public S0 F0; + public S0 F4; + public S1(S0 f0): this() + { + F0 = f0; + } +} + +struct S2 +{ + public S1 F0; + public S2(S1 f0): this() + { + F0 = f0; + } +} + +public class Program +{ + public static int Main() + { + S2 vr0 = new S2(new S1(new S0(100))); + int ret = vr0.F0.F0.F3 + vr0.F0.F4.F1; + return ret; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_54102/Runtime_54102.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_54102/Runtime_54102.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_54102/Runtime_54102.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_56980/Runtime_56980.cs b/src/tests/JIT/Regression/JitBlue/Runtime_56980/Runtime_56980.cs new file mode 100644 index 00000000000000..1ff1c7611e84fc --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_56980/Runtime_56980.cs @@ -0,0 +1,61 @@ +// 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.Runtime.CompilerServices; + +// Generated by Fuzzlyn v1.2 on 2021-07-06 09:46:44 +// Seed: 16635934940619066544 +// Reduced from 447.5 KiB to 0.6 KiB in 00:02:24 +// Debug: Runs successfully +// Release: Throws 'System.NullReferenceException' +struct S0 +{ + public uint F1; + public byte F3; + public long F4; + public uint F5; + public S0(long f4): this() + { + F4 = f4; + } +} + +class C0 +{ + public S0 F4; +} + +struct S1 +{ + public C0 F2; + public S0 F8; + public S1(C0 f2, S0 f8): this() + { + F2 = f2; + F8 = f8; + } +} + +struct S2 +{ + public S1 F0; + public S2(S1 f0): this() + { + F0 = f0; + } +} + +public class Program +{ + public static int Main() + { + S2 vr0 = new S2(new S1(new C0(), new S0(0))); + M17(ref vr0.F0.F2.F4.F1); + return 100; + } + + static void M17(ref uint arg2) + { + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_56980/Runtime_56980.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_56980/Runtime_56980.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_56980/Runtime_56980.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_1.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_1.cs new file mode 100644 index 00000000000000..9a13f069e29069 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_1.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. + +// Generated by Fuzzlyn v1.2 on 2021-08-16 12:59:38 +// Run on .NET 6.0.0-dev on X64 Windows +// Seed: 9053537220764489964 +// Reduced from 104.8 KiB to 0.8 KiB in 00:00:44 +// Debug: Outputs 1, 0 +// Release: Outputs 1, 1 +struct S0 +{ + public short F1; + public ushort F4; + public S0(short f1) : this() + { + F1 = f1; + } +} + +struct S1 +{ + public S0 F0; + public S1(S0 f0) : this() + { + F0 = f0; + } +} + +struct S2 +{ + public S1 F1; + public S0 F2; + public S2(S1 f1) : this() + { + F1 = f1; + } +} + +struct S3 +{ + public S2 F0; + public S3(S2 f0) : this() + { + F0 = f0; + } +} + +struct S4 +{ + public sbyte F4; + public S3 F5; + public S4(S3 f5) : this() + { + F5 = f5; + } +} + +public class Program +{ + public static int Test() + { + S4 vr0 = new S4(new S3(new S2(new S1(new S0(1))))); + System.Console.WriteLine(vr0.F5.F0.F1.F0.F1); + System.Console.WriteLine(vr0.F5.F0.F1.F0.F4); + return vr0.F5.F0.F1.F0.F1 + vr0.F5.F0.F1.F0.F4; + } + + public static int Main() + { + if (Test() == 1) + { + return 100; + } + return 101; + + } + +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_1.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_1.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_1.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_2.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_2.cs new file mode 100644 index 00000000000000..fc78551f5c6779 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_2.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v1.2 on 2021-08-16 12:56:37 +// Run on .NET 6.0.0-dev on X64 Windows +// Seed: 10782465293682251646 +// Reduced from 129.7 KiB to 0.8 KiB in 00:01:40 +// Debug: Outputs 0 +// Release: Outputs 1 +struct S0 +{ + public short F0; + public short F1; + public int F2; + public short F3; + public short F4; + public S0(short f4) : this() + { + F4 = f4; + } +} + +struct S1 +{ + public S0 F0; + public int F3; + public S1(S0 f0) : this() + { + F0 = f0; + } +} + +struct S3 +{ + public S1 F0; + public S3(S1 f0) : this() + { + F0 = f0; + } +} + +struct S4 +{ + public ushort F3; + public S3 F4; + public S4(S3 f4) : this() + { + F4 = f4; + } +} + +public class Program +{ + static S0[] s_9 = new S0[] { new S0(0) }; + + public static int Test() + { + S0 vr4 = default(S0); + S4 vr5 = new S4(new S3(new S1(new S0(1)))); + s_9[0].F4 = vr5.F4.F0.F0.F4; + System.Console.WriteLine(vr4.F1); + return vr4.F1; + } + + public static int Main() + { + if (Test() == 0) + { + return 100; + } + return 101; + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_2.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_2.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57282/Runtime_57282_2.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535.cs new file mode 100644 index 00000000000000..1af66647dff377 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.CompilerServices; + +class Runtime_57535 +{ + static long z; + + public static int Main() + { + z = 10; + int[] a = F(); + long zz = z; + int result = 0; + for (int i = 0; i < (int) zz; i++) + { + result += a[i]; + } + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int[] F() + { + int[] result = new int[100]; + result[3] = 100; + return result; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535_1.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535_1.cs new file mode 100644 index 00000000000000..83040ad93efcaf --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535_1.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.CompilerServices; + +class Runtime_57535_1 +{ + static long z; + + public static int Main() + { + z = 2; + int[] a = F(); + long zz = z; + int result = 0; + for (int i = (int) zz; i < a.Length; i++) + { + result += a[i]; + } + Bar(zz); + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int[] F() + { + int[] result = new int[100]; + result[3] = 100; + return result; + } + + static void Bar(long z) {} +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535_1.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535_1.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57535/Runtime_57535_1.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57640/Runtime_57640.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57640/Runtime_57640.cs new file mode 100644 index 00000000000000..906780463e8a2f --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57640/Runtime_57640.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Generated by Fuzzlyn v1.2 on 2021-08-15 23:15:19 +// Run on .NET 6.0.0-dev on Arm Linux +// Seed: 18219619158927602726 +// Reduced from 82.6 KiB to 0.3 KiB in 00:02:54 +// Debug: Outputs 14270 +// Release: Outputs 4294953026 +public class Runtime_57640 +{ + static long[] s_28 = new long[]{1}; + public static int Main() + { + bool correct = true; + var vr10 = s_28[0]; + for (int vr13 = 0; vr13 < 2; vr13++) + { + uint vr12 = (uint)(0 - (-14270 * vr10)); + correct &= vr12 == 14270; + } + + return correct ? 100 : -1; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57640/Runtime_57640.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57640/Runtime_57640.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57640/Runtime_57640.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57912/Runtime_57912.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57912/Runtime_57912.cs new file mode 100644 index 00000000000000..620b598306619f --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57912/Runtime_57912.cs @@ -0,0 +1,43 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[StructLayout(LayoutKind.Sequential)] +internal struct AA +{ + public short tmp1; + public short q; + + public ushort tmp2; + public int tmp3; + + public AA(short qq) + { + tmp1 = 106; + tmp2 = 107; + tmp3 = 108; + q = qq; + } + + // The test verifies that we accurately update the byref variable that is a field of struct. + public static short call_target_ref(ref short arg) { arg = 100; return arg; } +} + + +public class Runtime_57912 +{ + + public static int Main() + { + return (int)test_0_17(100, new AA(100), new AA(0)); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short test_0_17(int num, AA init, AA zero) + { + return AA.call_target_ref(ref init.q); + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57912/Runtime_57912.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57912/Runtime_57912.csproj new file mode 100644 index 00000000000000..edc51be9ca25b2 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57912/Runtime_57912.csproj @@ -0,0 +1,10 @@ + + + Exe + True + None + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57914/Runtime_57914.cs b/src/tests/JIT/Regression/JitBlue/Runtime_57914/Runtime_57914.cs new file mode 100644 index 00000000000000..f11dc7d8302077 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57914/Runtime_57914.cs @@ -0,0 +1,50 @@ +// 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.Runtime.CompilerServices; + +public class Program +{ + public static int Main() + { + return (Test1() && Test2()) ? 100 : 101; + } + + private static bool Test1() + { + byte[] array = new byte[2]; + array[0] = 1; + array[1] = 2; + + // a1, a2 and a3 all have different values here + byte a1 = Unsafe.ReadUnaligned(ref array[0]); + short a2 = Unsafe.ReadUnaligned(ref array[0]); + array[1] = 42; + short a3 = Unsafe.ReadUnaligned(ref array[0]); + + return a1 != a2 && a1 != a3 && a2 != a3; + } + + private static bool Test2() + { + bool result = true; + byte[] buffer = new byte[4]; + buffer[0] = 0x1; + buffer[1] = 0x2; + buffer[2] = 0x3; + buffer[3] = 0x4; + + if (buffer.Length > 0) + { + int n = Unsafe.ReadUnaligned(ref buffer[0]); + if (n != 0x4030201) + result = false; + Consume(n); + } + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static void Consume(int n) {} +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_57914/Runtime_57914.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_57914/Runtime_57914.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_57914/Runtime_57914.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58259/Runtime_58259.cs b/src/tests/JIT/Regression/JitBlue/Runtime_58259/Runtime_58259.cs new file mode 100644 index 00000000000000..7e49a3c9208310 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58259/Runtime_58259.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +public unsafe class Runtime_58259 +{ + public static int Main() + { + M(out _); + return 100; + } + + static delegate* unmanaged _f; + + public static void M(out int index) + { + if (_f != null) + { + _f(out index); + _f(out index); + } + else + { + index = 0; + } + } +} + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58259/Runtime_58259.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_58259/Runtime_58259.csproj new file mode 100644 index 00000000000000..d1dc80557b728c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58259/Runtime_58259.csproj @@ -0,0 +1,14 @@ + + + Exe + True + 1 + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_1.cs b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_1.cs new file mode 100644 index 00000000000000..76a46072e556d2 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_1.cs @@ -0,0 +1,29 @@ +// 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.Runtime.CompilerServices; + +public unsafe class Runtime_58373 +{ + public static int Main() + { + short halfValue = HalfToInt16Bits(MakeHalf()); + int x = halfValue; + short val2 = HalfToInt16Bits(*(Half*)&x); + + return halfValue == val2 ? 100 : -1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Half MakeHalf() + { + return (Half)(-1.0f); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short HalfToInt16Bits(Half h) + { + return *(short*)&h; + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_1.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_1.csproj new file mode 100644 index 00000000000000..1a1d3eadae5ce4 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_1.csproj @@ -0,0 +1,13 @@ + + + Exe + + + None + True + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_2.cs b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_2.cs new file mode 100644 index 00000000000000..c8d1286c1ba7b2 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_2.cs @@ -0,0 +1,47 @@ +// 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.Runtime.CompilerServices; + +public unsafe class Runtime_58373 +{ + public static int Main() + { + // Use up a lot of registers + int a = GetVal(); + int b = GetVal(); + int c = GetVal(); + int d = GetVal(); + int e = GetVal(); + int f = GetVal(); + int g = GetVal(); + int h = GetVal(); + int i = GetVal(); + + short val1 = HalfToInt16Bits(MakeHalf()); + Half half = MakeHalf(); + MakeHalf(); // This will spill lower 16 bits of 'half' to memory + short val2 = HalfToInt16Bits(half); // This will pass 32 bits as arg with upper 16 bits undefined + + return val1 == val2 ? 100 + a + b + c + d + e + f + g + h + i : -1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static int GetVal() + { + return 0; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static Half MakeHalf() + { + return default; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short HalfToInt16Bits(Half h) + { + return *(short*)&h; + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_2.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_2.csproj new file mode 100644 index 00000000000000..1a1d3eadae5ce4 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58373/Runtime_58373_2.csproj @@ -0,0 +1,13 @@ + + + Exe + + + None + True + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58832/Runtime_58832.cs b/src/tests/JIT/Regression/JitBlue/Runtime_58832/Runtime_58832.cs new file mode 100644 index 00000000000000..9acd698ca4c13c --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58832/Runtime_58832.cs @@ -0,0 +1,30 @@ +// 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.Runtime.CompilerServices; + +public class Runtime_58832 +{ + public static int Main() + { + try + { + Test(double.MaxValue); + } + catch (OverflowException) + { + return 100; + } + return 101; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void Test(double x) + { + try { Console.WriteLine(checked((ulong)x)); } catch { } + + if ((ulong)x == checked((ulong)x)) + Console.WriteLine("Should not be invoked"); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58832/Runtime_58832.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_58832/Runtime_58832.csproj new file mode 100644 index 00000000000000..1100f420532dc8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58832/Runtime_58832.csproj @@ -0,0 +1,10 @@ + + + Exe + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58972/Runtime_58972.cs b/src/tests/JIT/Regression/JitBlue/Runtime_58972/Runtime_58972.cs new file mode 100644 index 00000000000000..b63c1d907f14c1 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58972/Runtime_58972.cs @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public class Runtime_58972 +{ + public static int Main() + { + GetItem(new MyStruct[1], 0); + return 100; + } + + // This code results in a struct returned in register where we replace the local + // of type MyStruct by its only field, and where that field cannot be enregistered. + // We would potentially miss normalization if the struct was returned as an integer + // type and hit a defensive assertion because of it. + static MyStruct GetItem(MyStruct[] a, int i) + { + try + { + return a[i]; + } + catch (IndexOutOfRangeException) + { + ThrowHelper(); + return default; + } + } + + static void ThrowHelper() => throw new Exception(); + + struct MyStruct + { + byte b; + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_58972/Runtime_58972.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_58972/Runtime_58972.csproj new file mode 100644 index 00000000000000..f3e1cbd44b4041 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_58972/Runtime_58972.csproj @@ -0,0 +1,12 @@ + + + Exe + + + None + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_61486/Runtime_61486.cs b/src/tests/JIT/Regression/JitBlue/Runtime_61486/Runtime_61486.cs new file mode 100644 index 00000000000000..3285ee9cc556a9 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_61486/Runtime_61486.cs @@ -0,0 +1,45 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; + +public class Runtime_61486 +{ + public static int Main() + { + var my = new My(new My(null)); + var m = my.GetType().GetMethod("M"); + try + { + m.Invoke(my, null); + return -1; + } + catch (TargetInvocationException ex) when (ex.InnerException is NullReferenceException) + { + return 100; + } + } + + public interface IFace + { + void M(); + } + + public class My : IFace + { + private IFace _face; + + public My(IFace face) + { + _face = face; + } + + // We cannot handle a null ref inside a VSD if the caller is not + // managed frame. This test is verifying that JIT null checks ahead of + // time in this case. + [MethodImpl(MethodImplOptions.AggressiveOptimization)] + public void M() => _face.M(); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_61486/Runtime_61486.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_61486/Runtime_61486.csproj new file mode 100644 index 00000000000000..6946bed81bfd5b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_61486/Runtime_61486.csproj @@ -0,0 +1,9 @@ + + + Exe + True + + + + + diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62597/Runtime_62597.cs b/src/tests/JIT/Regression/JitBlue/Runtime_62597/Runtime_62597.cs new file mode 100644 index 00000000000000..fb3ccef4ade51b --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_62597/Runtime_62597.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// Note: In below test case, we were not honoring the fact that the explicit struct size +// of struct is 32 bytes while the only 2 fields it has is just 2 bytes. In such case, +// we would pass partial struct value. +using System; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +[StructLayout(LayoutKind.Explicit, Size = 32)] +public readonly unsafe struct SmallString +{ + [FieldOffset(0)] private readonly byte _length; + [FieldOffset(1)] private readonly byte _firstByte; + + public SmallString(string value) + { + fixed (char* srcPtr = value) + fixed (byte* destPtr = &_firstByte) + { + Encoding.ASCII.GetBytes(srcPtr, value.Length, destPtr, value.Length); + } + + _length = (byte)value.Length; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public byte Dump() + { + fixed (byte* ptr = &_firstByte) + { + byte* next = ptr + 1; + return *next; + } + } +} + +public static class Program +{ + static int result = 0; + public static int Main() + { + var value = new SmallString("foobar"); + + TheTest(value); + + return result; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void TheTest(SmallString foo) + { + Execute(foo); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static object Execute(SmallString foo) + { + byte value = foo.Dump(); + // 111 corresponds to the ASCII code of 2nd characted of string "foobar" i.e. ASCII value of 'o'. + if (value == 111) + { + result = 100; + } + return new StringBuilder(); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_62597/Runtime_62597.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_62597/Runtime_62597.csproj new file mode 100644 index 00000000000000..e822a8b10a5a6f --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_62597/Runtime_62597.csproj @@ -0,0 +1,13 @@ + + + Exe + True + + + None + True + + + + + \ No newline at end of file diff --git a/src/tests/JIT/opt/Structs/structcopies.cs b/src/tests/JIT/opt/Structs/structcopies.cs index e1331e38f00614..61d8a6f424f0f1 100644 --- a/src/tests/JIT/opt/Structs/structcopies.cs +++ b/src/tests/JIT/opt/Structs/structcopies.cs @@ -36,7 +36,7 @@ struct S4W struct S4WW { - public S4W s4; + public S4W s4W; } struct S4Copy @@ -142,18 +142,18 @@ static int TestS4_WW1() { S4 s1 = new S4(); S4WW s2 = new S4WW(); - s2.s4.s4.i = 1; + s2.s4W.s4.i = 1; if (s1.i != 0) { return 101; } - s1 = s2.s4.s4; - s2.s4.s4.i = 2; + s1 = s2.s4W.s4; + s2.s4W.s4.i = 2; if (s1.i != 1) { return 101; } - if (s2.s4.s4.i != 2) + if (s2.s4W.s4.i != 2) { return 101; } @@ -166,13 +166,13 @@ static int TestS4_WW2() S4WW s1 = new S4WW(); S4 s2 = new S4(); s2.i = 1; - if (s1.s4.s4.i != 0) + if (s1.s4W.s4.i != 0) { return 101; } - s1.s4.s4 = s2; + s1.s4W.s4 = s2; s2.i = 2; - if (s1.s4.s4.i != 1) + if (s1.s4W.s4.i != 1) { return 101; } @@ -462,7 +462,7 @@ struct S8W struct S8WW { - public S8W s8; + public S8W s8W; } struct S8Copy @@ -605,8 +605,8 @@ static int TestS8_WW1() { S8 s1 = new S8(); S8WW s2 = new S8WW(); - s2.s8.s8.i1 = 1; - s2.s8.s8.i2 = 2; + s2.s8W.s8.i1 = 1; + s2.s8W.s8.i2 = 2; if (s1.i1 != 0) { return 101; @@ -615,9 +615,9 @@ static int TestS8_WW1() { return 101; } - s1 = s2.s8.s8; - s2.s8.s8.i1 = 3; - s2.s8.s8.i2 = 4; + s1 = s2.s8W.s8; + s2.s8W.s8.i1 = 3; + s2.s8W.s8.i2 = 4; if (s1.i1 != 1) { return 101; @@ -626,11 +626,11 @@ static int TestS8_WW1() { return 101; } - if (s2.s8.s8.i1 != 3) + if (s2.s8W.s8.i1 != 3) { return 101; } - if (s2.s8.s8.i2 != 4) + if (s2.s8W.s8.i2 != 4) { return 101; } @@ -644,22 +644,22 @@ static int TestS8_WW2() S8 s2 = new S8(); s2.i1 = 1; s2.i2 = 2; - if (s1.s8.s8.i1 != 0) + if (s1.s8W.s8.i1 != 0) { return 101; } - if (s1.s8.s8.i2 != 0) + if (s1.s8W.s8.i2 != 0) { return 101; } - s1.s8.s8 = s2; + s1.s8W.s8 = s2; s2.i1 = 3; s2.i2 = 4; - if (s1.s8.s8.i1 != 1) + if (s1.s8W.s8.i1 != 1) { return 101; } - if (s1.s8.s8.i2 != 2) + if (s1.s8W.s8.i2 != 2) { return 101; } @@ -989,7 +989,7 @@ struct S16W struct S16WW { - public S16W s16; + public S16W s16W; } struct S16Copy @@ -1215,10 +1215,10 @@ static int TestS16_WW1() { S16 s1 = new S16(); S16WW s2 = new S16WW(); - s2.s16.s16.i1 = 1; - s2.s16.s16.i2 = 2; - s2.s16.s16.i3 = 3; - s2.s16.s16.i4 = 4; + s2.s16W.s16.i1 = 1; + s2.s16W.s16.i2 = 2; + s2.s16W.s16.i3 = 3; + s2.s16W.s16.i4 = 4; if (s1.i1 != 0) { return 101; @@ -1235,11 +1235,11 @@ static int TestS16_WW1() { return 101; } - s1 = s2.s16.s16; - s2.s16.s16.i1 = 5; - s2.s16.s16.i2 = 6; - s2.s16.s16.i3 = 7; - s2.s16.s16.i4 = 8; + s1 = s2.s16W.s16; + s2.s16W.s16.i1 = 5; + s2.s16W.s16.i2 = 6; + s2.s16W.s16.i3 = 7; + s2.s16W.s16.i4 = 8; if (s1.i1 != 1) { @@ -1258,19 +1258,19 @@ static int TestS16_WW1() return 101; } - if (s2.s16.s16.i1 != 5) + if (s2.s16W.s16.i1 != 5) { return 101; } - if (s2.s16.s16.i2 != 6) + if (s2.s16W.s16.i2 != 6) { return 101; } - if (s2.s16.s16.i3 != 7) + if (s2.s16W.s16.i3 != 7) { return 101; } - if (s2.s16.s16.i4 != 8) + if (s2.s16W.s16.i4 != 8) { return 101; } @@ -1286,41 +1286,41 @@ static int TestS16_WW2() s2.i2 = 2; s2.i3 = 3; s2.i4 = 4; - if (s1.s16.s16.i1 != 0) + if (s1.s16W.s16.i1 != 0) { return 101; } - if (s1.s16.s16.i2 != 0) + if (s1.s16W.s16.i2 != 0) { return 101; } - if (s1.s16.s16.i3 != 0) + if (s1.s16W.s16.i3 != 0) { return 101; } - if (s1.s16.s16.i4 != 0) + if (s1.s16W.s16.i4 != 0) { return 101; } - s1.s16.s16 = s2; + s1.s16W.s16 = s2; s2.i1 = 5; s2.i2 = 6; s2.i3 = 7; s2.i4 = 8; - if (s1.s16.s16.i1 != 1) + if (s1.s16W.s16.i1 != 1) { return 101; } - if (s1.s16.s16.i2 != 2) + if (s1.s16W.s16.i2 != 2) { return 101; } - if (s1.s16.s16.i3 != 3) + if (s1.s16W.s16.i3 != 3) { return 101; } - if (s1.s16.s16.i4 != 4) + if (s1.s16W.s16.i4 != 4) { return 101; } diff --git a/src/tests/JIT/opt/Structs/structcopies.csproj b/src/tests/JIT/opt/Structs/structcopies.csproj index c85bacc9218e5c..f3e1cbd44b4041 100644 --- a/src/tests/JIT/opt/Structs/structcopies.csproj +++ b/src/tests/JIT/opt/Structs/structcopies.csproj @@ -5,8 +5,6 @@ None True - - True diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github58394.cs b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github58394.cs new file mode 100644 index 00000000000000..ee94e5422908dc --- /dev/null +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github58394.cs @@ -0,0 +1,47 @@ +// 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.Runtime.CompilerServices; + +namespace GenericDimValuetypeBug +{ + class Program + { + static int Main() + { + if (RunOne() != 17) + return 1; + if (RunTwo() != 23) + return 2; + return 100; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int RunOne() + { + return (new Foo() { x = 17 } as IFoo).NoCrash(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int RunTwo() + { + return (new Foo() { x = 23 } as IFoo).Crash(); + } + } + + interface IFoo + { + int Crash() => Bla(); + + int NoCrash() => Bla(); + + int Bla(); + } + + struct Foo: IFoo + { + public int x; + public int Bla() => x; + } +} diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github58394.csproj b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github58394.csproj new file mode 100644 index 00000000000000..aab61d4e4497b8 --- /dev/null +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github58394.csproj @@ -0,0 +1,11 @@ + + + true + Exe + BuildAndRun + 0 + + + + + diff --git a/src/tests/Regressions/coreclr/GitHub_45929/test45929.cs b/src/tests/Regressions/coreclr/GitHub_45929/test45929.cs index 72632a5b4aaf6b..ba783a498a7de7 100644 --- a/src/tests/Regressions/coreclr/GitHub_45929/test45929.cs +++ b/src/tests/Regressions/coreclr/GitHub_45929/test45929.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.Reflection; using System.Runtime.ExceptionServices; using System.Threading; @@ -46,18 +47,40 @@ public static void Run() long progress = 0; var test = new Test(); const int MaxCount = 1000000; - Parallel.For( - 0, - MaxCount, - new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, - i => + int increment = 100; + bool done = false; + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + Console.WriteLine($"{DateTime.Now} : {progress * 100D / MaxCount:000.0}% : {stopwatch.ElapsedMilliseconds}"); + + Action makeProgress = i => { - if (Interlocked.Increment(ref progress) % 10000 == 0) + if (done) return; + long newProgress = Interlocked.Increment(ref progress); + if (newProgress % increment == 0) { - Console.WriteLine($"{DateTime.Now} : {progress * 100D / MaxCount:000.0}%"); + int newIncrement = (increment * 3) / 2; + if (newIncrement > 10000) + newIncrement = 10000; + increment = newIncrement; + + Console.WriteLine($"{DateTime.Now} : {newProgress * 100D / MaxCount:000.0}% : {stopwatch.ElapsedMilliseconds}"); + if (stopwatch.ElapsedMilliseconds > 150000) + { + Console.WriteLine($"Attempting to finish early"); + done = true; + } } test.Invoke(); - }); + }; + + makeProgress(0); + + Parallel.For( + 1, + MaxCount, + new ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount }, + makeProgress); } public void Invoke() diff --git a/src/tests/Regressions/coreclr/GitHub_61104/test61104.cs b/src/tests/Regressions/coreclr/GitHub_61104/test61104.cs new file mode 100644 index 00000000000000..2e01b96bf31d52 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_61104/test61104.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var type = Type.GetType("_测试数据记录仪_Iiİı_åäö_Controller_DataLogger1_log_all_", false); +var obj = Activator.CreateInstance(type!); +Console.WriteLine(obj?.GetType().Name); + +return 100; + +public class _测试数据记录仪_Iiİı_åäö_Controller_DataLogger1_log_all_ +{ +} diff --git a/src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj b/src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj new file mode 100644 index 00000000000000..b72e9a46cf95a8 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_61104/test61104.csproj @@ -0,0 +1,17 @@ + + + + Exe + enable + enable + 1 + + + true + + + + + + + diff --git a/src/tests/Regressions/coreclr/GitHub_62058/test62058.cs b/src/tests/Regressions/coreclr/GitHub_62058/test62058.cs new file mode 100644 index 00000000000000..bffbf999e7396f --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_62058/test62058.cs @@ -0,0 +1,60 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +public class Program +{ + private interface IFoo + { + bool IsValid { get; } + } + + private class Foo : IFoo + { + public bool IsValid { get; set; } + } + + public static int Main(string[] args) + { + bool warmup = new Foo().IsValid; + CatchIgnore(() => + CatchRethrow(() => + { + IFoo[] foos = {new Foo(), null}; + foreach (var foo in foos) + { + bool check = foo.IsValid; + } + })); + + return 100; + } + + public static void CatchRethrow(Action action) + { + try + { + action.Invoke(); + } + catch (Exception e) + { + Console.Out.WriteLine("catch"); + Console.Out.Flush(); + throw new Exception("catch", e); + } + } + + public static void CatchIgnore(Action action) + { + try + { + action.Invoke(); + } + catch (Exception) + { + Console.Out.WriteLine("ignore"); + Console.Out.Flush(); + } + } +} diff --git a/src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj b/src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj new file mode 100644 index 00000000000000..0fce5a0556f40e --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_62058/test62058.csproj @@ -0,0 +1,9 @@ + + + Exe + 1 + + + + + diff --git a/src/tests/baseservices/RuntimeConfiguration/TestConfig.cs b/src/tests/baseservices/RuntimeConfiguration/TestConfig.cs new file mode 100644 index 00000000000000..383a5d08f466d3 --- /dev/null +++ b/src/tests/baseservices/RuntimeConfiguration/TestConfig.cs @@ -0,0 +1,159 @@ +// 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.IO; +using System.Linq; +using System.Text; +using System.Reflection; +using System.Runtime; + +using Xunit; + +class TestConfig +{ + const int Success = 100; + const int Fail = 101; + + [Fact] + [EnvVar("DOTNET_gcServer", "1")] + static int Verify_ServerGC_Env_Enable(string[] _) + { + return GCSettings.IsServerGC + ? Success + : Fail; + } + + [Fact] + [ConfigProperty("DOTNET_gcServer", "0")] + static int Verify_ServerGC_Env_Disable(string[] _) + { + return GCSettings.IsServerGC + ? Fail + : Success; + } + + [Fact] + [ConfigProperty("System.GC.Server", "true")] + static int Verify_ServerGC_Prop_Enable(string[] _) + { + return GCSettings.IsServerGC + ? Success + : Fail; + } + + [Fact] + [ConfigProperty("System.GC.Server", "false")] + static int Verify_ServerGC_Prop_Disable(string[] _) + { + return GCSettings.IsServerGC + ? Fail + : Success; + } + + [Fact] + [EnvVar("DOTNET_gcServer", "0")] + [ConfigProperty("System.GC.Server", "true")] + static int Verify_ServerGC_Env_Override_Prop(string[] _) + { + return GCSettings.IsServerGC + ? Fail + : Success; + } + + static int Main(string[] args) + { + if (args.Length == 0) + { + return RunTests(); + } + + MethodInfo infos = typeof(TestConfig).GetMethod(args[0], BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + if (infos is null) + { + return Fail; + } + return (int)infos.Invoke(null, new object[] { args[1..] }); + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] + class EnvVarAttribute : Attribute + { + public EnvVarAttribute(string name, string value) { Name = name; Value = value; } + public string Name { get; init; } + public string Value { get; init; } + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] + class ConfigPropertyAttribute : Attribute + { + public ConfigPropertyAttribute(string name, string value) { Name = name; Value = value; } + public string Name { get; init; } + public string Value { get; init; } + } + + static int RunTests() + { + string corerunPath = GetCorerunPath(); + MethodInfo[] infos = typeof(TestConfig).GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + foreach (var mi in infos) + { + var factMaybe = mi.GetCustomAttributes(typeof(FactAttribute)); + if (!factMaybe.Any()) + { + continue; + } + + using Process process = new(); + + StringBuilder arguments = new(); + var configProperties = mi.GetCustomAttributes(typeof(ConfigPropertyAttribute)); + + foreach (Attribute cp in configProperties) + { + ConfigPropertyAttribute configProp = (ConfigPropertyAttribute)cp; + arguments.Append($"-p {configProp.Name}={configProp.Value} "); + } + + arguments.Append($"\"{System.Reflection.Assembly.GetExecutingAssembly().Location}\" {mi.Name}"); + + process.StartInfo.FileName = corerunPath; + process.StartInfo.Arguments = arguments.ToString(); + + var envVariables = mi.GetCustomAttributes(typeof(EnvVarAttribute)); + foreach (string key in Environment.GetEnvironmentVariables().Keys) + { + process.StartInfo.EnvironmentVariables[key] = Environment.GetEnvironmentVariable(key); + } + + Console.WriteLine($"Running: {process.StartInfo.Arguments}"); + foreach (Attribute ev in envVariables) + { + EnvVarAttribute envVar = (EnvVarAttribute)ev; + process.StartInfo.EnvironmentVariables[envVar.Name] = envVar.Value; + Console.WriteLine($" set {envVar.Name}={envVar.Value}"); + } + + process.Start(); + process.WaitForExit(); + if (process.ExitCode != Success) + { + Console.WriteLine($"Failed: {mi.Name}"); + return process.ExitCode; + } + } + + return Success; + } + + static string GetCorerunPath() + { + string corerunName = "corerun"; + if (TestLibrary.Utilities.IsWindows) + { + corerunName += ".exe"; + } + return Path.Combine(Environment.GetEnvironmentVariable("CORE_ROOT"), corerunName); + } +} \ No newline at end of file diff --git a/src/tests/baseservices/RuntimeConfiguration/TestConfig.csproj b/src/tests/baseservices/RuntimeConfiguration/TestConfig.csproj new file mode 100644 index 00000000000000..efba9444477cd8 --- /dev/null +++ b/src/tests/baseservices/RuntimeConfiguration/TestConfig.csproj @@ -0,0 +1,15 @@ + + + Exe + + true + true + true + + + + + + + + \ No newline at end of file diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 85efa7cd8ae6d6..90f9fa90055d0e 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -968,27 +968,9 @@ - - https://github.com/dotnet/runtime/issues/51323 - - - https://github.com/dotnet/runtime/issues/51323 - Mono does not define out of range fp to int conversions - - https://github.com/dotnet/runtime/issues/51323 - - - https://github.com/dotnet/runtime/issues/51323 - - - https://github.com/dotnet/runtime/issues/51323 - - - https://github.com/dotnet/runtime/issues/51323 - https://github.com/dotnet/runtime/issues/48190 @@ -1005,6 +987,9 @@ Tests features specific to coreclr + + Tests features specific to coreclr + https://github.com/dotnet/runtime/issues/40394 @@ -1242,9 +1227,6 @@ needs triage - - https://github.com/dotnet/runtime/issues/51323 - needs triage diff --git a/src/tests/profiler/native/gcprofiler/gcprofiler.cpp b/src/tests/profiler/native/gcprofiler/gcprofiler.cpp index 42666a2d8eac82..ed6312cd89c461 100644 --- a/src/tests/profiler/native/gcprofiler/gcprofiler.cpp +++ b/src/tests/profiler/native/gcprofiler/gcprofiler.cpp @@ -37,6 +37,10 @@ HRESULT GCProfiler::Shutdown() { printf("GCProfiler::Shutdown: FAIL: Expected GarbageCollectionFinished to be called\n"); } + else if (_allocatedByClassCalls == 0) + { + printf("GCProfiler::Shutdown: FAIL: Expected ObjectsAllocatedByClass to be called\n"); + } else if (_pohObjectsSeenRootReferences == 0 || _pohObjectsSeenObjectReferences == 0) { printf("GCProfiler::Shutdown: FAIL: no POH objects seen. root references=%d object references=%d\n", @@ -86,6 +90,20 @@ HRESULT GCProfiler::GarbageCollectionFinished() return S_OK; } +HRESULT GCProfiler::ObjectsAllocatedByClass(ULONG cClassCount, ClassID classIds[], ULONG cObjects[]) +{ + SHUTDOWNGUARD(); + + _allocatedByClassCalls++; + if (_gcStarts != _allocatedByClassCalls) + { + _failures++; + printf("GCProfiler::ObjectsAllocatedByClass: FAIL: Expected ObjectsAllocatedByClass Calls == GCStart. AllocatedByClassCalls=%d, GCStart=%d\n", (int)_allocatedByClassCalls, (int)_gcStarts); + } + + return S_OK; +} + HRESULT GCProfiler::ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID objectRefIds[]) { SHUTDOWNGUARD(); diff --git a/src/tests/profiler/native/gcprofiler/gcprofiler.h b/src/tests/profiler/native/gcprofiler/gcprofiler.h index ab519f6f53399a..eebdb06853f7a1 100644 --- a/src/tests/profiler/native/gcprofiler/gcprofiler.h +++ b/src/tests/profiler/native/gcprofiler/gcprofiler.h @@ -16,6 +16,7 @@ class GCProfiler : public Profiler GCProfiler() : Profiler(), _gcStarts(0), _gcFinishes(0), + _allocatedByClassCalls(0), _failures(0), _pohObjectsSeenRootReferences(0), _pohObjectsSeenObjectReferences(0), @@ -28,12 +29,14 @@ class GCProfiler : public Profiler virtual HRESULT STDMETHODCALLTYPE Shutdown(); virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason); virtual HRESULT STDMETHODCALLTYPE GarbageCollectionFinished(); + virtual HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass(ULONG cClassCount, ClassID classIds[], ULONG cObjects[]); virtual HRESULT STDMETHODCALLTYPE ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID objectRefIds[]); virtual HRESULT STDMETHODCALLTYPE RootReferences(ULONG cRootRefs, ObjectID rootRefIds[]); private: std::atomic _gcStarts; std::atomic _gcFinishes; + std::atomic _allocatedByClassCalls; std::atomic _failures; std::atomic _pohObjectsSeenRootReferences; std::atomic _pohObjectsSeenObjectReferences; diff --git a/src/tests/run.proj b/src/tests/run.proj index f21a0bd1284065..1636171ec28487 100644 --- a/src/tests/run.proj +++ b/src/tests/run.proj @@ -101,7 +101,7 @@ $(_XunitEpilog) $(XUnitTestBinBase)\$(CategoryWithSlash) - $(MicrosoftNETCoreAppVersion) + $(MicrosoftNETCoreAppRuntimewinx64Version) false @@ -589,8 +589,8 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). $(MonoBinDir) - $(MonoBinDir)/cross/$(PackageRID)/mono-aot-cross - $(MonoBinDir)/cross/$(PackageRID) + $(MonoBinDir)/cross/$(OutputRid)/mono-aot-cross + $(MonoBinDir)/cross/$(OutputRid) @@ -775,6 +775,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackNativeDir)/include/mono-2.0" Assemblies="@(BundleAssemblies)" ForceInterpreter="$(MonoForceInterpreter)" + EnableAppSandbox="$(EnableAppSandbox)" UseConsoleUITemplate="True" GenerateXcodeProject="True" BuildAppBundle="True" @@ -826,7 +827,7 @@ namespace $([System.String]::Copy($(Category)).Replace(".","_").Replace("\",""). + Properties="Language=C#;OutputRid=$(OutputRid);RuntimeIdentifier=$(OutputRid)" /> diff --git a/src/tests/tracing/eventcounter/runtimecounters.cs b/src/tests/tracing/eventcounter/runtimecounters.cs index bdab454300ade0..e6623649736d1b 100644 --- a/src/tests/tracing/eventcounter/runtimecounters.cs +++ b/src/tests/tracing/eventcounter/runtimecounters.cs @@ -54,7 +54,9 @@ protected override void OnEventSourceCreated(EventSource source) { Dictionary refreshInterval = new Dictionary(); refreshInterval.Add("EventCounterIntervalSec", "1"); - EnableEvents(source, EventLevel.Informational, (EventKeywords)(-1), refreshInterval); + EnableEvents(source, EventLevel.Informational, + (EventKeywords)(-1 & (~1 /* RuntimeEventSource.Keywords.AppContext */)), + refreshInterval); } } @@ -100,7 +102,7 @@ public static int Main(string[] args) // Create an EventListener. using (RuntimeCounterListener myListener = new RuntimeCounterListener()) { - Thread.Sleep(3000); + Thread.Sleep(3000); if (myListener.Verify()) { Console.WriteLine("Test passed"); diff --git a/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs b/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs index 31f4b677681c2a..9cdc77a19eb881 100644 --- a/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs +++ b/src/tests/tracing/eventpipe/processinfo2/processinfo2.cs @@ -243,7 +243,8 @@ public static int Main(string[] args) string expectedClrProductVersion = typeof(object).Assembly.GetCustomAttribute()?.InformationalVersion; - Utils.Assert(expectedClrProductVersion.Equals(clrProductVersion), $"ClrProductVersion must match. Expected: \"{expectedClrProductVersion}\", received: \"{clrProductVersion}\""); + // https://github.com/dotnet/runtime/issues/60532 + // Utils.Assert(expectedClrProductVersion.Equals(clrProductVersion), $"ClrProductVersion must match. Expected: \"{expectedClrProductVersion}\", received: \"{clrProductVersion}\""); Utils.Assert(end == totalSize, $"Full payload should have been read. Expected: {totalSize}, Received: {end}"); diff --git a/src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs new file mode 100644 index 00000000000000..43306a803ffbfc --- /dev/null +++ b/src/tests/tracing/runtimeeventsource/NativeRuntimeEventSourceTest.cs @@ -0,0 +1,114 @@ +// 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.IO; +using System.Diagnostics.Tracing; +using System.Runtime.CompilerServices; +using System.Threading; +using Tracing.Tests.Common; + +namespace Tracing.Tests +{ + public sealed class NativeRuntimeEventSourceTest + { + static int Main(string[] args) + { + SimpleEventListener.EnableKeywords = (EventKeywords)0; + using (SimpleEventListener noEventsListener = new SimpleEventListener("NoEvents")) + { + // Create an EventListener. + SimpleEventListener.EnableKeywords = (EventKeywords)0x4c14fccbd; + using (SimpleEventListener listener = new SimpleEventListener("Simple")) + { + // Trigger the allocator task. + System.Threading.Tasks.Task.Run(new Action(Allocator)); + + // Wait for events. + Thread.Sleep(1000); + + // Generate some GC events. + GC.Collect(2, GCCollectionMode.Forced); + + // Wait for more events. + Thread.Sleep(1000); + + // Ensure that we've seen some events. + Assert.True("listener.EventCount > 0", listener.EventCount > 0); + } + + // Generate some more GC events. + GC.Collect(2, GCCollectionMode.Forced); + + // Ensure that we've seen no events. + Assert.True("noEventsListener.EventCount == 0", noEventsListener.EventCount == 0); + } + + return 100; + } + + private static void Allocator() + { + while (true) + { + for(int i=0; i<1000; i++) + GC.KeepAlive(new object()); + + Thread.Sleep(10); + } + } + } + + internal sealed class SimpleEventListener : EventListener + { + private string m_name; + + // Keep track of the set of keywords to be enabled. + public static EventKeywords EnableKeywords + { + get; + set; + } + + public SimpleEventListener(string name) + { + m_name = name; + } + + public int EventCount { get; private set; } = 0; + + protected override void OnEventSourceCreated(EventSource eventSource) + { + if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime")) + { + if (EnableKeywords != 0) + { + // Enable events. + EnableEvents(eventSource, EventLevel.Verbose, EnableKeywords); + } + else + { + // Enable the provider, but not any keywords, so we should get no events as long as no rundown occurs. + EnableEvents(eventSource, EventLevel.Critical, EnableKeywords); + } + } + } + + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + Console.WriteLine($"[{m_name}] ThreadID = {eventData.OSThreadId} ID = {eventData.EventId} Name = {eventData.EventName}"); + Console.WriteLine($"TimeStamp: {eventData.TimeStamp.ToLocalTime()}"); + Console.WriteLine($"LocalTime: {DateTime.Now}"); + Console.WriteLine($"Difference: {DateTime.UtcNow - eventData.TimeStamp}"); + Assert.True("eventData.TimeStamp <= DateTime.UtcNow", eventData.TimeStamp <= DateTime.UtcNow); + for (int i = 0; i < eventData.Payload.Count; i++) + { + string payloadString = eventData.Payload[i] != null ? eventData.Payload[i].ToString() : string.Empty; + Console.WriteLine($"\tName = \"{eventData.PayloadNames[i]}\" Value = \"{payloadString}\""); + } + Console.WriteLine("\n"); + + EventCount++; + } + } +} diff --git a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs index 4474176d360da5..3a4b4bd38667e9 100644 --- a/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs +++ b/src/tests/tracing/runtimeeventsource/RuntimeEventSourceTest.cs @@ -1,114 +1,101 @@ // 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.IO; +#if USE_MDT_EVENTSOURCE +using Microsoft.Diagnostics.Tracing; +#else using System.Diagnostics.Tracing; -using System.Runtime.CompilerServices; +#endif +using System; +using System.Collections.Generic; using System.Threading; -using Tracing.Tests.Common; +using System.Threading.Tasks; +using System.Diagnostics; -namespace Tracing.Tests +AppContext.SetSwitch("appContextSwitch", true); +AppDomain.CurrentDomain.SetData("appContextBoolData", true); // Not loggeed, bool key +AppDomain.CurrentDomain.SetData("appContextBoolAsStringData", "true"); +AppDomain.CurrentDomain.SetData("appContextStringData", "myString"); // Not logged, string does not parse as bool +AppDomain.CurrentDomain.SetData("appContextSwitch", "false"); // should not override the SetSwitch above + +// Create an EventListener. +using (var myListener = new RuntimeEventListener()) { - public sealed class RuntimeEventSourceTest + if (myListener.Verify()) + { + Console.WriteLine("Test passed"); + return 100; + } + else { - static int Main(string[] args) + Console.WriteLine($"Test Failed - did not see one or more of the expected runtime counters."); + Console.WriteLine("Observed events: "); + foreach (var (k, v) in myListener.ObservedEvents) { - SimpleEventListener.EnableKeywords = (EventKeywords)0; - using (SimpleEventListener noEventsListener = new SimpleEventListener("NoEvents")) - { - // Create an EventListener. - SimpleEventListener.EnableKeywords = (EventKeywords)0x4c14fccbd; - using (SimpleEventListener listener = new SimpleEventListener("Simple")) - { - // Trigger the allocator task. - System.Threading.Tasks.Task.Run(new Action(Allocator)); - - // Wait for events. - Thread.Sleep(1000); - - // Generate some GC events. - GC.Collect(2, GCCollectionMode.Forced); - - // Wait for more events. - Thread.Sleep(1000); - - // Ensure that we've seen some events. - Assert.True("listener.EventCount > 0", listener.EventCount > 0); - } + Console.WriteLine("Event: " + k + " " + v); + } + return 1; + } +} - // Generate some more GC events. - GC.Collect(2, GCCollectionMode.Forced); +public class RuntimeEventListener : EventListener +{ + internal readonly Dictionary ObservedEvents = new Dictionary(); - // Ensure that we've seen no events. - Assert.True("noEventsListener.EventCount == 0", noEventsListener.EventCount == 0); - } + private static readonly string[] s_expectedEvents = new[] { + "appContextSwitch", + "appContextBoolAsStringData", + "RuntimeHostConfigSwitch", // Set in the project file + }; - return 100; - } + private static readonly string[] s_unexpectedEvents = new[] { + "appContextBoolData", + "appContextStringData", + }; - private static void Allocator() + protected override void OnEventSourceCreated(EventSource source) + { + if (source.Name.Equals("System.Runtime")) { - while (true) - { - for(int i=0; i<1000; i++) - GC.KeepAlive(new object()); - - Thread.Sleep(10); - } + EnableEvents(source, EventLevel.Informational, (EventKeywords)1 /* RuntimeEventSource.Keywords.AppContext */); } } - internal sealed class SimpleEventListener : EventListener + protected override void OnEventWritten(EventWrittenEventArgs eventData) { - private string m_name; - - // Keep track of the set of keywords to be enabled. - public static EventKeywords EnableKeywords - { - get; - set; - } - - public SimpleEventListener(string name) + // Check AppContext switches + if (eventData is { EventName: "LogAppContextSwitch", + Payload: { Count: 2 } }) { - m_name = name; + var switchName = (string)eventData.Payload[0]; + ObservedEvents[switchName] = ((int)eventData.Payload[1]) == 1; + return; } + } - public int EventCount { get; private set; } = 0; - - protected override void OnEventSourceCreated(EventSource eventSource) + public bool Verify() + { + foreach (var key in s_expectedEvents) { - if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime")) + if (!ObservedEvents[key]) { - if (EnableKeywords != 0) - { - // Enable events. - EnableEvents(eventSource, EventLevel.Verbose, EnableKeywords); - } - else - { - // Enable the provider, but not any keywords, so we should get no events as long as no rundown occurs. - EnableEvents(eventSource, EventLevel.Critical, EnableKeywords); - } + Console.WriteLine($"Could not find key {key}"); + return false; + } + else + { + Console.WriteLine($"Saw {key}"); } } - protected override void OnEventWritten(EventWrittenEventArgs eventData) + foreach (var key in s_unexpectedEvents) { - Console.WriteLine($"[{m_name}] ThreadID = {eventData.OSThreadId} ID = {eventData.EventId} Name = {eventData.EventName}"); - Console.WriteLine($"TimeStamp: {eventData.TimeStamp.ToLocalTime()}"); - Console.WriteLine($"LocalTime: {DateTime.Now}"); - Console.WriteLine($"Difference: {DateTime.UtcNow - eventData.TimeStamp}"); - Assert.True("eventData.TimeStamp <= DateTime.UtcNow", eventData.TimeStamp <= DateTime.UtcNow); - for (int i = 0; i < eventData.Payload.Count; i++) + if (ObservedEvents.ContainsKey(key)) { - string payloadString = eventData.Payload[i] != null ? eventData.Payload[i].ToString() : string.Empty; - Console.WriteLine($"\tName = \"{eventData.PayloadNames[i]}\" Value = \"{payloadString}\""); + Console.WriteLine($"Should not have seen {key}"); + return false; } - Console.WriteLine("\n"); - - EventCount++; } + return true; } -} +} \ No newline at end of file diff --git a/src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj b/src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj new file mode 100644 index 00000000000000..70336054f35e5c --- /dev/null +++ b/src/tests/tracing/runtimeeventsource/nativeruntimeeventsource.csproj @@ -0,0 +1,21 @@ + + + Exe + BuildAndRun + true + 0 + true + + true + + true + + + + + + diff --git a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj index 70336054f35e5c..79075307131d43 100644 --- a/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj +++ b/src/tests/tracing/runtimeeventsource/runtimeeventsource.csproj @@ -4,18 +4,13 @@ BuildAndRun true 0 - true true - - true + true + diff --git a/src/workloads/workloads.csproj b/src/workloads/workloads.csproj index 92b25bf61fc46b..f64d641604674d 100644 --- a/src/workloads/workloads.csproj +++ b/src/workloads/workloads.csproj @@ -34,42 +34,54 @@ - $(PkgWix)\tools + $(PkgMicrosoft_Signed_Wix)\tools $(PkgMicroBuild_Plugins_SwixBuild_Dotnet) $(SwixPluginPath)\build\MicroBuild.Plugins.SwixBuild.targets - + - + + - - - + + + + + + + @@ -94,14 +106,6 @@ - - - - - - - - - - + + + <_MajorVersion>$([System.Version]::Parse('$(AssemblyVersion)').Major) + <_MinorVersion>$([System.Version]::Parse('$(AssemblyVersion)').Minor) + <_PatchVersion>$([System.Version]::Parse('$(AssemblyVersion)').Build) + <_BuildNumber>$([System.Version]::Parse('$(AssemblyVersion)').Revision) + + + - $(GitCommitCount.PadLeft(6,'0')) + 5 + + 1996-04-01 + - - $(_PatchNumber) - - $(GitCommitCount) + + + + - - $(FileVersion) - - $(VersionPrefix).$(CombinedBuildNumberAndRevision) - + + +