Skip to content
This repository was archived by the owner on Feb 25, 2021. It is now read-only.

Commit 15da07f

Browse files
In ComponentState, track parent ComponentState. Be explicit that Renderer only lets you attach root components.
1 parent 49c5392 commit 15da07f

File tree

9 files changed

+126
-48
lines changed

9 files changed

+126
-48
lines changed

src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void AddComponent<TComponent>(string domElementSelector)
6161
public void AddComponent(Type componentType, string domElementSelector)
6262
{
6363
var component = InstantiateComponent(componentType);
64-
var componentId = AssignComponentId(component);
64+
var componentId = AssignRootComponentId(component);
6565

6666
// The only reason we're calling this synchronously is so that, if it throws,
6767
// we get the exception back *before* attempting the first UpdateDisplay

src/Microsoft.AspNetCore.Blazor.Server/Circuits/RemoteRenderer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public void AddComponent<TComponent>(string domElementSelector)
6464
public void AddComponent(Type componentType, string domElementSelector)
6565
{
6666
var component = InstantiateComponent(componentType);
67-
var componentId = AssignComponentId(component);
67+
var componentId = AssignRootComponentId(component);
6868

6969
var attachComponentTask = _jsRuntime.InvokeAsync<object>(
7070
"Blazor._internal.attachRootComponentToElement",

src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffBuilder.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static RenderTreeDiff ComputeDiff(
2020
var editsBuffer = batchBuilder.EditsBuffer;
2121
var editsBufferStartLength = editsBuffer.Count;
2222

23-
var diffContext = new DiffContext(renderer, batchBuilder, oldTree.Array, newTree.Array);
23+
var diffContext = new DiffContext(renderer, batchBuilder, componentId, oldTree.Array, newTree.Array);
2424
AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count);
2525

2626
var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count);
@@ -638,7 +638,8 @@ private static void InitializeNewComponentFrame(ref DiffContext diffContext, int
638638
throw new InvalidOperationException($"Child component already exists during {nameof(InitializeNewComponentFrame)}");
639639
}
640640

641-
diffContext.Renderer.InstantiateChildComponentOnFrame(ref frame);
641+
var parentComponentId = diffContext.ComponentId;
642+
diffContext.Renderer.InstantiateChildComponentOnFrame(ref frame, parentComponentId);
642643
var childComponentInstance = frame.Component;
643644

644645
// Set initial parameters
@@ -718,16 +719,19 @@ private struct DiffContext
718719
public readonly ArrayBuilder<RenderTreeEdit> Edits;
719720
public readonly ArrayBuilder<RenderTreeFrame> ReferenceFrames;
720721
public readonly Dictionary<string, int> AttributeDiffSet;
722+
public readonly int ComponentId;
721723
public int SiblingIndex;
722724

723725
public DiffContext(
724726
Renderer renderer,
725727
RenderBatchBuilder batchBuilder,
728+
int componentId,
726729
RenderTreeFrame[] oldTree,
727730
RenderTreeFrame[] newTree)
728731
{
729732
Renderer = renderer;
730733
BatchBuilder = batchBuilder;
734+
ComponentId = componentId;
731735
OldTree = oldTree;
732736
NewTree = newTree;
733737
Edits = batchBuilder.EditsBuffer;

src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
1515
internal class ComponentState
1616
{
1717
private readonly int _componentId; // TODO: Change the type to 'long' when the Mono runtime has more complete support for passing longs in .NET->JS calls
18+
private readonly ComponentState _parentComponentState;
1819
private readonly IComponent _component;
1920
private readonly Renderer _renderer;
2021
private RenderTreeBuilder _renderTreeBuilderCurrent;
@@ -27,9 +28,11 @@ internal class ComponentState
2728
/// <param name="renderer">The <see cref="Renderer"/> with which the new instance should be associated.</param>
2829
/// <param name="componentId">The externally visible identifier for the <see cref="IComponent"/>. The identifier must be unique in the context of the <see cref="Renderer"/>.</param>
2930
/// <param name="component">The <see cref="IComponent"/> whose state is being tracked.</param>
30-
public ComponentState(Renderer renderer, int componentId, IComponent component)
31+
/// <param name="parentComponentState">The <see cref="ComponentState"/> for the parent component, or null if this is a root component.</param>
32+
public ComponentState(Renderer renderer, int componentId, IComponent component, ComponentState parentComponentState)
3133
{
3234
_componentId = componentId;
35+
_parentComponentState = parentComponentState;
3336
_component = component ?? throw new ArgumentNullException(nameof(component));
3437
_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));
3538
_renderTreeBuilderCurrent = new RenderTreeBuilder(renderer);
@@ -89,5 +92,10 @@ public void DispatchEvent(EventHandlerInvoker binding, UIEventArgs eventArgs)
8992

9093
public void NotifyRenderCompleted()
9194
=> (_component as IHandleAfterRender)?.OnAfterRender();
95+
96+
// TODO: Remove this once we can remove TemporaryGetParentComponentIdForTest
97+
// from Renderer.cs and corresponding unit test.
98+
public int? TemporaryParentComponentIdForTests
99+
=> _parentComponentState?._componentId;
92100
}
93101
}

src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,14 @@ protected IComponent InstantiateComponent(Type componentType)
4848
/// </summary>
4949
/// <param name="component">The component.</param>
5050
/// <returns>The component's assigned identifier.</returns>
51-
protected int AssignComponentId(IComponent component)
51+
protected int AssignRootComponentId(IComponent component)
52+
=> AssignComponentId(component, -1);
53+
54+
private int AssignComponentId(IComponent component, int parentComponentId)
5255
{
5356
var componentId = _nextComponentId++;
54-
var componentState = new ComponentState(this, componentId, component);
57+
var parentComponentState = GetOptionalComponentState(parentComponentId);
58+
var componentState = new ComponentState(this, componentId, component, parentComponentState);
5559
_componentStateById.Add(componentId, componentState);
5660
component.Init(new RenderHandle(this, componentId));
5761
return componentId;
@@ -92,7 +96,7 @@ public void DispatchEvent(int componentId, int eventHandlerId, UIEventArgs event
9296
}
9397
}
9498

95-
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame)
99+
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId)
96100
{
97101
if (frame.FrameType != RenderTreeFrameType.Component)
98102
{
@@ -105,7 +109,7 @@ internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame)
105109
}
106110

107111
var newComponent = InstantiateComponent(frame.ComponentType);
108-
var newComponentId = AssignComponentId(newComponent);
112+
var newComponentId = AssignComponentId(newComponent, parentComponentId);
109113
frame = frame.WithComponentInstance(newComponentId, newComponent);
110114
}
111115

@@ -140,6 +144,15 @@ internal void AddToRenderQueue(int componentId, RenderFragment renderFragment)
140144
}
141145
}
142146

147+
/// <summary>
148+
/// This only needs to exist until there's some other unit-testable functionality
149+
/// that makes use of walking the ancestor hierarchy.
150+
/// </summary>
151+
/// <param name="componentId">The component ID.</param>
152+
/// <returns>The parent component's ID, or null if the component was at the root.</returns>
153+
internal int? TemporaryGetParentComponentIdForTest(int componentId)
154+
=> GetRequiredComponentState(componentId).TemporaryParentComponentIdForTests;
155+
143156
private ComponentState GetRequiredComponentState(int componentId)
144157
=> _componentStateById.TryGetValue(componentId, out var componentState)
145158
? componentState

test/Microsoft.AspNetCore.Blazor.Build.Test/RazorIntegrationTestBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
@@ -368,7 +368,7 @@ public TestRenderer() : base(new TestServiceProvider())
368368
public RenderTreeFrame[] LatestBatchReferenceFrames { get; private set; }
369369

370370
public void AttachComponent(IComponent component)
371-
=> AssignComponentId(component);
371+
=> AssignRootComponentId(component);
372372

373373
protected override void UpdateDisplay(in RenderBatch renderBatch)
374374
{

test/Microsoft.AspNetCore.Blazor.Test/LayoutTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) .NET Foundation. All rights reserved.
1+
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using Microsoft.AspNetCore.Blazor.Components;
@@ -21,7 +21,7 @@ public LayoutTest()
2121
{
2222
_renderer = new TestRenderer();
2323
_layoutDisplayComponent = new LayoutDisplay();
24-
_layoutDisplayComponentId = _renderer.AssignComponentId(_layoutDisplayComponent);
24+
_layoutDisplayComponentId = _renderer.AssignRootComponentId(_layoutDisplayComponent);
2525
}
2626

2727
[Fact]

0 commit comments

Comments
 (0)