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

"Assertion failed - heap is currently locked" when an element is focused out #26809

Closed
Stamo-Gochev opened this issue Oct 12, 2020 · 3 comments
Closed
Assignees
Labels
area-blazor Includes: Blazor, Razor Components ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved
Milestone

Comments

@Stamo-Gochev
Copy link

Stamo-Gochev commented Oct 12, 2020

Describe the bug

An error is thrown when an element is focused out and removed from the DOM in a blazor wasm app in .NET 5.0 RC1:

Error: Assertion failed - heap is currently locked

This seems to be a regression from the 3.1 version (see below) as the same configuration works without throwing an error.

To Reproduce

  1. Clone the https://github.com/Stamo-Gochev/blazor-net5-wasm-focusout repository
  2. Set the TestNet5Wasm.Server as a startup project.
  3. Run the app (Ctrl + F5)
  4. On the Index.razor page, click on item 1

Note: The main logic is part of the Index.razor page only and the script.js file.

Expected:

No error is thrown

Actual:

An error is thrown

Uncaught (in promise) Error: Assertion failed - heap is currently locked
at y (blazor.webassembly.js:1)
at Object.beginInvokeDotNetFromJS (blazor.webassembly.js:1)

Using a @onfocusout handler does not solve the issue (click on item 2 to reproduce) as it rhows with another error:

Error: System.ArgumentException: There is no event handler associated with this event. EventId: '3'. (Parameter 'eventHandlerId'

IMPORTANT: The issue is not reproducible with the 3.1 version - use the same steps to reproduce as the above with the TestNet31Wasm app.

Exceptions (if any)

An error is thrown

Uncaught (in promise) Error: Assertion failed - heap is currently locked
at y (blazor.webassembly.js:1)
at Object.beginInvokeDotNetFromJS (blazor.webassembly.js:1)

Further technical details

  • ASP.NET Core version 5.0 RC1
  • Include the output of dotnet --info - Microsoft.NETCore.App 5.0.0-rc.1.20451.14
  • The IDE (VS / VS Code/ VS4Mac) you're running on, and it's version

Additional context

Might be connected to #23773 judging from the error message.

@pranavkm pranavkm added the area-blazor Includes: Blazor, Razor Components label Oct 12, 2020
@mkArtakMSFT mkArtakMSFT added this to the 5.0.0 milestone Oct 12, 2020
@SteveSandersonMS
Copy link
Member

What's happening here is that your JS code is trying to call back into .NET during the middle of applying a renderbatch to the DOM. This isn't safe to do, because if .NET code runs at this time, it might modify the contents of .NET memory and invalidate the renderbatch that's still being processed.

This was always dangerous and wrong to do in 3.2.0, but there wasn't anything checking to stop it. For safety, we've added a check in 5.0 to make sure it's not happening.

To avoid this problem, when performing JS interop calls during events like onfocusout that can occur while applying a renderbatch, be sure to defer the call. For example, update your code as follows:

    window.document.addEventListener("focusout", function (e) {
        console.log("focus out: " + new Date());

        if (e.target.classList.contains("list-item-1")) {
            setTimeout(invokeFocusOut, 0);
        }
    });

If this becomes a common source of confusion, we might choose to change the JS interop implementation so that async calls are automatically deferred while renderbatches are being applied (whereas synchronous calls would still have to throw). However this is the first time anyone's reported it so it might be that we don't need to implement special handling for it in the framework.

Hope that makes sense!

@SteveSandersonMS SteveSandersonMS added ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. and removed investigate labels Oct 13, 2020
@ghost ghost added the Status: Resolved label Oct 13, 2020
@Stamo-Gochev
Copy link
Author

Thanks for the clarifications @SteveSandersonMS

If this becomes a common source of confusion, we might choose to change the JS interop implementation so that async calls are automatically deferred while renderbatches are being applied (whereas synchronous calls would still have to throw). However this is the first time anyone's reported it so it might be that we don't need to implement special handling for it in the framework.

The main reason for the "workaround" (attaching a JS "focusout" handler and making a JS interop call to a C# method instead of using @onfocusout on the element) is due to problems with #26838 and that the component should work without errors in both server-side blazor and wasm.

Is it expected for the code to work if the handler is attached like:

<li @onfocusout="@OnItemFocusOut">item 2</li>

and #26838 is eventually fixed? This will be enough and actually remove the need for making async calls to be automatically deferred while renderbatches are processed.

@SteveSandersonMS
Copy link
Member

and #26838 is eventually fixed?

Yes, we definitely want to fix #26838. It's not specifically planned for inclusion in .NET 5, because .NET 5 is basically finished now, and we have had very few customer reports of it. But yes we do want to fix it when we can. I did some investigation into it today and found it was a bit complicated and wrote up some thoughts on #26838 itself.

@ghost ghost locked as resolved and limited conversation to collaborators Nov 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Includes: Blazor, Razor Components ✔️ Resolution: Answered Resolved because the question asked by the original author has been answered. Status: Resolved
Projects
None yet
Development

No branches or pull requests

4 participants