question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JSRuntime.Invoke APIs aren't correctly annotated for trimming

See original GitHub issue

Follow up to https://github.com/dotnet/aspnetcore/pull/39838. JSRuntime’s API (excluding the unmarshalled ones) use JSON serialization to serialize the args array and as such are subject to being trimmed away. S.T.Js API for its serialization are annotated with RequiresUnreferencedCode with a recommendation to use the source-generator based overload to avoid this.

Blazor’s APIs suppress STJ’s warnings (since it happens deep in its bowels) and don’t have a trimmer safe alternative. Perhaps one option is to annotate all of the JSRuntime APIs with RequiresUnferencedCode and add an JSRuntime.InvokeAsync overload that accepts exactly one argument a JsonTypeInfo to go with it. Something like so:

TValue IJSRuntime.InvokeAsync<TArg, TValue>(string method, TArg arg, JsonTypeInfo<TArg> t1,  JsonTypeInfo<TValue> t2, CancellationToken cancellationToken)

At the very least, we could require that all code in the framework uses this API for it’s interop.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:9 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
pavelsavaracommented, Nov 9, 2022

@pavelsavara would this still be applicable once we update to using the new JS interop with [JSImportAttribute] to make it CSP friendly?

#37787 (comment)

Yes, those are separate problems. Solving internal client side interop will fix CSP of Blazor as a framework. This is problem with IJSRuntime which will not go away by solving CSP.

If users adopted new runtime interop with JSImportAttribute instead of IJSRuntime it would help. But JSImportAttribute is not available on server side (hybrid Blazor), so it’s not complete solution.

Adding new trimming friendly signatures to the IJSRuntime is way to go. And maybe marking the old signatures obsolete ?

I think that implementing Roslyn code analyzer to hint or force users to pass JsonTypeInfo or JsonSerializerContext would be good.

1reaction
yugabecommented, Nov 2, 2022

I wanted to file a similar issue, as I essentially wanted to advise something very close to the one outlined here.

  1. The IJSRuntime is incorrectly annotated for linking. The IJSRuntime.InvokeAsync methods need the [RequiresUnreferencedCode] attribute applied, as the IJSInProcessRuntime already does on the Invoke method.

  1. I think there could easily be overloads which don’t break trimming if the arguments passed are typed instead of objects.
public interface IJSRuntime
{
    // Existing signature, but this should also have [RequiresUnreferencedCode] as the "args" are dynamically referenced.
    ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, object?[]? args);

    // Added overloads, with default implementation, doesn't break trimming (probably can use [UnconditionalSuppressMessage] or similar).
    ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TValue>(string identifier) => InvokeAsync<TValue>(identifier, null);
    ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue, [DynamicallyAccessedMembers(JsonSerialized)] TArg>(string identifier, TArg argument) => InvokeAsync<TValue>(identifier, new object?[] { argument });
    // And so on, for multiple arguments with <TArg1, TArg2>, up until maybe 3 or 4?

  1. Additionally, I am not sure there exists sufficient documentation regarding how the trimming warnings should be fixed in these cases. As IJSRuntime is not correctly annotated, I guess people expect it to just work, but it will fail if the argument types aren’t preserved. The question then (after fixing the annotations) becomes how to actually fix these issues in code, as [RequiresUnreferencedCode] will mitigate it to the caller (still the user) and [UnconditionalSuppressMessage] will just suppress it, but neither will actually solve the problem of actually keeping the correct types in the assemblies (although my point no. 2 above could solve that problem).

I hope @guardrex won’t mind me pinging.


  1. For 100% accuracy, I think a return type should correctly have DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties, as it is defined in https://github.com/dotnet/aspnetcore/blob/main/src/Shared/LinkerFlags.cs as JsonSerialized. But in fact, serialization requires only DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicProperties (reading them, so only the get accessors), and only deserialization (so, return types) requires DynamicallyAccessedMemberTypes.PublicConstructors as well (and writing the properties, so set accessors).

This probably doesn’t make too much difference in most cases, but it might trim out some unused public constructors, leaving us with a smaller assembly size in the end.

Read more comments on GitHub >

github_iconTop Results From Across the Web

VS Code API | Visual Studio Code Extension API
VS Code API is a set of JavaScript APIs that you can invoke in your Visual Studio Code extension. This page lists all...
Read more >
Fix list for Rational Application Developer for WebSphere ...
This document contains a complete listing of releases, refreshes, fix packs and interim fixes sorted by version for IBM Rational Application Developer for ......
Read more >
Mediapipe Holistic is one of the pipelines which contains ...
This approach may sacrifice performance when you need to call multiple APIs in a loop, but it gives you the flexibility to use...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found