Fully annotate JsonNode for trimmability#53184
Conversation
|
Tagging subscribers to this area: @eiriktsarpalis, @layomia Issue DetailsFollow up to #52934.
Contributes to #45623
|
|
Note regarding the This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change. |
|
@steveharter - thoughts on this change? (Note: The runtime-staging builds appear to be broken due to infra issues.) |
Follow up to dotnet#52934. - Using JsonNode in dynamic statements is not trim compatible. Add a LibraryBuild warning since there isn't a direct API to put the warning on. - Mark JsonValueNotTrimmable's ctor as unsafe - Fix up a few warning messages - minor doc fixup Contributes to dotnet#45623
| /// The object to be added to the end of the <see cref="JsonArray"/>. | ||
| /// </param> | ||
| [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)] | ||
| [RequiresUnreferencedCode(JsonValue.CreateUnreferencedCodeMessage)] |
There was a problem hiding this comment.
Due to trimming this was discussed as a method that we may want to remove, and require usage of the IList<T>.Add<T>(T value) implementation. However since that requires an extra call to JsonValue.Create(), it affects usability.
Have there been other non-JSON areas that we've discouraged API use from in this manner in favor of forcing or encouraging a trimmable API?
There was a problem hiding this comment.
Have there been other non-JSON areas that we've discouraged API use from in this manner in favor of forcing or encouraging a trimmable API?
Yes. A main difference between JSON and those APIs is that we are actively adding features to JSON, so that's why it seems JSON is trying to be "trim-compatible" from the start. And also because any API we've already shipped we can't change. But since we are defining these JSON APIs at the same time as making the BCL trimmable, we might as well at least consider it in the API design.
Other examples include:
- System.Linq.Expressions (ex. Preserving operator methods necessary for System.Linq.Expressions linker#1821 - see the full discussion, but the current recommended approach is to add a new overload that doesn't do the scanning for operator methods (which is the trim-incompatible issue)
TypeDescriptoris virtually allRequiresUnreferencedCode, because of its heavy use of Reflection.System.Data.Commonis getting a lot ofRequiresUnreferencedCodeattributes in Add trimmer annotations to System.Data.Common #52046
discouraged API use
Note though, this only matters if you care about trimmability and AOT'ing your code. If a developer is only concerned about the "current deployment models" of their code, they can easily use these APIs and their code will work. They only get warnings once they attempt to trim unused code away.
| <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> |
There was a problem hiding this comment.
Does usage of dynamic itself causes a warning (without STJ)?
There was a problem hiding this comment.
Yes. We marked basically all APIs in Microsoft.CSharp as RequiresUnreferencedCode.
runtime/src/libraries/Microsoft.CSharp/ref/Microsoft.CSharp.cs
Lines 10 to 34 in ffb095a
However, I didn't want to rely on those warnings here, because someone could cast a JsonNode to IDynamicMetaObjectProvider and call GetMetaObject on it, and thus travelling down the path to creating a JsonValueNotTrimmable object.
Follow up to #52934.
Contributes to #45623