Skip to content

Commit 9971a3b

Browse files
committed
Fix the test
1 parent 67c7fc9 commit 9971a3b

File tree

2 files changed

+16
-22
lines changed

2 files changed

+16
-22
lines changed

src/Components/Components/src/RenderTree/Renderer.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System.Diagnostics;
77
using System.Diagnostics.CodeAnalysis;
88
using System.Linq;
9-
using System.Threading;
109
using Microsoft.AspNetCore.Components.HotReload;
1110
using Microsoft.AspNetCore.Components.Infrastructure;
1211
using Microsoft.AspNetCore.Components.Reflection;
@@ -1383,9 +1382,9 @@ private sealed class HotReloadRenderHandler(Renderer renderer, ExecutionContext?
13831382
{
13841383
public void RerenderOnHotReload()
13851384
{
1386-
if (_executionContext is null)
1385+
if (executionContext is null)
13871386
{
1388-
_renderer.RenderRootComponentsOnHotReload();
1387+
renderer.RenderRootComponentsOnHotReload();
13891388
}
13901389
else
13911390
{

src/Components/Components/test/RendererTest.cs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5029,21 +5029,17 @@ public async Task DisposingRenderer_UnsubsribesFromHotReloadManager()
50295029
}
50305030

50315031
[Fact]
5032-
public async Task HotReload_ReRenderPreservesAsyncLocalValues_FailsToday()
5032+
public async Task HotReload_ReRenderPreservesAsyncLocalValues()
50335033
{
5034-
// This is a regression test for the reported issue: AsyncLocal values are lost during hot reload.
5035-
// The desired (correct) behavior is that AsyncLocal values flow into the hot-reload re-render.
5036-
// Currently, because the hot reload callback is raised from a context without the original ExecutionContext,
5037-
// the AsyncLocal value is lost and the assertion below will FAIL (demonstrating the bug).
5038-
50395034
await using var renderer = new TestRenderer();
5040-
var hotReloadManager = new HotReloadManager { MetadataUpdateSupported = true };
5041-
renderer.HotReloadManager = hotReloadManager;
5035+
5036+
renderer.HotReloadManager = HotReloadManager.Default;
5037+
HotReloadManager.Default.MetadataUpdateSupported = true;
50425038

50435039
var component = new AsyncLocalCaptureComponent();
50445040

50455041
// Establish AsyncLocal value before registering hot reload handler / rendering.
5046-
AsyncLocalCaptureComponent.TestAsyncLocal.Value = "AmbientValue";
5042+
ServiceAccessor.TestAsyncLocal.Value = "AmbientValue";
50475043

50485044
var componentId = renderer.AssignRootComponentId(component);
50495045
await renderer.Dispatcher.InvokeAsync(() => renderer.RenderRootComponentAsync(componentId));
@@ -5052,20 +5048,16 @@ public async Task HotReload_ReRenderPreservesAsyncLocalValues_FailsToday()
50525048
Assert.Null(component.HotReloadValue);
50535049

50545050
// Simulate hot reload delta applied from a fresh thread (different ExecutionContext) so the AsyncLocal value is lost.
5055-
var expected = AsyncLocalCaptureComponent.TestAsyncLocal.Value;
5051+
var expected = ServiceAccessor.TestAsyncLocal.Value;
50565052
var thread = new Thread(() =>
50575053
{
50585054
// Simulate environment where the ambient value is not present on the hot reload thread.
5059-
AsyncLocalCaptureComponent.TestAsyncLocal.Value = null;
5060-
var evtField = typeof(HotReloadManager).GetField("OnDeltaApplied", BindingFlags.Instance | BindingFlags.NonPublic);
5061-
var del = (Action)evtField.GetValue(hotReloadManager);
5062-
del?.Invoke();
5055+
ServiceAccessor.TestAsyncLocal.Value = null;
5056+
HotReloadManager.UpdateApplication([]);
50635057
});
50645058
thread.Start();
50655059
thread.Join();
50665060

5067-
// EXPECTED (desired) correct behavior: value should still be present.
5068-
// ACTUAL today: this will be null, so the test fails, confirming the bug.
50695061
Assert.Equal(expected, component.HotReloadValue);
50705062
}
50715063

@@ -5222,10 +5214,13 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
52225214
=> Task.CompletedTask;
52235215
}
52245216

5225-
private class AsyncLocalCaptureComponent : IComponent
5217+
private class ServiceAccessor
52265218
{
5227-
public static readonly AsyncLocal<string> TestAsyncLocal = new();
5219+
public static AsyncLocal<string> TestAsyncLocal = new AsyncLocal<string>();
5220+
}
52285221

5222+
private class AsyncLocalCaptureComponent : IComponent
5223+
{
52295224
private bool _initialized;
52305225
private RenderHandle _renderHandle;
52315226
public string HotReloadValue { get; private set; }
@@ -5241,7 +5236,7 @@ public Task SetParametersAsync(ParameterView parameters)
52415236
else
52425237
{
52435238
// Hot reload re-render path.
5244-
HotReloadValue = TestAsyncLocal.Value;
5239+
HotReloadValue = ServiceAccessor.TestAsyncLocal.Value;
52455240
}
52465241
return Task.CompletedTask;
52475242
}

0 commit comments

Comments
 (0)