Consolidate downlevel library API polyfills#130581
Conversation
Replace target-specific fallbacks in shipped libraries with shared polyfills for missing framework APIs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9dd11e22-e8e2-4915-ac0a-67eab550e366
|
Tagging subscribers to this area: @dotnet/area-meta |
There was a problem hiding this comment.
Pull request overview
This PR removes a large set of target-framework #if branches across several libraries by introducing (and then consuming) shared downlevel polyfills under src/libraries/Common/src/Polyfills, allowing call sites to use “normal” APIs (e.g., TryAdd, span-based parsing/formatting, span-based stream helpers, RuntimeHelpers, etc.) consistently across TFMs.
Changes:
- Adds new shared polyfill helpers (e.g., dictionary helpers, span-based stream helpers, parsing/formatting, reflection delegate creation, runtime feature helpers, binary primitives).
- Replaces per-library
#if NET...call-site logic with unified calls that bind to either in-box APIs (on .NET) or the shared polyfills (downlevel TFMs). - Updates multiple
.csprojfiles to link the needed polyfill sources for non-.NETCoreApptargets.
Reviewed changes
Copilot reviewed 65 out of 65 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfo.cs | Uses TryAdd directly for extension-data duplicate detection instead of TFM-specific branches. |
| src/libraries/System.Text.Json/src/System.Text.Json.csproj | Links DictionaryPolyfills.cs for non-.NETCoreApp builds. |
| src/libraries/System.Security.Cryptography.Cose/src/System/Security/Cryptography/Cose/PureDataToBeSignedBuilder.cs | Uses span-based Stream.Write unconditionally (polyfilled downlevel). |
| src/libraries/System.Security.Cryptography.Cose/src/System.Security.Cryptography.Cose.csproj | Links StreamSpanPolyfills.cs for non-.NETCoreApp builds. |
| src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/BinaryFormat/SerializationInfoExtensions.cs | Uses generic delegate creation via CreateDelegate<T>() uniformly. |
| src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/BinaryFormat/SerializationEvents.cs | Uses generic delegate creation uniformly for serialization callbacks. |
| src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/BinaryFormat/Deserializer/ClassRecordDeserializer.cs | Uses RuntimeHelpers.GetUninitializedObject uniformly (polyfilled downlevel). |
| src/libraries/System.Resources.Extensions/src/System.Resources.Extensions.csproj | Links ReflectionPolyfills and RuntimeHelpersPolyfills for downlevel TFMs. |
| src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/TypeNameParseOptions.cs | Uses ArgumentOutOfRangeException.ThrowIfLessThanOrEqual uniformly (polyfilled downlevel). |
| src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/NamespaceCache.cs | Uses ReadOnlySpan<char>.Count('.') uniformly (polyfilled span helpers). |
| src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriterImpl.cs | Uses BinaryPrimitives.WriteDouble/SingleLittleEndian uniformly (polyfilled downlevel). |
| src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/DecimalUtilities.cs | Uses decimal.GetBits(decimal, Span<int>) uniformly (polyfilled downlevel). |
| src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj | Links BinaryPrimitivesPolyfills and DecimalPolyfills for non-.NETCoreApp builds. |
| src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs | Uses UTF-8 long.TryParse(ReadOnlySpan<byte>) uniformly (polyfilled downlevel). |
| src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs | Uses UTF-8 long.TryFormat(Span<byte>) uniformly (polyfilled downlevel). |
| src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj | Links Int64Polyfills.cs for non-.NETCoreApp builds. |
| src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipPackagePartPiece.cs | Uses ArgumentOutOfRangeException.ThrowIfNegative uniformly (polyfilled downlevel). |
| src/libraries/System.IO.Packaging/src/System/IO/Packaging/InternalRelationshipCollection.cs | Uses Enum.Parse<TEnum> uniformly (polyfilled downlevel). |
| src/libraries/System.IO.Packaging/src/System.IO.Packaging.csproj | Links EnumPolyfills.cs for non-.NETCoreApp builds. |
| src/libraries/System.IO.Hashing/src/System/IO/Hashing/XxHashShared.cs | Uses Math.BigMul(ulong, ulong, out ulong) uniformly (polyfilled downlevel). |
| src/libraries/System.IO.Hashing/src/System.IO.Hashing.csproj | Links MathPolyfills.cs for non-.NETCoreApp builds. |
| src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/RecordMap.cs | Uses Dictionary.TryAdd uniformly for duplicate record ID handling. |
| src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ClassInfo.cs | Uses Dictionary.TryAdd uniformly for member-name uniqueness. |
| src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/ArraySinglePrimitiveRecord.cs | Uses Stream.ReadExactly and span BinaryPrimitives.ReverseEndianness uniformly (polyfilled downlevel). |
| src/libraries/System.Formats.Nrbf/src/System.Formats.Nrbf.csproj | Links shared polyfills (BinaryPrimitives, Dictionary, StreamSpan) for non-.NETCoreApp builds. |
| src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/SetOfValueComparer.cs | Uses CommonPrefixLength uniformly (polyfilled downlevel). |
| src/libraries/System.Diagnostics.DiagnosticSource/tests/System.Diagnostics.DiagnosticSource.Tests.csproj | Links additional polyfills for test TFMs (non-.NETCoreApp). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/MetricsEventSource.cs | Uses span-based int.TryParse uniformly (polyfilled downlevel). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/CircularBufferBuckets.cs | Uses Array.Clear(Array) uniformly (polyfilled downlevel). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Base2ExponentialHistogramAggregator.cs | Uses BitOperations.LeadingZeroCount uniformly (polyfilled downlevel). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DsesFilterAndTransform.cs | Uses span-based double/int.TryParse uniformly (polyfilled downlevel). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DsesActivitySourceListener.cs | Uses Dictionary.TryAdd uniformly for spec deduplication. |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs | Uses Convert.ToHexStringLower uniformly (polyfilled downlevel). |
| src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj | Links added polyfills for non-.NETCoreApp builds. |
| src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedSet_1.cs | Uses span List<T>.AddRange uniformly (polyfilled downlevel). |
| src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.Builder.cs | Uses generic Array.Reverse<T> uniformly (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceProvider.cs | Uses RuntimeFeature.IsDynamicCodeSupported uniformly (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/StackGuard.cs | Uses RuntimeHelpers.TryEnsureSufficientExecutionStack uniformly (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ILEmit/ILEmitResolverBuilder.cs | Uses the 3-arg ConcurrentDictionary.GetOrAdd uniformly (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs | Uses the 3-arg ConcurrentDictionary.GetOrAdd uniformly (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.DependencyInjection/src/Microsoft.Extensions.DependencyInjection.csproj | Links ConcurrentDictionaryPolyfills, RuntimeFeaturePolyfills, RuntimeHelpersPolyfills for downlevel TFMs. |
| src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/Microsoft.Extensions.DependencyInjection.Abstractions.csproj | Links RuntimeFeaturePolyfills for downlevel TFMs. |
| src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/EmptyServiceProvider.cs | Uses RuntimeFeature.IsDynamicCodeSupported uniformly (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.Configuration.Xml/src/XmlStreamConfigurationProvider.cs | Uses TryAdd uniformly for duplicate-key detection (polyfilled downlevel). |
| src/libraries/Microsoft.Extensions.Configuration.Xml/src/Microsoft.Extensions.Configuration.Xml.csproj | Links DictionaryPolyfills.cs for downlevel TFMs. |
| src/libraries/Microsoft.Extensions.Caching.Memory/src/Microsoft.Extensions.Caching.Memory.csproj | Links ConcurrentDictionaryPolyfills.cs for downlevel TFMs. |
| src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs | Uses ConcurrentDictionary.TryRemove(KeyValuePair<,>) uniformly (polyfilled downlevel). |
| src/libraries/Common/src/System/MemoryExtensionsPolyfills.cs | Adds span helpers (Count, CommonPrefixLength) used by updated call sites. |
| src/libraries/Common/src/System/ExceptionPolyfills.cs | Adds additional ArgumentOutOfRangeException.ThrowIf* polyfills used by updated call sites. |
| src/libraries/Common/src/Polyfills/StreamSpanPolyfills.cs | Introduces span-based Stream polyfills (Read, Write, ReadExactly, ReadAtLeast). |
| src/libraries/Common/src/Polyfills/RuntimeHelpersPolyfills.cs | Narrows TryEnsureSufficientExecutionStack catch to InsufficientExecutionStackException. |
| src/libraries/Common/src/Polyfills/RuntimeFeaturePolyfills.cs | Adds downlevel RuntimeFeature.IsDynamicCodeSupported polyfill. |
| src/libraries/Common/src/Polyfills/ReflectionPolyfills.cs | Adds MethodInfo.CreateDelegate<T> polyfills used by resources extensions. |
| src/libraries/Common/src/Polyfills/MathPolyfills.cs | Adds downlevel Math.BigMul(ulong, ulong, out ulong) polyfill. |
| src/libraries/Common/src/Polyfills/Int64Polyfills.cs | Adds downlevel UTF-8 long.TryParse(ReadOnlySpan<byte>) and UTF-8 TryFormat helper. |
| src/libraries/Common/src/Polyfills/Int32Polyfills.cs | Adds downlevel span-based int.TryParse(ReadOnlySpan<char>, ...). |
| src/libraries/Common/src/Polyfills/EnumPolyfills.cs | Adds downlevel generic Enum.Parse<TEnum> helper. |
| src/libraries/Common/src/Polyfills/DoublePolyfills.cs | Adds downlevel span-based double.TryParse(ReadOnlySpan<char>, ...). |
| src/libraries/Common/src/Polyfills/DecimalPolyfills.cs | Adds downlevel decimal.GetBits(decimal, Span<int>) helper. |
| src/libraries/Common/src/Polyfills/ConvertPolyfills.cs | Adds downlevel Convert.ToHexStringLower(ReadOnlySpan<byte>) helper. |
| src/libraries/Common/src/Polyfills/ConcurrentDictionaryPolyfills.cs | Adds downlevel ConcurrentDictionary.GetOrAdd (with state arg) and TryRemove(KeyValuePair) helper. |
| src/libraries/Common/src/Polyfills/CollectionsPolyfills.cs | Adds List<T>.AddRange(ReadOnlySpan<T>) helper for downlevel. |
| src/libraries/Common/src/Polyfills/BitOperationsPolyfills.cs | Adds BitOperations.LeadingZeroCount helpers used by updated call sites. |
| src/libraries/Common/src/Polyfills/BinaryPrimitivesPolyfills.cs | Adds downlevel BinaryPrimitives.WriteSingle/DoubleLittleEndian and span ReverseEndianness helpers. |
| src/libraries/Common/src/Polyfills/ArrayPolyfills.cs | Adds downlevel Array.Clear(Array) and generic Array.Reverse<T> helpers. |
| src/libraries/Common/src/Polyfills/DictionaryPolyfills.cs | Adds downlevel IDictionary<TKey,TValue>.TryAdd helper. |
Restore the original BinaryPrimitives, Int64, Math, Stream span, and MemoryCache target-specific implementations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9dd11e22-e8e2-4915-ac0a-67eab550e366
Match Array.Clear and Array.Reverse argument validation and lower-bound behavior with the framework implementations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9dd11e22-e8e2-4915-ac0a-67eab550e366
Restore the target-specific Array.Reverse and RuntimeFeature implementations requested during PR refinement. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9dd11e22-e8e2-4915-ac0a-67eab550e366
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d4a076fc-e1aa-4d7f-a5d5-ccd89277bc19
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1e2ebd26-ba12-428e-826b-d4c65e99ab83
|
@jkotas @MihaZupan anything else here? The goal is just to have less if-defs in libraries + one unsafe context is moved under the rug. |
Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
…iagnostics/DsesActivitySourceListener.cs Co-authored-by: Miha Zupan <mihazupan.zupan1@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 745ed4f5-b953-4b7c-b34a-89de11f95432
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1ec9dd1-21d6-4f9a-af6f-8549ae169d49
|
/ba-g known issue that just got fixed in main |
move more stuff to Polyfills
Note
This pull request was created with GitHub Copilot.