Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSteve Harter <steveharter@users.noreply.github.com>2021-07-13 20:57:48 +0300
committerGitHub <noreply@github.com>2021-07-13 20:57:48 +0300
commit04429ca36aa2a4075a1638a6025d2df74792741d (patch)
treeb76658246466c58b297227b1610d5d3d7252a3ec /src
parent2c275e87c0033da3830bae29059d9ee5b663cf58 (diff)
Remove C# dynamic support from JsonNode (#55430)
Diffstat (limited to 'src')
-rw-r--r--src/libraries/System.Text.Json/ref/System.Text.Json.cs3
-rw-r--r--src/libraries/System.Text.Json/ref/System.Text.Json.csproj2
-rw-r--r--src/libraries/System.Text.Json/src/ILLink/ILLink.Suppressions.LibraryBuild.xml12
-rw-r--r--src/libraries/System.Text.Json/src/System.Text.Json.csproj5
-rw-r--r--src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Dynamic.cs27
-rw-r--r--src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.Dynamic.cs55
-rw-r--r--src/libraries/System.Text.Json/src/System/Text/Json/Nodes/MetaDynamic.cs438
-rw-r--r--src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/StackOfTConverter.cs1
-rw-r--r--src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs6
-rw-r--r--src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonObjectConverter.cs2
-rw-r--r--src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/DynamicTests.cs282
-rw-r--r--src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs42
-rw-r--r--src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj1
-rw-r--r--src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/Collections/StackOfT.cs14
14 files changed, 56 insertions, 834 deletions
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 a7d5a44feb6..26b72dd6493 100644
--- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs
+++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs
@@ -547,7 +547,7 @@ namespace System.Text.Json.Nodes
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
public override void WriteTo(System.Text.Json.Utf8JsonWriter writer, System.Text.Json.JsonSerializerOptions? options = null) { }
}
- public abstract partial class JsonNode : System.Dynamic.IDynamicMetaObjectProvider
+ public abstract partial class JsonNode
{
internal JsonNode() { }
public System.Text.Json.Nodes.JsonNode? this[int index] { get { throw null; } set { } }
@@ -646,7 +646,6 @@ namespace System.Text.Json.Nodes
public static System.Text.Json.Nodes.JsonNode? Parse(System.ReadOnlySpan<byte> utf8Json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; }
public static System.Text.Json.Nodes.JsonNode? Parse(string json, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?), System.Text.Json.JsonDocumentOptions documentOptions = default(System.Text.Json.JsonDocumentOptions)) { throw null; }
public static System.Text.Json.Nodes.JsonNode? Parse(ref System.Text.Json.Utf8JsonReader reader, System.Text.Json.Nodes.JsonNodeOptions? nodeOptions = default(System.Text.Json.Nodes.JsonNodeOptions?)) { throw null; }
- System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(System.Linq.Expressions.Expression parameter) { throw null; }
public string ToJsonString(System.Text.Json.JsonSerializerOptions? options = null) { throw null; }
public override string ToString() { throw null; }
public abstract void WriteTo(System.Text.Json.Utf8JsonWriter writer, System.Text.Json.JsonSerializerOptions? options = 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 dc0bb21c008..f015d29c355 100644
--- a/src/libraries/System.Text.Json/ref/System.Text.Json.csproj
+++ b/src/libraries/System.Text.Json/ref/System.Text.Json.csproj
@@ -13,7 +13,6 @@
<Compile Include="$(CoreLibSharedDir)System\Diagnostics\CodeAnalysis\RequiresUnreferencedCodeAttribute.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(NetCoreAppCurrent)'">
- <ProjectReference Include="$(LibrariesProjectRoot)System.Linq.Expressions\ref\System.Linq.Expressions.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Memory\ref\System.Memory.csproj" />
<ProjectReference Include="$(LibrariesProjectRoot)System.Runtime\ref\System.Runtime.csproj" />
</ItemGroup>
@@ -21,7 +20,6 @@
<Reference Include="System.Collections" />
<Reference Include="System.Memory" />
<Reference Include="System.Runtime" />
- <Reference Include="System.Linq.Expressions" />
<Reference Include="netstandard" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
diff --git a/src/libraries/System.Text.Json/src/ILLink/ILLink.Suppressions.LibraryBuild.xml b/src/libraries/System.Text.Json/src/ILLink/ILLink.Suppressions.LibraryBuild.xml
deleted file mode 100644
index b12ccebb9c9..00000000000
--- a/src/libraries/System.Text.Json/src/ILLink/ILLink.Suppressions.LibraryBuild.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<linker>
- <assembly fullname="System.Text.Json">
- <attribute fullname="System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute">
- <argument>ILLink</argument>
- <argument>IL2026</argument>
- <property name="Scope">member</property>
- <property name="Target">M:System.Text.Json.Nodes.JsonNode.System#Dynamic#IDynamicMetaObjectProvider#GetMetaObject(System.Linq.Expressions.Expression)</property>
- <property name="Justification">System.Text.Json's integration with dynamic is not trim compatible. However, there isn't a direct API developers call. Instead they use the 'dynamic' keyword, which gets compiled into calls to Microsoft.CSharp. Microsoft.CSharp looks for IDynamicMetaObjectProvider implementations. Leaving this warning in the product so developers get a warning stating that using dynamic JsonValue code may be broken in trimmed apps.</property>
- </attribute>
- </assembly>
-</linker>
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 195c640c85a..3206cbd6de1 100644
--- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj
+++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj
@@ -59,20 +59,17 @@
<Compile Include="System\Text\Json\Nodes\JsonArray.cs" />
<Compile Include="System\Text\Json\Nodes\JsonArray.IList.cs" />
<Compile Include="System\Text\Json\Nodes\JsonNode.cs" />
- <Compile Include="System\Text\Json\Nodes\JsonNode.Dynamic.cs" />
<Compile Include="System\Text\Json\Nodes\JsonNode.Operators.cs" />
<Compile Include="System\Text\Json\Nodes\JsonNode.Parse.cs" />
<Compile Include="System\Text\Json\Nodes\JsonNode.To.cs" />
<Compile Include="System\Text\Json\Nodes\JsonNodeOptions.cs" />
<Compile Include="System\Text\Json\Nodes\JsonObject.cs" />
- <Compile Include="System\Text\Json\Nodes\JsonObject.Dynamic.cs" />
<Compile Include="System\Text\Json\Nodes\JsonObject.IDictionary.cs" />
<Compile Include="System\Text\Json\Nodes\JsonValue.CreateOverloads.cs" />
<Compile Include="System\Text\Json\Nodes\JsonValue.cs" />
<Compile Include="System\Text\Json\Nodes\JsonValueNotTrimmable.cs" />
<Compile Include="System\Text\Json\Nodes\JsonValueOfT.cs" />
<Compile Include="System\Text\Json\Nodes\JsonValueTrimmable.cs" />
- <Compile Include="System\Text\Json\Nodes\MetaDynamic.cs" />
<Compile Include="System\Text\Json\Reader\ConsumeNumberResult.cs" />
<Compile Include="System\Text\Json\Reader\ConsumeTokenResult.cs" />
<Compile Include="System\Text\Json\Reader\JsonReaderException.cs" />
@@ -298,7 +295,6 @@
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Diagnostics.Debug" />
<Reference Include="System.Diagnostics.Tools" Condition="'$(TargetFramework)' == 'netcoreapp3.1'" />
- <Reference Include="System.Linq.Expressions" />
<Reference Include="System.Memory" />
<Reference Include="System.Numerics.Vectors" />
<Reference Include="System.Reflection.Emit.ILGeneration" />
@@ -315,7 +311,6 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
<PackageReference Include="System.Buffers" Version="$(SystemBuffersVersion)" />
- <PackageReference Include="System.Linq.Expressions" Version="$(SystemLinqExpressionsVersion)" />
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<PackageReference Include="System.Numerics.Vectors" Version="$(SystemNumericsVectorsVersion)" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsVersion)" />
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Dynamic.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Dynamic.cs
deleted file mode 100644
index 457af37eb0f..00000000000
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.Dynamic.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics.CodeAnalysis;
-using System.Dynamic;
-using System.Linq.Expressions;
-using System.Reflection;
-
-namespace System.Text.Json.Nodes
-{
- public partial class JsonNode : IDynamicMetaObjectProvider
- {
- internal virtual MethodInfo? TryGetMemberMethodInfo => null;
- internal virtual MethodInfo? TrySetMemberMethodInfo
- {
- [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
- get => null;
- }
-
- DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) =>
- CreateDynamicObject(parameter, this);
-
- [RequiresUnreferencedCode("Using JsonNode instances as dynamic types is not compatible with trimming. It can result in non-primitive types being serialized, which may have their members trimmed.")]
- private static DynamicMetaObject CreateDynamicObject(Expression parameter, JsonNode node) =>
- new MetaDynamic(parameter, node);
- }
-}
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.Dynamic.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.Dynamic.cs
deleted file mode 100644
index b343b70d3fa..00000000000
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.Dynamic.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Diagnostics.CodeAnalysis;
-using System.Dynamic;
-using System.Reflection;
-
-namespace System.Text.Json.Nodes
-{
- public partial class JsonObject
- {
- private bool TryGetMemberCallback(GetMemberBinder binder, out object? result)
- {
- if (TryGetPropertyValue(binder.Name, out JsonNode? node))
- {
- result = node;
- return true;
- }
-
- // Return null for missing properties.
- result = null;
- return true;
- }
-
- [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
- private bool TrySetMemberCallback(SetMemberBinder binder, object? value)
- {
- JsonNode? node = null;
- if (value != null)
- {
- node = value as JsonNode;
- if (node == null)
- {
- node = new JsonValueNotTrimmable<object>(value, Options);
- }
- }
-
- this[binder.Name] = node;
- return true;
- }
-
- private const BindingFlags MemberInfoBindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
-
- private static MethodInfo? s_TryGetMember;
- internal override MethodInfo? TryGetMemberMethodInfo =>
- s_TryGetMember ??= typeof(JsonObject).GetMethod(nameof(TryGetMemberCallback), MemberInfoBindingFlags);
-
- private static MethodInfo? s_TrySetMember;
- internal override MethodInfo? TrySetMemberMethodInfo
- {
- [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
- get => s_TrySetMember ??= typeof(JsonObject).GetMethod(nameof(TrySetMemberCallback), MemberInfoBindingFlags);
- }
- }
-}
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/MetaDynamic.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/MetaDynamic.cs
deleted file mode 100644
index 8806fe30352..00000000000
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/MetaDynamic.cs
+++ /dev/null
@@ -1,438 +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.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Dynamic;
-using System.Linq.Expressions;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-namespace System.Text.Json.Nodes
-{
- // The bulk of this code was pulled from src/libraries/System.Linq.Expressions/src/System/Dynamic/DynamicObject.cs
- // and then refactored.
- internal sealed class MetaDynamic : DynamicMetaObject
- {
- private static readonly ConstantExpression NullExpression = Expression.Constant(null);
- private static readonly DefaultExpression EmptyExpression = Expression.Empty();
- private static readonly ConstantExpression Int1Expression = Expression.Constant((object)1);
-
- private JsonNode Dynamic { get; }
-
- [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
- internal MetaDynamic(Expression expression, JsonNode dynamicObject)
- : base(expression, BindingRestrictions.Empty, dynamicObject)
- {
- Dynamic = dynamicObject;
- }
-
- public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
- {
- MethodInfo? methodInfo = Dynamic.TryGetMemberMethodInfo;
- if (methodInfo == null)
- {
- return base.BindGetMember(binder);
- }
-
- return CallMethodWithResult(
- methodInfo,
- binder,
- s_noArgs,
- (MetaDynamic @this, GetMemberBinder b, DynamicMetaObject? e) => b.FallbackGetMember(@this, e)
- );
- }
-
- [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
- Justification = "The ctor is marked with RequiresUnreferencedCode.")]
- public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
- {
- MethodInfo? methodInfo = Dynamic.TrySetMemberMethodInfo;
- if (methodInfo == null)
- {
- return base.BindSetMember(binder, value);
- }
-
- DynamicMetaObject localValue = value;
-
- return CallMethodReturnLast(
- methodInfo,
- binder,
- s_noArgs,
- value.Expression,
- (MetaDynamic @this, SetMemberBinder b, DynamicMetaObject? e) => b.FallbackSetMember(@this, localValue, e)
- );
- }
-
- private delegate DynamicMetaObject Fallback<TBinder>(MetaDynamic @this, TBinder binder, DynamicMetaObject? errorSuggestion);
-
-#pragma warning disable CA1825 // used in reference comparison, requires unique object identity
- private static readonly Expression[] s_noArgs = new Expression[0];
-#pragma warning restore CA1825
-
- private static ReadOnlyCollection<Expression> GetConvertedArgs(params Expression[] args)
- {
- var paramArgs = new Expression[args.Length];
-
- for (int i = 0; i < args.Length; i++)
- {
- paramArgs[i] = Expression.Convert(args[i], typeof(object));
- }
-
- return new ReadOnlyCollection<Expression>(paramArgs);
- }
-
- /// <summary>
- /// Helper method for generating expressions that assign byRef call
- /// parameters back to their original variables.
- /// </summary>
- private static Expression ReferenceArgAssign(Expression callArgs, Expression[] args)
- {
- ReadOnlyCollectionBuilder<Expression>? block = null;
-
- for (int i = 0; i < args.Length; i++)
- {
- ParameterExpression variable = (ParameterExpression)args[i];
-
- if (variable.IsByRef)
- {
- if (block == null)
- block = new ReadOnlyCollectionBuilder<Expression>();
-
- block.Add(
- Expression.Assign(
- variable,
- Expression.Convert(
- Expression.ArrayIndex(
- callArgs,
- Int1Expression
- ),
- variable.Type
- )
- )
- );
- }
- }
-
- if (block != null)
- return Expression.Block(block);
- else
- return EmptyExpression;
- }
-
- /// <summary>
- /// Helper method for generating arguments for calling methods
- /// on DynamicObject. parameters is either a list of ParameterExpressions
- /// to be passed to the method as an object[], or NoArgs to signify that
- /// the target method takes no object[] parameter.
- /// </summary>
- private static Expression[] BuildCallArgs<TBinder>(TBinder binder, Expression[] parameters, Expression arg0, Expression? arg1)
- where TBinder : DynamicMetaObjectBinder
- {
- if (!ReferenceEquals(parameters, s_noArgs))
- return arg1 != null ? new Expression[] { Constant(binder), arg0, arg1 } : new Expression[] { Constant(binder), arg0 };
- else
- return arg1 != null ? new Expression[] { Constant(binder), arg1 } : new Expression[] { Constant(binder) };
- }
-
- private static ConstantExpression Constant<TBinder>(TBinder binder)
- {
- return Expression.Constant(binder, typeof(TBinder));
- }
-
- /// <summary>
- /// Helper method for generating a MetaObject which calls a
- /// specific method on Dynamic that returns a result
- /// </summary>
- private DynamicMetaObject CallMethodWithResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Fallback<TBinder> fallback)
- where TBinder : DynamicMetaObjectBinder
- {
- return CallMethodWithResult(method, binder, args, fallback, null);
- }
-
- /// <summary>
- /// Helper method for generating a MetaObject which calls a
- /// specific method on Dynamic that returns a result
- /// </summary>
- private DynamicMetaObject CallMethodWithResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Fallback<TBinder> fallback, Fallback<TBinder>? fallbackInvoke)
- where TBinder : DynamicMetaObjectBinder
- {
- //
- // First, call fallback to do default binding
- // This produces either an error or a call to a .NET member
- //
- DynamicMetaObject fallbackResult = fallback(this, binder, null);
-
- DynamicMetaObject callDynamic = BuildCallMethodWithResult(method, binder, args, fallbackResult, fallbackInvoke);
-
- //
- // Now, call fallback again using our new MO as the error
- // When we do this, one of two things can happen:
- // 1. Binding will succeed, and it will ignore our call to
- // the dynamic method, OR
- // 2. Binding will fail, and it will use the MO we created
- // above.
- //
- return fallback(this, binder, callDynamic);
- }
-
- private DynamicMetaObject BuildCallMethodWithResult<TBinder>(MethodInfo method, TBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback<TBinder>? fallbackInvoke)
- where TBinder : DynamicMetaObjectBinder
- {
- ParameterExpression result = Expression.Parameter(typeof(object), null);
- ParameterExpression callArgs = Expression.Parameter(typeof(object[]), null);
- ReadOnlyCollection<Expression> callArgsValue = GetConvertedArgs(args);
-
- var resultMO = new DynamicMetaObject(result, BindingRestrictions.Empty);
-
- // Need to add a conversion if calling TryConvert
- if (binder.ReturnType != typeof(object))
- {
- Debug.Assert(binder is ConvertBinder && fallbackInvoke == null);
-
- UnaryExpression convert = Expression.Convert(resultMO.Expression, binder.ReturnType);
- // will always be a cast or unbox
- Debug.Assert(convert.Method == null);
-
- // Prepare a good exception message in case the convert will fail
- string convertFailed = SR.Format(SR.NodeDynamicObjectResultNotAssignable,
- "{0}",
- this.Value.GetType(),
- binder.GetType(),
- binder.ReturnType
- );
-
- Expression condition;
- // If the return type can not be assigned null then just check for type assignability otherwise allow null.
- if (binder.ReturnType.IsValueType && Nullable.GetUnderlyingType(binder.ReturnType) == null)
- {
- condition = Expression.TypeIs(resultMO.Expression, binder.ReturnType);
- }
- else
- {
- condition = Expression.OrElse(
- Expression.Equal(resultMO.Expression, NullExpression),
- Expression.TypeIs(resultMO.Expression, binder.ReturnType));
- }
-
- Expression checkedConvert = Expression.Condition(
- condition,
- convert,
- Expression.Throw(
- Expression.New(
- CachedReflectionInfo.InvalidCastException_Ctor_String,
- new TrueReadOnlyCollection<Expression>(
- Expression.Call(
- CachedReflectionInfo.String_Format_String_ObjectArray,
- Expression.Constant(convertFailed),
- Expression.NewArrayInit(
- typeof(object),
- new TrueReadOnlyCollection<Expression>(
- Expression.Condition(
- Expression.Equal(resultMO.Expression, NullExpression),
- Expression.Constant("null"),
- Expression.Call(
- resultMO.Expression,
- CachedReflectionInfo.Object_GetType
- ),
- typeof(object)
- )
- )
- )
- )
- )
- ),
- binder.ReturnType
- ),
- binder.ReturnType
- );
-
- resultMO = new DynamicMetaObject(checkedConvert, resultMO.Restrictions);
- }
-
- if (fallbackInvoke != null)
- {
- resultMO = fallbackInvoke(this, binder, resultMO);
- }
-
- var callDynamic = new DynamicMetaObject(
- Expression.Block(
- new TrueReadOnlyCollection<ParameterExpression>(result, callArgs),
- new TrueReadOnlyCollection<Expression>(
- Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)),
- Expression.Condition(
- Expression.Call(
- GetLimitedSelf(),
- method,
- BuildCallArgs(
- binder,
- args,
- callArgs,
- result
- )
- ),
- Expression.Block(
- ReferenceArgAssign(callArgs, args),
- resultMO.Expression
- ),
- fallbackResult.Expression,
- binder.ReturnType
- )
- )
- ),
- GetRestrictions().Merge(resultMO.Restrictions).Merge(fallbackResult.Restrictions)
- );
- return callDynamic;
- }
-
- private DynamicMetaObject CallMethodReturnLast<TBinder>(MethodInfo method, TBinder binder, Expression[] args, Expression value, Fallback<TBinder> fallback)
- where TBinder : DynamicMetaObjectBinder
- {
- //
- // First, call fallback to do default binding
- // This produces either an error or a call to a .NET member
- //
- DynamicMetaObject fallbackResult = fallback(this, binder, null);
-
- //
- // Build a new expression like:
- // {
- // object result;
- // TrySetMember(payload, result = value) ? result : fallbackResult
- // }
- //
-
- ParameterExpression result = Expression.Parameter(typeof(object), null);
- ParameterExpression callArgs = Expression.Parameter(typeof(object[]), null);
- ReadOnlyCollection<Expression> callArgsValue = GetConvertedArgs(args);
-
- var callDynamic = new DynamicMetaObject(
- Expression.Block(
- new TrueReadOnlyCollection<ParameterExpression>(result, callArgs),
- new TrueReadOnlyCollection<Expression>(
- Expression.Assign(callArgs, Expression.NewArrayInit(typeof(object), callArgsValue)),
- Expression.Condition(
- Expression.Call(
- GetLimitedSelf(),
- method,
- BuildCallArgs(
- binder,
- args,
- callArgs,
- Expression.Assign(result, Expression.Convert(value, typeof(object)))
- )
- ),
- Expression.Block(
- ReferenceArgAssign(callArgs, args),
- result
- ),
- fallbackResult.Expression,
- typeof(object)
- )
- )
- ),
- GetRestrictions().Merge(fallbackResult.Restrictions)
- );
-
- //
- // Now, call fallback again using our new MO as the error
- // When we do this, one of two things can happen:
- // 1. Binding will succeed, and it will ignore our call to
- // the dynamic method, OR
- // 2. Binding will fail, and it will use the MO we created
- // above.
- //
- return fallback(this, binder, callDynamic);
- }
-
- /// <summary>
- /// Returns a Restrictions object which includes our current restrictions merged
- /// with a restriction limiting our type
- /// </summary>
- private BindingRestrictions GetRestrictions()
- {
- Debug.Assert(Restrictions == BindingRestrictions.Empty, "We don't merge, restrictions are always empty");
-
- return GetTypeRestriction(this);
- }
-
- /// <summary>
- /// Returns our Expression converted to DynamicObject
- /// </summary>
- private Expression GetLimitedSelf()
- {
- // Convert to DynamicObject rather than LimitType, because
- // the limit type might be non-public.
- if (AreEquivalent(Expression.Type, Value.GetType()))
- {
- return Expression;
- }
- return Expression.Convert(Expression, Value.GetType());
- }
-
- private static bool AreEquivalent(Type? t1, Type? t2) => t1 != null && t1.IsEquivalentTo(t2);
-
- private new object Value => base.Value!;
-
- // It is okay to throw NotSupported from this binder. This object
- // is only used by DynamicObject.GetMember--it is not expected to
- // (and cannot) implement binding semantics. It is just so the DO
- // can use the Name and IgnoreCase properties.
- private sealed class GetBinderAdapter : GetMemberBinder
- {
- internal GetBinderAdapter(InvokeMemberBinder binder)
- : base(binder.Name, binder.IgnoreCase)
- {
- }
-
- public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion)
- {
- throw new NotSupportedException();
- }
- }
-
- private sealed class TrueReadOnlyCollection<T> : ReadOnlyCollection<T>
- {
- /// <summary>
- /// Creates instance of TrueReadOnlyCollection, wrapping passed in array.
- /// !!! DOES NOT COPY THE ARRAY !!!
- /// </summary>
- public TrueReadOnlyCollection(params T[] list)
- : base(list)
- {
- }
- }
-
- internal static BindingRestrictions GetTypeRestriction(DynamicMetaObject obj)
- {
- Debug.Assert(obj != null);
- if (obj.Value == null && obj.HasValue)
- {
- return BindingRestrictions.GetInstanceRestriction(obj.Expression, null);
- }
- else
- {
- return BindingRestrictions.GetTypeRestriction(obj.Expression, obj.LimitType);
- }
- }
-
- internal static partial class CachedReflectionInfo
- {
- private static MethodInfo? s_String_Format_String_ObjectArray;
- public static MethodInfo String_Format_String_ObjectArray =>
- s_String_Format_String_ObjectArray ??
- (s_String_Format_String_ObjectArray = typeof(string).GetMethod(nameof(string.Format), new Type[] { typeof(string), typeof(object[]) })!);
-
- private static ConstructorInfo? s_InvalidCastException_Ctor_String;
- public static ConstructorInfo InvalidCastException_Ctor_String =>
- s_InvalidCastException_Ctor_String ??
- (s_InvalidCastException_Ctor_String = typeof(InvalidCastException).GetConstructor(new Type[] { typeof(string) })!);
-
- private static MethodInfo? s_Object_GetType;
- public static MethodInfo Object_GetType =>
- s_Object_GetType ??
- (s_Object_GetType = typeof(object).GetMethod(nameof(object.GetType))!);
- }
- }
-}
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/StackOfTConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/StackOfTConverter.cs
index df483b6986e..7e1badfb968 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/StackOfTConverter.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Collection/StackOfTConverter.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
namespace System.Text.Json.Serialization.Converters
{
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 1e1856ccdaa..07da2c99ebf 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}.
/// </summary>
- internal sealed class JsonNodeConverter : JsonConverter<object?>
+ internal sealed class JsonNodeConverter : JsonConverter<JsonNode?>
{
private static JsonNodeConverter? s_nodeConverter;
private static JsonArrayConverter? s_arrayConverter;
@@ -23,7 +23,7 @@ namespace System.Text.Json.Serialization.Converters
public static JsonObjectConverter ObjectConverter => s_objectConverter ??= new JsonObjectConverter();
public static JsonValueConverter ValueConverter => s_valueConverter ??= new JsonValueConverter();
- public override void Write(Utf8JsonWriter writer, object? value, JsonSerializerOptions options)
+ public override void Write(Utf8JsonWriter writer, JsonNode? value, JsonSerializerOptions options)
{
if (value == null)
{
@@ -47,7 +47,7 @@ namespace System.Text.Json.Serialization.Converters
}
}
- public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ public override JsonNode? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
switch (reader.TokenType)
{
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonObjectConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonObjectConverter.cs
index da3be52fde0..b25f544d3c9 100644
--- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonObjectConverter.cs
+++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonObjectConverter.cs
@@ -20,7 +20,7 @@ namespace System.Text.Json.Serialization.Converters
JsonSerializerOptions options,
ref ReadStack state)
{
- bool success = JsonNodeConverter.Instance.TryRead(ref reader, typeof(JsonNode), options, ref state, out object? value);
+ bool success = JsonNodeConverter.Instance.TryRead(ref reader, typeof(JsonNode), options, ref state, out JsonNode? value);
Debug.Assert(success); // Node converters are not resumable.
Debug.Assert(obj is JsonObject);
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/DynamicTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/DynamicTests.cs
deleted file mode 100644
index 63afb3920b0..00000000000
--- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/DynamicTests.cs
+++ /dev/null
@@ -1,282 +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.Collections.Generic;
-using System.Linq;
-using System.Text.Json.Serialization;
-using Microsoft.CSharp.RuntimeBinder;
-using Xunit;
-
-namespace System.Text.Json.Nodes.Tests
-{
- public static class DynamicTests
- {
- [Fact]
- public static void ImplicitOperators()
- {
- dynamic jObj = new JsonObject();
-
- // Dynamic objects do not support object initializers.
-
- // Primitives
- jObj.MyString = "Hello!";
- Assert.IsAssignableFrom<JsonValue>(jObj.MyString);
-
- jObj.MyNull = null;
- jObj.MyBoolean = false;
-
- // Nested array
- jObj.MyArray = new JsonArray(2, 3, 42);
-
- // Additional primitives
- jObj.MyInt = 43;
- jObj.MyDateTime = new DateTime(2020, 7, 8);
- jObj.MyGuid = new Guid("ed957609-cdfe-412f-88c1-02daca1b4f51");
-
- // Nested objects
- jObj.MyObject = new JsonObject();
- jObj.MyObject.MyString = "Hello!!";
-
- jObj.Child = new JsonObject();
- jObj.Child.ChildProp = 1;
-
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
-
- string json = jObj.ToJsonString(options);
- JsonTestHelper.AssertJsonEqual(JsonNodeTests.ExpectedDomJson, json);
- }
-
- private enum MyCustomEnum
- {
- Default = 0,
- FortyTwo = 42,
- Hello = 77
- }
-
- [Fact]
- public static void Primitives_UnknownTypeHandling()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
- options.Converters.Add(new JsonStringEnumConverter());
-
- dynamic obj = JsonSerializer.Deserialize<object>(Serialization.Tests.DynamicTests.Json, options);
- Assert.IsAssignableFrom<JsonObject>(obj);
-
- // JsonValue created from a JSON string.
- Assert.IsAssignableFrom<JsonValue>(obj.MyString);
- Assert.Equal("Hello", (string)obj.MyString);
-
- // Verify other string-based types.
- // Even though a custom converter was used, an explicit deserialize needs to be done.
- Assert.Equal(42, (int)obj.MyInt);
- Assert.ThrowsAny<RuntimeBinderException>(() => (MyCustomEnum)obj.MyInt);
- // Perform the explicit deserialize on the enum.
- Assert.Equal(MyCustomEnum.FortyTwo, JsonSerializer.Deserialize<MyCustomEnum>(obj.MyInt.ToJsonString()));
-
- Assert.Equal(Serialization.Tests.DynamicTests.MyDateTime, (DateTime)obj.MyDateTime);
- Assert.Equal(Serialization.Tests.DynamicTests.MyGuid, (Guid)obj.MyGuid);
-
- // JsonValue created from a JSON bool.
- Assert.IsAssignableFrom<JsonValue>(obj.MyBoolean);
- bool b = (bool)obj.MyBoolean;
- Assert.True(b);
-
- // Numbers must specify the type through a cast or assignment.
- Assert.IsAssignableFrom<JsonValue>(obj.MyInt);
- Assert.ThrowsAny<RuntimeBinderException>(() => obj.MyInt == 42L);
- Assert.Equal(42L, (long)obj.MyInt);
- Assert.Equal((byte)42, (byte)obj.MyInt);
-
- // Verify floating point.
- obj = JsonSerializer.Deserialize<object>("4.2", options);
- Assert.IsAssignableFrom<JsonValue>(obj);
-
- double dbl = (double)obj;
- Assert.Equal(4.2, dbl);
- }
-
- [Fact]
- public static void Array_UnknownTypeHandling()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
-
- dynamic obj = JsonSerializer.Deserialize<object>(Serialization.Tests.DynamicTests.Json, options);
- Assert.IsAssignableFrom<JsonObject>(obj);
- Assert.IsAssignableFrom<JsonArray>(obj.MyArray);
-
- Assert.Equal(2, obj.MyArray.Count);
- Assert.Equal(1, (int)obj.MyArray[0]);
- Assert.Equal(2, (int)obj.MyArray[1]);
-
- int count = 0;
- foreach (object value in obj.MyArray)
- {
- count++;
- }
- Assert.Equal(2, count);
- Assert.Equal(2, obj.MyArray.Count);
-
- obj.MyArray[0] = 10;
- Assert.IsAssignableFrom<JsonValue>(obj.MyArray[0]);
-
- Assert.Equal(10, (int)obj.MyArray[0]);
- }
-
- [Fact]
- public static void CreateDom_UnknownTypeHandling()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
-
- string GuidJson = $"{Serialization.Tests.DynamicTests.MyGuid.ToString("D")}";
-
- // We can't convert an unquoted string to a Guid
- dynamic dynamicString = JsonValue.Create(GuidJson);
- InvalidOperationException ex = Assert.Throws<InvalidOperationException>(() => (Guid)dynamicString);
- // "A value of type 'System.String' cannot be converted to a 'System.Guid'."
- Assert.Contains(typeof(string).ToString(), ex.Message);
- Assert.Contains(typeof(Guid).ToString(), ex.Message);
-
- string json;
-
- // Number (JsonElement)
- using (JsonDocument doc = JsonDocument.Parse($"{decimal.MaxValue}"))
- {
- dynamic dynamicNumber = JsonValue.Create(doc.RootElement);
- Assert.Equal(decimal.MaxValue, (decimal)dynamicNumber);
- json = dynamicNumber.ToJsonString(options);
- Assert.Equal(decimal.MaxValue.ToString(), json);
- }
-
- // Boolean
- dynamic dynamicBool = JsonValue.Create(true);
- Assert.True((bool)dynamicBool);
- json = dynamicBool.ToJsonString(options);
- Assert.Equal("true", json);
-
- // Array
- dynamic arr = new JsonArray();
- arr.Add(1);
- arr.Add(2);
- json = arr.ToJsonString(options);
- Assert.Equal("[1,2]", json);
-
- // Object
- dynamic dynamicObject = new JsonObject();
- dynamicObject.One = 1;
- dynamicObject.Two = 2;
-
- json = dynamicObject.ToJsonString(options);
- JsonTestHelper.AssertJsonEqual("{\"One\":1,\"Two\":2}", json);
- }
-
- /// <summary>
- /// Use a mutable DOM with the 'dynamic' keyword.
- /// </summary>
- [Fact]
- public static void UnknownTypeHandling_Object()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
-
- dynamic obj = JsonSerializer.Deserialize<object>(Serialization.Tests.DynamicTests.Json, options);
- Assert.IsAssignableFrom<JsonObject>(obj);
-
- // Change some primitives.
- obj.MyString = "Hello!";
- obj.MyBoolean = false;
- obj.MyInt = 43;
-
- // Add nested objects.
- // Use JsonObject; ExpandoObject should not be used since it doesn't have the same semantics including
- // null handling and case-sensitivity that respects JsonSerializerOptions.PropertyNameCaseInsensitive.
- dynamic myObject = new JsonObject();
- myObject.MyString = "Hello!!";
- obj.MyObject = myObject;
-
- dynamic child = new JsonObject();
- child.ChildProp = 1;
- obj.Child = child;
-
- // Modify number elements.
- dynamic arr = obj.MyArray;
- arr[0] = (int)arr[0] + 1;
- arr[1] = (int)arr[1] + 1;
-
- // Add an element.
- arr.Add(42);
-
- string json = obj.ToJsonString(options);
- JsonTestHelper.AssertJsonEqual(JsonNodeTests.ExpectedDomJson, json);
- }
-
- [Fact]
- public static void ConvertJsonArrayToIListOfJsonNode()
- {
- dynamic obj = JsonSerializer.Deserialize<JsonArray>("[42]");
- Assert.Equal(42, (int)obj[0]);
-
- IList<JsonNode> ilist = obj;
- Assert.NotNull(ilist);
- Assert.Equal(42, (int)ilist[0]);
- }
-
- [Fact]
- public static void UnknownTypeHandling_CaseSensitivity()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
- dynamic obj = JsonSerializer.Deserialize<object>("{\"MyProperty\":42}", options);
-
- Assert.IsType<JsonObject>(obj);
- Assert.IsAssignableFrom<JsonValue>(obj.MyProperty);
-
- Assert.Equal(42, (int)obj.MyProperty);
- Assert.Null(obj.myProperty);
- Assert.Null(obj.MYPROPERTY);
-
- options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
- options.PropertyNameCaseInsensitive = true;
- obj = JsonSerializer.Deserialize<object>("{\"MyProperty\":42}", options);
-
- Assert.Equal(42, (int)obj.MyProperty);
- Assert.Equal(42, (int)obj.myproperty);
- Assert.Equal(42, (int)obj.MYPROPERTY);
- }
-
- [Fact]
- public static void MissingProperty_UnknownTypeHandling()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
- dynamic obj = JsonSerializer.Deserialize<object>("{}", options);
- Assert.Equal(null, obj.NonExistingProperty);
- }
-
- [Fact]
- public static void Linq_UnknownTypeHandling()
- {
- var options = new JsonSerializerOptions();
- options.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
-
- IEnumerable<dynamic> allOrders = JsonSerializer.Deserialize<IEnumerable<dynamic>>(JsonNodeTests.Linq_Query_Json, options);
- IEnumerable<dynamic> orders = allOrders.Where(o => ((string)o.Customer.City) == "Fargo");
-
- Assert.Equal(2, orders.Count());
- Assert.Equal(100, (int)orders.ElementAt(0).OrderId);
- Assert.Equal(300, (int)orders.ElementAt(1).OrderId);
- Assert.Equal("Customer1", (string)orders.ElementAt(0).Customer.Name);
- Assert.Equal("Customer3", (string)orders.ElementAt(1).Customer.Name);
-
- // Verify methods can be called as well.
- Assert.Equal(100, orders.ElementAt(0).OrderId.GetValue<int>());
- Assert.Equal(300, orders.ElementAt(1).OrderId.GetValue<int>());
- Assert.Equal("Customer1", orders.ElementAt(0).Customer.Name.GetValue<string>());
- Assert.Equal("Customer3", orders.ElementAt(1).Customer.Name.GetValue<string>());
- }
- }
-}
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs
index b451ff0bc22..e5b1c18cf57 100644
--- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs
+++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/JsonArrayTests.cs
@@ -197,6 +197,48 @@ namespace System.Text.Json.Nodes.Tests
}
[Fact]
+ public static void ConvertJSONArrayToIListOfJsonNode()
+ {
+ dynamic obj = JsonSerializer.Deserialize<JsonArray>("[42]");
+ Assert.Equal(42, (int)obj[0]);
+
+ IList<JsonNode> ilist = obj;
+ Assert.NotNull(ilist);
+ Assert.Equal(42, (int)ilist[0]);
+ }
+
+ [Fact]
+ public static void ConvertJSONArrayToJsonArray()
+ {
+ JsonArray nodes = JsonSerializer.Deserialize<JsonArray>("[1,1.1,\"Hello\"]");
+ Assert.Equal(1, (long)nodes[0]);
+ Assert.Equal(1.1, (double)nodes[1]);
+ Assert.Equal("Hello", (string)nodes[2]);
+ }
+
+ [Fact]
+ public static void ConvertJSONArrayToJsonNodeArray()
+ {
+ // Instead of JsonArray, use array of JsonNodes
+ JsonNode[] nodes = JsonSerializer.Deserialize<JsonNode[]>("[1,1.1,\"Hello\"]");
+ Assert.Equal(1, (long)nodes[0]);
+ Assert.Equal(1.1, (double)nodes[1]);
+ Assert.Equal("Hello", (string)nodes[2]);
+ }
+
+ [Fact]
+ public static void ConvertJSONArrayToObjectArray()
+ {
+ // Instead of JsonArray, use array of objects
+ JsonSerializerOptions options = new();
+ options.UnknownTypeHandling = Serialization.JsonUnknownTypeHandling.JsonNode;
+ object[] nodes = JsonSerializer.Deserialize<object[]>("[1,1.1,\"Hello\"]", options);
+ Assert.Equal(1, (long)(JsonNode)nodes[0]);
+ Assert.Equal(1.1, (double)(JsonNode)nodes[1]);
+ Assert.Equal("Hello", (string)(JsonNode)nodes[2]);
+ }
+
+ [Fact]
public static void ReAddSameNode_Throws()
{
var jValue = JsonValue.Create(1);
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 41a5ec38d5a..20d919ca164 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
@@ -53,7 +53,6 @@
<Compile Include="JsonEncodedTextTests.cs" />
<Compile Include="JsonGuidTestData.cs" />
<Compile Include="JsonNode\Common.cs" />
- <Compile Include="JsonNode\DynamicTests.cs" />
<Compile Include="JsonNode\JsonArrayTests.cs" />
<Compile Include="JsonNode\JsonNodeTests.cs" />
<Compile Include="JsonNode\JsonNodeOperatorTests.cs" />
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/Collections/StackOfT.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/Collections/StackOfT.cs
index 48435095e57..c408c57cf90 100644
--- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/Collections/StackOfT.cs
+++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/TrimmingTests/Collections/StackOfT.cs
@@ -13,12 +13,14 @@ namespace SerializerTrimmingTest
{
static int Main(string[] args)
{
- string json = "[1]";
- object obj = JsonSerializer.Deserialize(json, typeof(Stack<int>));
- if (!(TestHelper.AssertCollectionAndSerialize<Stack<int>>(obj, json)))
- {
- return -1;
- }
+ // Test is currently disabled until issue #53393 is addressed.
+
+ //string json = "[1]";
+ //object obj = JsonSerializer.Deserialize(json, typeof(Stack<int>));
+ //if (!(TestHelper.AssertCollectionAndSerialize<Stack<int>>(obj, json)))
+ //{
+ // return -1;
+ //}
return 100;
}