Skip to content

Commit c4bfed7

Browse files
csharpfritzCopilot
andcommitted
fix: preserve registration state across FlushAsync calls
ClientScriptShim.FlushAsync was clearing _startupScripts, _scriptBlocks, and _scriptIncludes after execution, causing Is*Registered methods to return false. Web Forms preserves registration state for the full page lifecycle. Added _flushed* HashSets to track executed keys so IsStartupScriptRegistered, IsClientScriptBlockRegistered, and IsClientScriptIncludeRegistered return true after flush. Fixes: RegisterClientScriptInclude demo and Deduplication demo on the ClientScriptShim sample page. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 5adadf1 commit c4bfed7

2 files changed

Lines changed: 17 additions & 7 deletions

File tree

src/BlazorWebFormsComponents.Test/ClientScriptShimTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,11 @@ public async Task FlushAsync_ClearsQueuesAfterFlush()
300300

301301
await shim.FlushAsync(mockJs.Object);
302302

303-
// After flush, all queues should be empty
304-
shim.IsStartupScriptRegistered(typeof(ClientScriptShimTests), "temp").ShouldBeFalse();
305-
shim.IsClientScriptBlockRegistered(typeof(ClientScriptShimTests), "block").ShouldBeFalse();
306-
shim.IsClientScriptIncludeRegistered("inc").ShouldBeFalse();
303+
// After flush, queues are empty (no re-execution) but registration
304+
// status persists — matching Web Forms page-lifecycle semantics.
305+
shim.IsStartupScriptRegistered(typeof(ClientScriptShimTests), "temp").ShouldBeTrue();
306+
shim.IsClientScriptBlockRegistered(typeof(ClientScriptShimTests), "block").ShouldBeTrue();
307+
shim.IsClientScriptIncludeRegistered("inc").ShouldBeTrue();
307308
}
308309

309310
[Fact]

src/BlazorWebFormsComponents/ClientScriptShim.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ public class ClientScriptShim
2828
private readonly Dictionary<string, string> _startupScripts = new();
2929
private readonly Dictionary<string, string> _scriptBlocks = new();
3030
private readonly Dictionary<string, string> _scriptIncludes = new();
31+
private readonly HashSet<string> _flushedStartupScripts = new();
32+
private readonly HashSet<string> _flushedScriptBlocks = new();
33+
private readonly HashSet<string> _flushedScriptIncludes = new();
3134

3235
/// <summary>
3336
/// Initializes a new instance of the <see cref="ClientScriptShim"/> class.
@@ -80,7 +83,8 @@ public void RegisterStartupScript(Type type, string key, string script)
8083
/// <returns><c>true</c> if the script is registered; otherwise <c>false</c>.</returns>
8184
public bool IsStartupScriptRegistered(Type type, string key)
8285
{
83-
return _startupScripts.ContainsKey(BuildKey(type, key));
86+
var k = BuildKey(type, key);
87+
return _startupScripts.ContainsKey(k) || _flushedStartupScripts.Contains(k);
8488
}
8589

8690
// ─── Client Script Blocks ──────────────────────────────────────────
@@ -111,7 +115,8 @@ public void RegisterClientScriptBlock(Type type, string key, string script, bool
111115
/// <returns><c>true</c> if the script block is registered; otherwise <c>false</c>.</returns>
112116
public bool IsClientScriptBlockRegistered(Type type, string key)
113117
{
114-
return _scriptBlocks.ContainsKey(BuildKey(type, key));
118+
var k = BuildKey(type, key);
119+
return _scriptBlocks.ContainsKey(k) || _flushedScriptBlocks.Contains(k);
115120
}
116121

117122
// ─── Client Script Includes ────────────────────────────────────────
@@ -149,7 +154,7 @@ public void RegisterClientScriptInclude(Type type, string key, string url)
149154
/// <returns><c>true</c> if the include is registered; otherwise <c>false</c>.</returns>
150155
public bool IsClientScriptIncludeRegistered(string key)
151156
{
152-
return _scriptIncludes.ContainsKey(key);
157+
return _scriptIncludes.ContainsKey(key) || _flushedScriptIncludes.Contains(key);
153158
}
154159

155160
// ─── Flush ─────────────────────────────────────────────────────────
@@ -188,6 +193,10 @@ public async Task FlushAsync(IJSRuntime jsRuntime)
188193
await jsRuntime.InvokeVoidAsync("eval", loaderScript);
189194
}
190195

196+
foreach (var key in _scriptBlocks.Keys) _flushedScriptBlocks.Add(key);
197+
foreach (var key in _startupScripts.Keys) _flushedStartupScripts.Add(key);
198+
foreach (var key in _scriptIncludes.Keys) _flushedScriptIncludes.Add(key);
199+
191200
_scriptBlocks.Clear();
192201
_startupScripts.Clear();
193202
_scriptIncludes.Clear();

0 commit comments

Comments
 (0)