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

"There is no event handler associated with this event" when an element is focused out #26838

Closed
Stamo-Gochev opened this issue Oct 13, 2020 · 21 comments · Fixed by #31612
Closed
Assignees
Labels
affected-medium This issue impacts approximately half of our customers area-blazor Includes: Blazor, Razor Components bug This issue describes a behavior which is not expected - a bug. Done This issue has been fixed feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly severity-major This label is used by an internal tool
Milestone

Comments

@Stamo-Gochev
Copy link

Stamo-Gochev commented Oct 13, 2020

Describe the bug

An error is thrown:

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

when an element with focusout handler is removed from the DOM in a blazor wasm app (both 3.1 and 5.0).

To Reproduce

  1. Clone the https://github.com/Stamo-Gochev/blazor-net5-wasm-focusout repository
  2. Set the TestNet5Wasm.Server as a startup project.

Note: In order to test the 3.1 version of wasm, use the TestNet31Wasm.Server

  1. Run the app (Ctrl + F5)
  2. On the Index.razor page, click on item 2 that has @onfocusout handler

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

Exceptions (if any)

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

Further technical details

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

Additional context

A similar problem is marked to be fixed in multiple cases like:
#17926
#21241
#21366
#21874 (comment)

but the problem is still reproducible in both the 3.1 and 5.0 versions.

@mkArtakMSFT mkArtakMSFT added area-blazor Includes: Blazor, Razor Components feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly labels Oct 13, 2020
@captainsafia captainsafia added this to the Next sprint planning milestone Oct 13, 2020
@ghost
Copy link

ghost commented Oct 13, 2020

Thanks for contacting us.
We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

@SteveSandersonMS SteveSandersonMS added affected-medium This issue impacts approximately half of our customers bug This issue describes a behavior which is not expected - a bug. severity-major This label is used by an internal tool labels Oct 14, 2020 — with ASP.NET Core Issue Ranking
@SteveSandersonMS
Copy link
Member

SteveSandersonMS commented Oct 15, 2020

I did some investigation on this today, and confirmed it is a current bug. The repro can be simplified to:

@if (showButtonThatDisappearsWhenClicked)
{
    <button @onfocusout="HandleFocusOut" @onclick="HandleClick">Click me</button>
}

@code {
    bool showButtonThatDisappearsWhenClicked = true;

    void HandleClick()
    {
        Console.WriteLine("click");
        showButtonThatDisappearsWhenClicked = false;
    }

    void HandleFocusOut()
    {
        Console.WriteLine("focusout");
    }
}

This works OK on Blazor Server but throws on Blazor WebAssembly. On wasm, the sequence of events is:

  • JS: Notify click event

    • .NET: Track that an event handler is in progress
    • .NET: Notify new renderbatch, which includes removing element and disposing the focusout event handler
    • JS: Lock the heap
    • JS: Upon removing element from DOM, 'focusout' JS event fires, so wants to notify 'focusout' to .NET
      • JS: Can't issue notification synchronously because heap is locked. Defer it.
    • JS: Finish applying renderbatch and unlock heap, synchronously processing deferred calls
      • JS: Now we can dispatch the notification for 'focusout' to .NET [*]
      • .NET: I'm already handling an event, so defer this until later
    • JS: Notify .NET that renderbatch finished being applied
      • .NET: Release the event 'focusout' handler
      • .NET: Track that event handling is finished and we're ready for more events
  • Next clock tick:

    • .NET: OK I'm ready to run the deferred event handler from earlier
      • .NET: That event handler was already released - CRASH

Possible resolution:

  • When JS is trying to dispatch and event but has to defer it [*], check the event handler is still known
    inside the deferral callback, not outside it (as we do today). Then in this case we'd never dispatch the 'focusout' event to .NET,
    so there'd be no exception, but also no call to the focusout handler.
    • But that's inconsistent with server behavior. The server would queue up the 'focusout' event notification and
      deliver it before the first 'batch complete' confirmation, and hence the 'focusout' event would fire.
    • To make Wasm consistent with server, we could change the .NET side code so that, when being notified that
      a renderbatch finished application, before releasing its event handlers we execute any deferred event notifications

@majorimi
Copy link

With .NET5 RC2 it seems to be working even with Blazor WebAssembly. Did not get any error. But VS 2019 Intelligense does not show this event handler only onfucus:

image

@SteveSandersonMS
Copy link
Member

@majorimi It's not clear to me that what you're posting here is the same thing as this issue. Instead of posting here, could you please file a new issue giving a clear description of what you're doing (since it's likely totally different)?

@majorimi
Copy link

@SteveSandersonMS: I was trying out @onfocusout event with a very similar code as your example above. Run it in a Blazor WebAssembly (not server side) project and I received the events without exceptions. So just confirmed bug was fixed...

Also my point was if this event is supported by Blazor and works perfectly, why Visual Studio 2019 Intelligense is not offering it when I'm typing focus keyword?
As you can see on that screenshot Intelligense has 1 result for @onfocus however it should match with 2 items: @onfocus and @onfocusout as well.

Sure lets post it to a new issue, however not sure if is it belongs to this repo or should be posted for VS team? Thanks.

@SteveSandersonMS
Copy link
Member

Sure lets post it to a new issue

Yes please, in this repo.

@RobertBouillon
Copy link

Just a note that this breaks data binding scenarios:

  1. User enters data into text field
  2. User navigates away, causing field to be destroyed by DOM
  3. Event fires, causing bug. User data is lost.

I haven't found a reliable workaround. Changing the bind:event to oninput works, but only when binding is appropriate for that event. A workaround for this would be great.

@Indrajith-Sync
Copy link

I am also facing the same script issue.

Any workarounds for resolving this ?

@SteveSandersonMS
Copy link
Member

@RobertBouillon @Indrajith-Sync If you could each post separate issues with your own minimal repro steps, we can figure out whether it’s the same issue or not. Thanks!

@Stamo-Gochev
Copy link
Author

@SteveSandersonMS Can you clarify if a potential fix will be backported to the 3.x branch or will it be part of the upcoming 5.0.1 release only? I need to support both 3.x and 5.0, so this information will be helpful to me beforehand.

@SteveSandersonMS
Copy link
Member

We don't have a decision about that yet, however as a caution, please note that 3.2.0 is not an LTS release and hence doesn't come with support beyond (I think) February 2021. Developers using Blazor WebAssembly should upgrade to 5.0 before February 2021.

@Stamo-Gochev
Copy link
Author

You are probably referring to the 6.0-preview1 milestone targeting February 10, 2021 for an end date for wasm 3.2.0, but are any fixes for wasm going to be part of any of the 3.1.x releases? As far as I understand, Blazor WebAssembly 3.2.0 is not considered to be connected with the 3.1 LTS (ending on December 3, 2022), but I cannot find any official statement about that, am I correct?

@SteveSandersonMS
Copy link
Member

You can find out more about support policy and roadmap at https://dotnet.microsoft.com/platform/support/policy/dotnet-core. You are correct that 3.2.x is not part of the 3.1.x LTS release (in fact, that's why we gave it the 3.2.0 version originally).

@PrinceOliver
Copy link

Can anyone confirm which release version, will this fix be included?

@RobertBouillon
Copy link

@SteveSandersonMS I've failed to create a minimal repro thus far. I've put a couple hours into it. Every simple scenario I create seems to work, so I've been unable to isolate the exact problem here. I can provide you with access to the repo, if you'd like, otherwise I'll try and take another stab at this sometime this month by stripping away functionality until the problem disappears, rather than trying to recreate something simple.

@JPtenBerge
Copy link

JPtenBerge commented Nov 29, 2020

@RobertBouillon @SteveSandersonMS I've run into this error and managed to reproduce it in the latest .NET 5 for Blazor WebAssembly with this bit of code:

@page "/my-error-page"

<h1>Reproduce error</h1>

Show input? @ShowInput

<button @onclick="ToggleInput">Toggle input</button>

@if (ShowInput)
{
	<input @onkeydown="HideIfEnter" @onblur="HandleBlur">
}
else
{
	<p>Not showing input</p>
}

@code {
	public bool ShowInput { get; set; } = true;

	public void ToggleInput()
	{
		ShowInput = !ShowInput;
	}

	public void HandleBlur()
	{
		Console.WriteLine("Blurring");
	}

	public void HideIfEnter(KeyboardEventArgs args)
	{
		if (args.Key == "Enter")
		{
			ShowInput = false;
		}
	}
}

Navigate to the page, then focus on the input field and hit the enter button.

The problem lies in the combination where I have a blur and a keydown event handler on an input field. The keydown event handler effectively removes the input field from the DOM, causing the blur event to -kinda- get triggered, but it can't find its associated element anymore.

Hope this helps.

@SteveSandersonMS
Copy link
Member

Thanks for the clarification. Yes, I believe this is a duplicate repro of this issue (#26838). It's in "Next spring planning" so we'll be evaluating it for a possible fix in 5.0.2.

@Stamo-Gochev
Copy link
Author

Stamo-Gochev commented Jan 25, 2021

@SteveSandersonMS
Is there any chance the priority of this issue is raised as it didn't make it to 5.0.2 and it is getting tedious to implement workarounds again and again?

@ghostinside
Copy link

just got recently

Uncaught (in promise) Error: Assertion failed - heap is currently locked at g (blazor.webassembly.js:1) at Object.beginInvokeDotNetFromJS (blazor.webassembly.js:1) at h (blazor.webassembly.js:1) at e.invokeMethodAsync (blazor.webassembly.js:1) at e.value (telerik-blazor.js:1) at e.value (telerik-blazor.js:46) at HTMLLIElement.i.onFocusOut (telerik-blazor.js:46) at e (blazor.webassembly.js:1) at Object.e [as removeLogicalChild] (blazor.webassembly.js:1) at e.applyEdits (blazor.webassembly.js:1) g @ blazor.webassembly.js:1 beginInvokeDotNetFromJS @ blazor.webassembly.js:1 h @ blazor.webassembly.js:1 e.invokeMethodAsync @ blazor.webassembly.js:1 value @ telerik-blazor.js:1 value @ telerik-blazor.js:46 i.onFocusOut @ telerik-blazor.js:46 e @ blazor.webassembly.js:1 e @ blazor.webassembly.js:1 e.applyEdits @ blazor.webassembly.js:1 e.updateComponent @ blazor.webassembly.js:1 t.renderBatch @ blazor.webassembly.js:1 window.Blazor._internal.renderBatch @ blazor.webassembly.js:1 w @ blazor.webassembly.js:1 _mono_wasm_invoke_js_blazor @ dotnet.5.0.3.js:1 wasm_invoke_iiiiii @ 00aba242:0xdda7f ves_pinvoke_method @ 00aba242:0xdfb62 interp_exec_method @ 00aba242:0x44c08 interp_runtime_invoke @ 00aba242:0x12efff mono_jit_runtime_invoke @ 00aba242:0x118e5f do_runtime_invoke @ 00aba242:0x79d42 mono_runtime_invoke_checked @ 00aba242:0xf65d mono_runtime_try_invoke_array @ 00aba242:0x10e831 ves_icall_InternalInvoke @ 00aba242:0xed492 ves_icall_InternalInvoke_raw @ 00aba242:0xecf57 do_icall @ 00aba242:0x194ddb do_icall_wrapper @ 00aba242:0x79df9 interp_exec_method @ 00aba242:0x44ad3 interp_runtime_invoke @ 00aba242:0x12efff mono_jit_runtime_invoke @ 00aba242:0x118e5f do_runtime_invoke @ 00aba242:0x79d42 mono_runtime_try_invoke @ 00aba242:0x12982 mono_runtime_invoke @ 00aba242:0x10ec2b mono_wasm_invoke_method @ 00aba242:0x108e48 Module._mono_wasm_invoke_method @ dotnet.5.0.3.js:1 call_method @ dotnet.5.0.3.js:1 (anonymous) @ dotnet.5.0.3.js:1 beginInvokeDotNetFromJS @ blazor.webassembly.js:1 h @ blazor.webassembly.js:1 e.invokeMethodAsync @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 r @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 (anonymous) @ blazor.webassembly.js:1 r @ blazor.webassembly.js:1 d @ blazor.webassembly.js:1 f @ blazor.webassembly.js:1 l @ blazor.webassembly.js:1 invokeJSFromDotNet @ blazor.webassembly.js:1 w @ blazor.webassembly.js:1 _mono_wasm_invoke_js_blazor @ dotnet.5.0.3.js:1 do_icall @ 00aba242:0x194e4e do_icall_wrapper @ 00aba242:0x79df9 interp_exec_method @ 00aba242:0x44ad3 interp_runtime_invoke @ 00aba242:0x12efff mono_jit_runtime_invoke @ 00aba242:0x118e5f do_runtime_invoke @ 00aba242:0x79d42 mono_runtime_invoke_checked @ 00aba242:0xf65d mono_runtime_try_invoke_array @ 00aba242:0x10e831 ves_icall_InternalInvoke @ 00aba242:0xed492 ves_icall_InternalInvoke_raw @ 00aba242:0xecf57 do_icall @ 00aba242:0x194ddb do_icall_wrapper @ 00aba242:0x79df9 interp_exec_method @ 00aba242:0x44ad3 interp_runtime_invoke @ 00aba242:0x12efff mono_jit_runtime_invoke @ 00aba242:0x118e5f do_runtime_invoke @ 00aba242:0x79d42 mono_runtime_try_invoke @ 00aba242:0x12982 mono_runtime_invoke @ 00aba242:0x10ec2b mono_wasm_invoke_method @ 00aba242:0x108e48 Module._mono_wasm_invoke_method @ dotnet.5.0.3.js:1 call_method @ dotnet.5.0.3.js:1 (anonymous) @ dotnet.5.0.3.js:1 beginInvokeDotNetFromJS @ blazor.webassembly.js:1 h @ blazor.webassembly.js:1 e.invokeMethodAsync @ blazor.webassembly.js:1 value @ telerik-blazor.js:1 value @ telerik-blazor.js:46 i.onClick @ telerik-blazor.js:46 Show 55 more frames

@ghostinside
Copy link

@Stamo-Gochev

@angelru
Copy link

angelru commented Mar 29, 2021

The same issue when i submit a form with enter key and then I navigate:

Uncaught (in promise) Error: System.ArgumentException: There is no event handler associated with this event. EventId: '711'. (Parameter 'eventHandlerId')
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.DispatchEventAsync(UInt64 eventHandlerId, EventFieldInfo fieldInfo, EventArgs eventArgs)
   at Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer.DispatchEventAsync(UInt64 eventHandlerId, EventFieldInfo eventFieldInfo, EventArgs eventArgs)
   at Microsoft.AspNetCore.Components.WebAssembly.Infrastructure.JSInteropMethods.DispatchEvent(WebEventDescriptor eventDescriptor, String eventArgsJson)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
--- End of stack trace from previous location ---
   at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously(JSRuntime jsRuntime, DotNetInvocationInfo& callInfo, IDotNetObjectReference objectReference, String argsJson)
   at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, String argsJson)
    at Object.endInvokeDotNetFromJS (http://localhost:56826/_framework/blazor.webassembly.js:1:4191)
    at Object.invokeJSFromDotNet (http://localhost:56826/_framework/blazor.webassembly.js:1:3797)
    at Object.w [as invokeJSFromDotNet] (http://localhost:56826/_framework/blazor.webassembly.js:1:64301)
    at _mono_wasm_invoke_js_blazor (http://localhost:56826/_framework/dotnet.5.0.4.js:1:190800)
    at do_icall (<anonymous>:wasm-function[10596]:0x194e4e)
    at do_icall_wrapper (<anonymous>:wasm-function[3305]:0x79df9)
    at interp_exec_method (<anonymous>:wasm-function[2155]:0x44ad3)
    at interp_runtime_invoke (<anonymous>:wasm-function[7862]:0x12efff)
    at mono_jit_runtime_invoke (<anonymous>:wasm-function[7347]:0x118e5f)
    at do_runtime_invoke (<anonymous>:wasm-function[3304]:0x79d42)

@SteveSandersonMS SteveSandersonMS added the Done This issue has been fixed label Apr 9, 2021
@ghost ghost locked as resolved and limited conversation to collaborators May 9, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affected-medium This issue impacts approximately half of our customers area-blazor Includes: Blazor, Razor Components bug This issue describes a behavior which is not expected - a bug. Done This issue has been fixed feature-blazor-wasm This issue is related to and / or impacts Blazor WebAssembly severity-major This label is used by an internal tool
Projects
None yet
Development

Successfully merging a pull request may close this issue.