Skip to content

Commit 741d98f

Browse files
authored
Fix Ignitor bug (#25933)
The implementation of the Ignitor has a few differences compared to BrowserRenderer which results in exceptions. This change addresses these issue. In addition, this adds a minimal sample that makes it easier to test Ignitor without having to package it.
1 parent 0250c22 commit 741d98f

File tree

7 files changed

+108
-20
lines changed

7 files changed

+108
-20
lines changed

AspNetCore.sln

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,7 +1507,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.App.Un
15071507
EndProject
15081508
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Localization", "Localization", "{3D34C81F-2CB5-459E-87E9-0CC04757A2A0}"
15091509
EndProject
1510-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GlobalizationWasmApp", "src\Components\test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{04CFE286-6D32-41EF-8887-4B5F8086A365}"
1510+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GlobalizationWasmApp", "src\Components\test\testassets\GlobalizationWasmApp\GlobalizationWasmApp.csproj", "{04CFE286-6D32-41EF-8887-4B5F8086A365}"
15111511
EndProject
15121512
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Localization.Abstractions", "src\Localization\Abstractions\src\Microsoft.Extensions.Localization.Abstractions.csproj", "{FEF97646-9BC9-4D1B-A939-784D915C18A4}"
15131513
EndProject
@@ -1551,6 +1551,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{E83B0BCC-A8E
15511551
EndProject
15521552
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostingStartup", "src\SiteExtensions\Sdk\HostingStartup\HostingStartup.csproj", "{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}"
15531553
EndProject
1554+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IgnitorSample", "src\Components\Samples\IgnitorSample\IgnitorSample.csproj", "{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}"
1555+
EndProject
15541556
Global
15551557
GlobalSection(SolutionConfigurationPlatforms) = preSolution
15561558
Debug|Any CPU = Debug|Any CPU
@@ -7223,18 +7225,6 @@ Global
72237225
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x64.Build.0 = Release|Any CPU
72247226
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x86.ActiveCfg = Release|Any CPU
72257227
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1}.Release|x86.Build.0 = Release|Any CPU
7226-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7227-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.Build.0 = Debug|Any CPU
7228-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.ActiveCfg = Debug|Any CPU
7229-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.Build.0 = Debug|Any CPU
7230-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.ActiveCfg = Debug|Any CPU
7231-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.Build.0 = Debug|Any CPU
7232-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.ActiveCfg = Release|Any CPU
7233-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.Build.0 = Release|Any CPU
7234-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.ActiveCfg = Release|Any CPU
7235-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.Build.0 = Release|Any CPU
7236-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.ActiveCfg = Release|Any CPU
7237-
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.Build.0 = Release|Any CPU
72387228
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72397229
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
72407230
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -7247,6 +7237,18 @@ Global
72477237
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x64.Build.0 = Release|Any CPU
72487238
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x86.ActiveCfg = Release|Any CPU
72497239
{010A9638-F20E-4FE6-A186-85732BFC9CB0}.Release|x86.Build.0 = Release|Any CPU
7240+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7241+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|Any CPU.Build.0 = Debug|Any CPU
7242+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.ActiveCfg = Debug|Any CPU
7243+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x64.Build.0 = Debug|Any CPU
7244+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.ActiveCfg = Debug|Any CPU
7245+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Debug|x86.Build.0 = Debug|Any CPU
7246+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.ActiveCfg = Release|Any CPU
7247+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|Any CPU.Build.0 = Release|Any CPU
7248+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.ActiveCfg = Release|Any CPU
7249+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x64.Build.0 = Release|Any CPU
7250+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.ActiveCfg = Release|Any CPU
7251+
{04CFE286-6D32-41EF-8887-4B5F8086A365}.Release|x86.Build.0 = Release|Any CPU
72507252
{FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72517253
{FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
72527254
{FEF97646-9BC9-4D1B-A939-784D915C18A4}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -7427,6 +7429,18 @@ Global
74277429
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x64.Build.0 = Release|Any CPU
74287430
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x86.ActiveCfg = Release|Any CPU
74297431
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21}.Release|x86.Build.0 = Release|Any CPU
7432+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
7433+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
7434+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x64.ActiveCfg = Debug|Any CPU
7435+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x64.Build.0 = Debug|Any CPU
7436+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x86.ActiveCfg = Debug|Any CPU
7437+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Debug|x86.Build.0 = Debug|Any CPU
7438+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
7439+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|Any CPU.Build.0 = Release|Any CPU
7440+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x64.ActiveCfg = Release|Any CPU
7441+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x64.Build.0 = Release|Any CPU
7442+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x86.ActiveCfg = Release|Any CPU
7443+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1}.Release|x86.Build.0 = Release|Any CPU
74307444
EndGlobalSection
74317445
GlobalSection(SolutionProperties) = preSolution
74327446
HideSolutionNode = FALSE
@@ -8179,10 +8193,10 @@ Global
81798193
{37329855-01B8-4B03-9765-1A941B06E43C} = {8C15FD04-7F90-43FC-B488-023432FE3CE1}
81808194
{D3246226-BC1A-47F1-8E3E-C3380A8F13FB} = {8C15FD04-7F90-43FC-B488-023432FE3CE1}
81818195
{B06ADD57-E855-4D8C-85DC-B323509AE540} = {898F7E0B-1671-42CB-9DFB-689AFF212ED3}
8182-
{04CFE286-6D32-41EF-8887-4B5F8086A365} = {6126DCE4-9692-4EE2-B240-C65743572995}
81838196
{BAD47859-95DF-4C8F-9AF7-C48B68F478A1} = {A4C26078-B6D8-4FD8-87A6-7C15A3482038}
81848197
{010A9638-F20E-4FE6-A186-85732BFC9CB0} = {A4C26078-B6D8-4FD8-87A6-7C15A3482038}
81858198
{3D34C81F-2CB5-459E-87E9-0CC04757A2A0} = {017429CC-C5FB-48B4-9C46-034E29EE2F06}
8199+
{04CFE286-6D32-41EF-8887-4B5F8086A365} = {6126DCE4-9692-4EE2-B240-C65743572995}
81868200
{FEF97646-9BC9-4D1B-A939-784D915C18A4} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0}
81878201
{839CE175-E0D9-43B9-9FA8-F32C47E7F56B} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0}
81888202
{50BF2926-7435-4F4B-88A9-3D0EDEB67FC8} = {3D34C81F-2CB5-459E-87E9-0CC04757A2A0}
@@ -8204,6 +8218,7 @@ Global
82048218
{545751D5-71FC-4889-A3A0-BBD731DBA18A} = {56B45580-B089-424E-A847-A6115D591950}
82058219
{E83B0BCC-A8E0-4FBD-BE51-9A533C9CB972} = {DFC4F588-B4B4-484B-AB93-B36721374AD3}
82068220
{5D6F99C5-D292-4459-B8BD-8E4AD42E1B21} = {E83B0BCC-A8E0-4FBD-BE51-9A533C9CB972}
8221+
{CAFD1885-B87B-4A7A-8BE6-86B0C238C2B1} = {5FE1FBC1-8CE3-4355-9866-44FE1307C5F1}
82078222
EndGlobalSection
82088223
GlobalSection(ExtensibilityGlobals) = postSolution
82098224
SolutionGuid = {3E8720B3-DBDD-498C-B383-2CC32A054E8F}

src/Components/ComponentsNoDeps.slnf

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"src\\Components\\Ignitor\\src\\Ignitor.csproj",
1515
"src\\Components\\Ignitor\\test\\Ignitor.Test.csproj",
1616
"src\\Components\\Samples\\BlazorServerApp\\BlazorServerApp.csproj",
17+
"src\\Components\\Samples\\IgnitorSample\\IgnitorSample.csproj",
1718
"src\\Components\\Server\\src\\Microsoft.AspNetCore.Components.Server.csproj",
1819
"src\\Components\\Server\\test\\Microsoft.AspNetCore.Components.Server.Tests.csproj",
1920
"src\\Components\\Web.Extensions\\src\\Microsoft.AspNetCore.Components.Web.Extensions.csproj",
@@ -49,4 +50,4 @@
4950
"src\\Components\\test\\testassets\\TestServer\\Components.TestServer.csproj"
5051
]
5152
}
52-
}
53+
}

src/Components/Ignitor/src/BlazorClient.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Diagnostics;
56
using System.Linq;
67
using System.Net.Http;
78
using System.Text.Json;
@@ -35,8 +36,10 @@ public BlazorClient()
3536
});
3637
}
3738

38-
public TimeSpan? DefaultConnectionTimeout { get; set; } = TimeSpan.FromSeconds(20);
39-
public TimeSpan? DefaultOperationTimeout { get; set; } = TimeSpan.FromMilliseconds(500);
39+
public TimeSpan? DefaultConnectionTimeout { get; set; } = Debugger.IsAttached ?
40+
Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(20);
41+
public TimeSpan? DefaultOperationTimeout { get; set; } = Debugger.IsAttached ?
42+
Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(500);
4043

4144
/// <summary>
4245
/// Gets or sets a value that determines whether the client will capture data such

src/Components/Ignitor/src/ElementHive.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ private int InsertFrame(RenderBatch batch, ContainerNode parent, int childIndex,
259259

260260
case RenderTreeFrameType.Region:
261261
{
262-
return InsertFrameRange(batch, parent, childIndex, frames, frameIndex + 1, frameIndex + CountDescendantFrames(frame));
262+
return InsertFrameRange(batch, parent, childIndex, frames, frameIndex + 1, frameIndex + frame.RegionSubtreeLength);
263263
}
264264

265265
case RenderTreeFrameType.ElementReferenceCapture:
@@ -322,7 +322,8 @@ private void InsertElement(RenderBatch batch, ContainerNode parent, int childInd
322322
{
323323
// Note: we don't handle SVG here
324324
var newElement = new ElementNode(frame.ElementName);
325-
parent.InsertLogicalChild(newElement, childIndex);
325+
326+
var inserted = false;
326327

327328
// Apply attributes
328329
for (var i = frameIndex + 1; i < frameIndex + frame.ElementSubtreeLength; i++)
@@ -334,12 +335,21 @@ private void InsertElement(RenderBatch batch, ContainerNode parent, int childInd
334335
}
335336
else
336337
{
338+
parent.InsertLogicalChild(newElement, childIndex);
339+
inserted = true;
340+
337341
// As soon as we see a non-attribute child, all the subsequent child frames are
338342
// not attributes, so bail out and insert the remnants recursively
339343
InsertFrameRange(batch, newElement, 0, frames, i, frameIndex + frame.ElementSubtreeLength);
340344
break;
341345
}
342346
}
347+
348+
// this element did not have any children, so it's not inserted yet.
349+
if (!inserted)
350+
{
351+
parent.InsertLogicalChild(newElement, childIndex);
352+
}
343353
}
344354

345355
private void ApplyAttribute(RenderBatch batch, ElementNode elementNode, RenderTreeFrame attributeFrame)

src/Components/Samples/BlazorServerApp/Pages/Counter.razor

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<h1>Counter</h1>
44

5-
<p>Current count: @currentCount</p>
5+
<p id="counter">Current count: @currentCount</p>
66

77
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
88

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
5+
<IsShippingPackage>false</IsShippingPackage>
6+
<Nullable>enable</Nullable>
7+
<OutputType>Exe</OutputType>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<Reference Include="Ignitor" />
12+
</ItemGroup>
13+
14+
</Project>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Text.Json;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using Ignitor;
7+
using Microsoft.AspNetCore.SignalR.Client;
8+
9+
namespace IgnitorSample
10+
{
11+
/// <summary>
12+
/// This is a minimal sample that lets you try out Ignitor against a Blazor Server app.
13+
/// To use this, first launch the server app. Update the code below to point to the host url and run the test.
14+
/// </summary>
15+
class Program
16+
{
17+
private static readonly string ServerUrl = "https://localhost:5001";
18+
private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
19+
20+
static async Task Main(string[] args)
21+
{
22+
var client = new BlazorClient();
23+
await client.ConnectAsync(new Uri(ServerUrl));
24+
25+
await VerifyNavigationAsync(client);
26+
27+
Console.WriteLine("Done");
28+
}
29+
30+
static async ValueTask VerifyNavigationAsync(BlazorClient client)
31+
{
32+
await client.ExpectRenderBatch(() => client.NavigateAsync($"{ServerUrl}/counter"));
33+
client.Hive.TryFindElementById("counter", out var counter);
34+
Debug.Assert(counter != null, "We must have navigated to counter.");
35+
}
36+
}
37+
38+
static class BlazorClientExtensions
39+
{
40+
public static Task NavigateAsync(this BlazorClient client, string url, CancellationToken cancellationToken = default)
41+
{
42+
return client.HubConnection.InvokeAsync("OnLocationChanged", url, false, cancellationToken);
43+
}
44+
}
45+
}

0 commit comments

Comments
 (0)