aspnetcore: [dotnet-sdk-8.0.100-rc.2.23451.1] SPOTClient reported Telerik.UI.for.Blazor package error on the login page.
Is there an existing issue for this?
- I have searched the existing issues
Describe the bug
When run the 3rd party application SPOTClient with the latest .NET 8 build, it failed on login page with Telerik.UI.for.Blazor package error.
Application Name: SPOTClient OS: Windows 10 21H2 CPU: X64 .NET Build Number: dotnet-sdk-8.0.100-rc.2.23451.1 App, App Source and Repro environment checking at: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1881082
Verify Scenarios: 1). Windows 10 21H2 AMD64 + dotnet-sdk-8.0.100-rc.2.23451.1: Fail 2). Windows 10 21H2 AMD64 + dotnet-sdk-8.0.100-rc.1.23423.3: Pass 3). Windows 10 21H2 AMD64 + dotnet-sdk-6.0.414-win-x64: Pass
Expected Behavior
launch successful.
Steps To Reproduce
Minimal repro steps:
Please refer to the demo attached BlazorApp1.zip
- Create Blazor Server App project(.net7.0)
- Install the nuget package :
telerik.ui.for.blazor - Add this code to _Host.cshtml
<script src="_content/Telerik.UI.for.Blazor/js/telerik-blazor.js" defer></script> - Add this code to Index.razor
<div class="mb-3">
<Telerik.Blazor.Components.TelerikTextBox Id="@ID" Value="@Values" Label="@Labels" PlaceHolder="Enter your connected email address"></Telerik.Blazor.Components.TelerikTextBox>
</div>
@code
{
string Values = "Values", Labels = "Labels", ID = "1";
}
- Build and publish and run it with .net8 runtime
- Go to : http://localhost:5000/
App repro steps on repro machine: 1.Execute “cd C:\SPOTClient\App\SPOTClient” in cmd. 2.Execute “dotnet SPOT.Platform.Client.Host.dll” in cmd. 3.Launch Server url: https://localhost:5005
Exceptions (if any)
launch failed with below error:
blazor.server.js:1 [2023-09-05T08:32:55.677Z] Error: Microsoft.JSInterop.JSException: Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
at Function.assign (<anonymous>)
at e.extend (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9184)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9537)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at t (https://localhost:5005/_content/Telerik.UI.for.Blazor/js/telerik-blazor.js:1:9523)
at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
at Telerik.Blazor.Components.Common.TextBoxBase.InitJsComponentAsync()
at Telerik.Blazor.Components.Common.TextBoxBase.OnAfterRenderInternalAsync(Boolean firstRender)
at Telerik.Blazor.Components.Common.TextBoxBase.OnAfterRenderAsync(Boolean firstRender)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
.NET Version
8.0.100-rc.2.23451.1
Anything else?
dotnet info:
.NET SDK:
Version: 8.0.100-rc.2.23451.1
Commit: dabc29073d
Runtime Environment:
OS Name: Windows
OS Version: 10.0.22000
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.100-rc.2.23451.1\
.NET workloads installed:
There are no installed workloads to display.
Host:
Version: 8.0.0-rc.2.23431.9
Architecture: x64
Commit: 3c48925a6c
RID: win-x64
.NET SDKs installed:
8.0.100-rc.2.23451.1 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.0-rc.2.23431.20 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 8.0.0-rc.2.23431.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 8.0.0-rc.2.23430.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
None
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
About this issue
- Original URL
- State: closed
- Created 10 months ago
- Comments: 15 (8 by maintainers)
Hi all,
My name is Stamo Gochev and I am one of the developers working on the Telerik UI for Blazor product.
I want to inform you that we are investigating the issue. Once we have more details, we will share our findings. If you have any further feedback or questions about the case, please reach out to us by opening a Telerik support ticket.
@SteveSandersonMS You can close the current issue as it is not related to the Blazor framework.
I’ve been trying to investigate, which is tricky, because this issue happens inside
telerik-blazor.jswhich is not included in the repro sources, and the only publicly available versions of it are minified.However I do think I can see what’s going on.
telerik-blazor.jstries to do something similar to:… where
options1andoptions2are both JavaScript objects that have a property calleddotNetInstanceof typeDotNetObject. ThedeepExtendlogic presumably walks all the properties ofoptions2recursively to apply them tooptions1.In effect this means writing to the internals of a
DotNetObjectinstance, which is definitely not supported. In .NET 7 and before, this happened to work, because both of thedotNetInstanceobjects happened to have the same_idvalue and no other properties. But in .NET 8,DotNetObjectalso has a new property_callDispatcherof typeCallDispatcher, which on Blazor Server is actually theCircuitManager. This references a very wide range of things, and in particular, has a reference cycle so that if you naively try to walk its properties recursively, you’ll get stuck in an infinite loop evaluating:Fixing this
Developers and component library authors shouldn’t be making the assumption that
DotNetObjectinstances are safe to mutate internally (they are opaque handles, and mutating their internals is like private reflection or unsafe code in C#), nor should they assume it’s possible to walk their properties recursively (again, it’s exactly equivalent to using private reflection in C# to walk everything reachable from some framework primitive likeGCHandle). It only worked by chance in earlier versions.So, the best fix would be inside
telerik-blazor.js, changing it to stop doing an infinite property traversal or any mutations onDotNetObjectinstances.Stopping the problem more generally
Blazor could be more defensive about this. For example, we could change
DotNetObject(inMicrosoft.JSInterop.ts) so that its properties are not enumerable or at least have symbol names. As per the traversal rules, the options include:for (let propName in obj). That’s whattelerik-blazor.jsis doing to enumerate the properties.getOwnPropertyNames/getOwnPropertySymbols)_callDispatcherhas a symbol name and is defined only on the prototype chain. That would give very high robustness against accidental discovery but is quite complex as we’d have to go outside the help that TypeScript offers natively for objects and inheritance_callDispatcheronDotNetObject, replace it with a numeric ID into aMap<number, CallDispatcher>. Then it would be exactly equivalent to what we had before in terms of behavior when enumerating or assigning properties (for good or ill).If we did this, I don’t know if
telerik-blazor.jswould start working. My guess is it probably would, at least in the common case where you only have either Server or WebAssembly in your app at a single time. If you have both platforms at once, or switch from one to the other, then it may be buggy since it appears to make the assumption it’s allowed to track a singleDotNetObjectthat refers to .NET as a whole. I can’t confirm either way since I don’t have access to its sources or design documents etc.If we had to work around it in Blazor (but hopefully it will be fixed inside telerik-blazor.js instead)
While I’m motivated to stop the property from appearing in enumeration (likely by just using a symbol name), the more risk-averse solution is replacing the new property with an ID, i.e., the fourth option on the set above.
Note that
Virtualize.tsuses a hack to access the_idand_callDispatcherproperties directly across library boundaries. No matter which option we choose, we would also have to do something else to make that continue to work. For example if we use symbol-named properties, we could expose the property name symbols intentionally fromMicrosoft.JSInterop, or expose a helper function that can supply the values of those properties. Not sure what reaction will be necessary if we replace the instance with a numeric ID.Thanks @Stamo-Gochev. Closing this as
externalat this point, given no action is pending from our end.A quick update on this - we have a bug fix for the reported problem - if you are a Telerik customer and would like to test the fix, please open a Telerik support ticket and our team will help you.
@SteveSandersonMS We tried it with latest Telerik version, it is also reproduced. Here is the repro for your reference. BlazorApp_Telerik4.zip
Update the minimal repro steps as following:
@Junjun-zhao will be able to try using the latest Telerik version 4.5.0 tonight (team is based in China) and report back.
Yes, it seems to have worked in RC1 based on the following at the top of the issue: Verify Scenarios: 1). Windows 10 21H2 AMD64 + dotnet-sdk-8.0.100-rc.2.23451.1: Fail 2). Windows 10 21H2 AMD64 + dotnet-sdk-8.0.100-rc.1.23423.3: Pass 3). Windows 10 21H2 AMD64 + dotnet-sdk-6.0.414-win-x64: **Pass**