The Wayback Machine - https://web.archive.org/web/20220201184842/https://github.com/dotnet/aspnetcore/issues/39918
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cachedFunction of JSInterop causes memory leaks #39918

Open
1 task done
Inkeliz opened this issue Feb 1, 2022 · 0 comments
Open
1 task done

cachedFunction of JSInterop causes memory leaks #39918

Inkeliz opened this issue Feb 1, 2022 · 0 comments

Comments

@Inkeliz
Copy link

@Inkeliz Inkeliz commented Feb 1, 2022

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Using .NET 6 with JSInterop.InvokeVoidAsync, may cause memory leak, since the cacheFunction maps (on JS-side of JSInterop) isn't covered by garbage-collector.

I don't use C# nor .NET 6. I'm just exploring how C# runtime calls JS functions.


The function documentation describes:

/// <summary>
/// Invokes the specified JavaScript function asynchronously.
/// </summary>
/// <param name="jsRuntime">The <see cref="IJSRuntime"/>.</param>
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>window.someScope.someFunction</c>.</param>
/// <param name="args">JSON-serializable arguments.</param>
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous invocation operation.</returns>

Given that "someScope.someFunction" is a valid function. We can also consider that someScope could be one map (such as new Map()), in that case each index the internal cacheFunction will also cached:

class JSObject {
_cachedFunctions: Map<string, Function>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(private _jsObject: any) {
this._cachedFunctions = new Map<string, Function>();
}
public findFunction(identifier: string) {
const cachedFunction = this._cachedFunctions.get(identifier);
if (cachedFunction) {
return cachedFunction;
}

Expected Behavior

It should not cause memory leak, and not implicit cache, or must be covered by GC somehow.

Or, otherwise, that behavior must be documented. It must inform that JsRuntime.InvokeVoidAsync caches the argument values, and that isn't suppose to be used for accessing mutable methods and maps (or anything that implements get directly). _Consider the code below as example, since it acts like a "function-table" that always return a valid value. That code is valid and a valid JS, and works. It also works currently, but causes memory leaks due to .NET 6 implementation.

Steps To Reproduce

If we consider such function in Javascript:

window.keyToFunc = new Proxy([], {
    get: function (_, k, _) {
        return function () { /* no-op example */};
    },
    has: function (_, _) {
        return true;
    }
})

If we call it using the following C# code:

Random rnd = new Random();
byte[] b = new byte[32 * 1024];

for (int i = 0; i < 10_000; i++) {
    rnd.NextBytes(b);
    await JsRuntime.InvokeVoidAsync("keyToFunc." + Convert.ToBase64String(b));
}

It would cause a huge memory leak on JS-side of JSInterop. Since it would cache each Convert.ToBase64String(b) value into the _cachedFunctions. The values from _cachedFunctions is never cleared by .NET/C#.

Exceptions (if any)

No response

.NET Version

6.0.101

Anything else?

dotnet --info
SDK do .NET (refletindo qualquer global.json):
 Version:   6.0.101
 Commit:    ef49f6213a

Ambiente de runtime:
 OS Name:     Windows
 OS Version:  10.0.19044
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\6.0.101\

Host (useful for support):
  Version: 6.0.1
  Commit:  3a25a7f1cc

.NET SDKs installed:
  3.1.410 [C:\Program Files\dotnet\sdk]
  5.0.100 [C:\Program Files\dotnet\sdk]
  5.0.104 [C:\Program Files\dotnet\sdk]
  6.0.101 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.All 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 6.0.1 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.23 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 6.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 3.1.9 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 3.1.16 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.4 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 5.0.7 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
  Microsoft.WindowsDesktop.App 6.0.1 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant