Skip to content

Commit 82605a1

Browse files
committed
Fix for Early initialzation problem.
When we add LocationChanging eventhandlers before the JSRuntime was initialized, the RemoteNavigationManager would crash. Also the navigation subsystem would not be informed we had Eventhandlers unless that state changed.
1 parent debb1b0 commit 82605a1

File tree

3 files changed

+26
-13
lines changed

3 files changed

+26
-13
lines changed

src/Components/Components/src/NavigationManager.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ namespace Microsoft.AspNetCore.Components
1111
/// </summary>
1212
public abstract class NavigationManager
1313
{
14-
private bool _hasLocationChangingListeners;
15-
1614
/// <summary>
1715
/// An event that fires when the navigation location has changed.
1816
/// </summary>
@@ -41,18 +39,20 @@ public event EventHandler<LocationChangingEventArgs> LocationChanging
4139
{
4240
AssertInitialized();
4341
_locationChanging += value;
44-
UpdateHasLocationChangingListeners(true);
42+
UpdateHasLocationChangingEventHandlers();
4543
}
4644
remove
4745
{
4846
AssertInitialized();
4947
_locationChanging -= value;
50-
UpdateHasLocationChangingListeners(_locationChanging != null);
48+
UpdateHasLocationChangingEventHandlers();
5149
}
5250
}
5351

5452
private EventHandler<LocationChangingEventArgs>? _locationChanging;
5553

54+
private bool _hasLocationChangingEventHandlers;
55+
5656
// For the baseUri it's worth storing as a System.Uri so we can do operations
5757
// on that type. System.Uri gives us access to the original string anyway.
5858
private Uri? _baseUri;
@@ -255,17 +255,28 @@ protected bool NotifyLocationChanging(string uri, bool isInterceptedLink)
255255
/// Called when <see cref="LocationChanging"/> the fact that any event handlers are present or not changes.
256256
/// this can be used by descendants to inform the JSRuntime that there are locationchanging event handlers
257257
/// </summary>
258-
/// <param name="value">true if there are eventhandlers</param>
259-
protected virtual void SetHasLocationChangingListeners(bool value)
258+
/// <param name="value">true if there are event handlers</param>
259+
/// <returns>true when the navigation subsystem could be informed that we have event handlers</returns>
260+
protected virtual bool SetHasLocationChangingEventHandlers(bool value)
260261
{
262+
return true;
261263
}
262264

263-
private void UpdateHasLocationChangingListeners(bool value)
265+
/// <summary>
266+
/// Calls <see cref="SetHasLocationChangingEventHandlers"/> when needed
267+
/// This function is normally called when event handlers are added or removed from <see cref="LocationChanging"/>
268+
/// </summary>
269+
protected void UpdateHasLocationChangingEventHandlers()
264270
{
265-
if (_hasLocationChangingListeners != value)
271+
var value = _locationChanging != null;
272+
if (_hasLocationChangingEventHandlers != value)
266273
{
267-
_hasLocationChangingListeners = value;
268-
SetHasLocationChangingListeners(value);
274+
//If SetHasLocationChangingEventHandlers returns false, we won't update the _hasLocationChangingEventHandlers.
275+
//This way we can call this function again at a later time (for example when JSRuntime is initialized, See RemoteNavigationManager)
276+
if (SetHasLocationChangingEventHandlers(value))
277+
{
278+
_hasLocationChangingEventHandlers = value;
279+
}
269280
}
270281
}
271282

src/Components/Server/src/Circuits/RemoteNavigationManager.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ public void AttachJsRuntime(IJSRuntime jsRuntime)
5252
{
5353
throw new InvalidOperationException("JavaScript runtime already initialized.");
5454
}
55-
5655
_jsRuntime = jsRuntime;
56+
UpdateHasLocationChangingEventHandlers();
5757
}
5858

5959
public void NotifyLocationChanged(string uri, bool intercepted)
@@ -98,9 +98,10 @@ protected override void NavigateToCore(string uri, bool forceLoad)
9898
}
9999

100100
/// <inheritdoc />
101-
protected override void SetHasLocationChangingListeners(bool value)
101+
protected override bool SetHasLocationChangingEventHandlers(bool value)
102102
{
103103
_jsRuntime?.InvokeAsync<object>(Interop.SetHasLocationChangingListeners, value);
104+
return _jsRuntime != null;
104105
}
105106

106107
private static class Log

src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyNavigationManager.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ protected override void NavigateToCore(string uri, bool forceLoad)
4747
}
4848

4949
/// <inheritdoc />
50-
protected override void SetHasLocationChangingListeners(bool value)
50+
protected override bool SetHasLocationChangingEventHandlers(bool value)
5151
{
5252
DefaultWebAssemblyJSRuntime.Instance.Invoke<object>(Interop.SetHasLocationChangingListeners, value);
53+
return true;
5354
}
5455
}
5556
}

0 commit comments

Comments
 (0)