In ComponentState, track parent ComponentState. Be explicit that Renderer only lets you attach root components.
This commit is contained in:
parent
c05b98f9cb
commit
fa2b61773a
|
|
@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
||||||
public void AddComponent(Type componentType, string domElementSelector)
|
public void AddComponent(Type componentType, string domElementSelector)
|
||||||
{
|
{
|
||||||
var component = InstantiateComponent(componentType);
|
var component = InstantiateComponent(componentType);
|
||||||
var componentId = AssignComponentId(component);
|
var componentId = AssignRootComponentId(component);
|
||||||
|
|
||||||
// The only reason we're calling this synchronously is so that, if it throws,
|
// The only reason we're calling this synchronously is so that, if it throws,
|
||||||
// we get the exception back *before* attempting the first UpdateDisplay
|
// we get the exception back *before* attempting the first UpdateDisplay
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
||||||
public void AddComponent(Type componentType, string domElementSelector)
|
public void AddComponent(Type componentType, string domElementSelector)
|
||||||
{
|
{
|
||||||
var component = InstantiateComponent(componentType);
|
var component = InstantiateComponent(componentType);
|
||||||
var componentId = AssignComponentId(component);
|
var componentId = AssignRootComponentId(component);
|
||||||
|
|
||||||
var attachComponentTask = _jsRuntime.InvokeAsync<object>(
|
var attachComponentTask = _jsRuntime.InvokeAsync<object>(
|
||||||
"Blazor._internal.attachRootComponentToElement",
|
"Blazor._internal.attachRootComponentToElement",
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
var editsBuffer = batchBuilder.EditsBuffer;
|
var editsBuffer = batchBuilder.EditsBuffer;
|
||||||
var editsBufferStartLength = editsBuffer.Count;
|
var editsBufferStartLength = editsBuffer.Count;
|
||||||
|
|
||||||
var diffContext = new DiffContext(renderer, batchBuilder, oldTree.Array, newTree.Array);
|
var diffContext = new DiffContext(renderer, batchBuilder, componentId, oldTree.Array, newTree.Array);
|
||||||
AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count);
|
AppendDiffEntriesForRange(ref diffContext, 0, oldTree.Count, 0, newTree.Count);
|
||||||
|
|
||||||
var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count);
|
var editsSegment = editsBuffer.ToSegment(editsBufferStartLength, editsBuffer.Count);
|
||||||
|
|
@ -638,7 +638,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
throw new InvalidOperationException($"Child component already exists during {nameof(InitializeNewComponentFrame)}");
|
throw new InvalidOperationException($"Child component already exists during {nameof(InitializeNewComponentFrame)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
diffContext.Renderer.InstantiateChildComponentOnFrame(ref frame);
|
var parentComponentId = diffContext.ComponentId;
|
||||||
|
diffContext.Renderer.InstantiateChildComponentOnFrame(ref frame, parentComponentId);
|
||||||
var childComponentInstance = frame.Component;
|
var childComponentInstance = frame.Component;
|
||||||
|
|
||||||
// Set initial parameters
|
// Set initial parameters
|
||||||
|
|
@ -718,16 +719,19 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
|
||||||
public readonly ArrayBuilder<RenderTreeEdit> Edits;
|
public readonly ArrayBuilder<RenderTreeEdit> Edits;
|
||||||
public readonly ArrayBuilder<RenderTreeFrame> ReferenceFrames;
|
public readonly ArrayBuilder<RenderTreeFrame> ReferenceFrames;
|
||||||
public readonly Dictionary<string, int> AttributeDiffSet;
|
public readonly Dictionary<string, int> AttributeDiffSet;
|
||||||
|
public readonly int ComponentId;
|
||||||
public int SiblingIndex;
|
public int SiblingIndex;
|
||||||
|
|
||||||
public DiffContext(
|
public DiffContext(
|
||||||
Renderer renderer,
|
Renderer renderer,
|
||||||
RenderBatchBuilder batchBuilder,
|
RenderBatchBuilder batchBuilder,
|
||||||
|
int componentId,
|
||||||
RenderTreeFrame[] oldTree,
|
RenderTreeFrame[] oldTree,
|
||||||
RenderTreeFrame[] newTree)
|
RenderTreeFrame[] newTree)
|
||||||
{
|
{
|
||||||
Renderer = renderer;
|
Renderer = renderer;
|
||||||
BatchBuilder = batchBuilder;
|
BatchBuilder = batchBuilder;
|
||||||
|
ComponentId = componentId;
|
||||||
OldTree = oldTree;
|
OldTree = oldTree;
|
||||||
NewTree = newTree;
|
NewTree = newTree;
|
||||||
Edits = batchBuilder.EditsBuffer;
|
Edits = batchBuilder.EditsBuffer;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -15,6 +15,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
internal class ComponentState
|
internal class ComponentState
|
||||||
{
|
{
|
||||||
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
|
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
|
||||||
|
private readonly ComponentState _parentComponentState;
|
||||||
private readonly IComponent _component;
|
private readonly IComponent _component;
|
||||||
private readonly Renderer _renderer;
|
private readonly Renderer _renderer;
|
||||||
private RenderTreeBuilder _renderTreeBuilderCurrent;
|
private RenderTreeBuilder _renderTreeBuilderCurrent;
|
||||||
|
|
@ -27,9 +28,11 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
/// <param name="renderer">The <see cref="Renderer"/> with which the new instance should be associated.</param>
|
/// <param name="renderer">The <see cref="Renderer"/> with which the new instance should be associated.</param>
|
||||||
/// <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>
|
/// <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>
|
||||||
/// <param name="component">The <see cref="IComponent"/> whose state is being tracked.</param>
|
/// <param name="component">The <see cref="IComponent"/> whose state is being tracked.</param>
|
||||||
public ComponentState(Renderer renderer, int componentId, IComponent component)
|
/// <param name="parentComponentState">The <see cref="ComponentState"/> for the parent component, or null if this is a root component.</param>
|
||||||
|
public ComponentState(Renderer renderer, int componentId, IComponent component, ComponentState parentComponentState)
|
||||||
{
|
{
|
||||||
_componentId = componentId;
|
_componentId = componentId;
|
||||||
|
_parentComponentState = parentComponentState;
|
||||||
_component = component ?? throw new ArgumentNullException(nameof(component));
|
_component = component ?? throw new ArgumentNullException(nameof(component));
|
||||||
_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));
|
_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));
|
||||||
_renderTreeBuilderCurrent = new RenderTreeBuilder(renderer);
|
_renderTreeBuilderCurrent = new RenderTreeBuilder(renderer);
|
||||||
|
|
@ -89,5 +92,10 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
|
|
||||||
public void NotifyRenderCompleted()
|
public void NotifyRenderCompleted()
|
||||||
=> (_component as IHandleAfterRender)?.OnAfterRender();
|
=> (_component as IHandleAfterRender)?.OnAfterRender();
|
||||||
|
|
||||||
|
// TODO: Remove this once we can remove TemporaryGetParentComponentIdForTest
|
||||||
|
// from Renderer.cs and corresponding unit test.
|
||||||
|
public int? TemporaryParentComponentIdForTests
|
||||||
|
=> _parentComponentState?._componentId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,14 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="component">The component.</param>
|
/// <param name="component">The component.</param>
|
||||||
/// <returns>The component's assigned identifier.</returns>
|
/// <returns>The component's assigned identifier.</returns>
|
||||||
protected int AssignComponentId(IComponent component)
|
protected int AssignRootComponentId(IComponent component)
|
||||||
|
=> AssignComponentId(component, -1);
|
||||||
|
|
||||||
|
private int AssignComponentId(IComponent component, int parentComponentId)
|
||||||
{
|
{
|
||||||
var componentId = _nextComponentId++;
|
var componentId = _nextComponentId++;
|
||||||
var componentState = new ComponentState(this, componentId, component);
|
var parentComponentState = GetOptionalComponentState(parentComponentId);
|
||||||
|
var componentState = new ComponentState(this, componentId, component, parentComponentState);
|
||||||
_componentStateById.Add(componentId, componentState);
|
_componentStateById.Add(componentId, componentState);
|
||||||
component.Init(new RenderHandle(this, componentId));
|
component.Init(new RenderHandle(this, componentId));
|
||||||
return componentId;
|
return componentId;
|
||||||
|
|
@ -92,7 +96,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame)
|
internal void InstantiateChildComponentOnFrame(ref RenderTreeFrame frame, int parentComponentId)
|
||||||
{
|
{
|
||||||
if (frame.FrameType != RenderTreeFrameType.Component)
|
if (frame.FrameType != RenderTreeFrameType.Component)
|
||||||
{
|
{
|
||||||
|
|
@ -105,7 +109,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
}
|
}
|
||||||
|
|
||||||
var newComponent = InstantiateComponent(frame.ComponentType);
|
var newComponent = InstantiateComponent(frame.ComponentType);
|
||||||
var newComponentId = AssignComponentId(newComponent);
|
var newComponentId = AssignComponentId(newComponent, parentComponentId);
|
||||||
frame = frame.WithComponentInstance(newComponentId, newComponent);
|
frame = frame.WithComponentInstance(newComponentId, newComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,6 +144,15 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This only needs to exist until there's some other unit-testable functionality
|
||||||
|
/// that makes use of walking the ancestor hierarchy.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="componentId">The component ID.</param>
|
||||||
|
/// <returns>The parent component's ID, or null if the component was at the root.</returns>
|
||||||
|
internal int? TemporaryGetParentComponentIdForTest(int componentId)
|
||||||
|
=> GetRequiredComponentState(componentId).TemporaryParentComponentIdForTests;
|
||||||
|
|
||||||
private ComponentState GetRequiredComponentState(int componentId)
|
private ComponentState GetRequiredComponentState(int componentId)
|
||||||
=> _componentStateById.TryGetValue(componentId, out var componentState)
|
=> _componentStateById.TryGetValue(componentId, out var componentState)
|
||||||
? componentState
|
? componentState
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -368,7 +368,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test
|
||||||
public RenderTreeFrame[] LatestBatchReferenceFrames { get; private set; }
|
public RenderTreeFrame[] LatestBatchReferenceFrames { get; private set; }
|
||||||
|
|
||||||
public void AttachComponent(IComponent component)
|
public void AttachComponent(IComponent component)
|
||||||
=> AssignComponentId(component);
|
=> AssignRootComponentId(component);
|
||||||
|
|
||||||
protected override void UpdateDisplay(in RenderBatch renderBatch)
|
protected override void UpdateDisplay(in RenderBatch renderBatch)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Blazor.Components;
|
using Microsoft.AspNetCore.Blazor.Components;
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
_renderer = new TestRenderer();
|
_renderer = new TestRenderer();
|
||||||
_layoutDisplayComponent = new LayoutDisplay();
|
_layoutDisplayComponent = new LayoutDisplay();
|
||||||
_layoutDisplayComponentId = _renderer.AssignComponentId(_layoutDisplayComponent);
|
_layoutDisplayComponentId = _renderer.AssignRootComponentId(_layoutDisplayComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
|
|
||||||
// Act/Assert
|
// Act/Assert
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
var componentFrame = batch.ReferenceFrames
|
var componentFrame = batch.ReferenceFrames
|
||||||
|
|
@ -83,13 +83,46 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CanWalkTheAncestorHierarchy()
|
||||||
|
{
|
||||||
|
// TODO: Instead of testing this directly, once there's some other functionaly
|
||||||
|
// that relies on the ancestor hierarchy (e.g., deep params), test that instead
|
||||||
|
// and remove the otherwise unnecessary TemporaryGetParentComponentIdForTest API.
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
var renderer = new TestRenderer();
|
||||||
|
var rootComponent = new TestComponent(builder =>
|
||||||
|
{
|
||||||
|
builder.AddContent(0, "Hello");
|
||||||
|
builder.OpenComponent<AncestryComponent>(0);
|
||||||
|
builder.AddAttribute(1, nameof(AncestryComponent.NumDescendants), 2);
|
||||||
|
builder.CloseComponent();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var componentId = renderer.AssignRootComponentId(rootComponent);
|
||||||
|
rootComponent.TriggerRender();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var batch = renderer.Batches.Single();
|
||||||
|
var componentIds = batch.ReferenceFrames
|
||||||
|
.Where(frame => frame.FrameType == RenderTreeFrameType.Component)
|
||||||
|
.Select(f => f.ComponentId);
|
||||||
|
Assert.Equal(new[] { 1, 2, 3 }, componentIds);
|
||||||
|
Assert.Equal(2, renderer.TemporaryGetParentComponentIdForTest(3));
|
||||||
|
Assert.Equal(1, renderer.TemporaryGetParentComponentIdForTest(2));
|
||||||
|
Assert.Equal(0, renderer.TemporaryGetParentComponentIdForTest(1));
|
||||||
|
Assert.Null(renderer.TemporaryGetParentComponentIdForTest(0));
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CanReRenderTopLevelComponents()
|
public void CanReRenderTopLevelComponents()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var renderer = new TestRenderer();
|
var renderer = new TestRenderer();
|
||||||
var component = new MessageComponent { Message = "Initial message" };
|
var component = new MessageComponent { Message = "Initial message" };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
|
|
||||||
// Act/Assert: first render
|
// Act/Assert: first render
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
@ -127,7 +160,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.OpenComponent<MessageComponent>(0);
|
builder.OpenComponent<MessageComponent>(0);
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
var parentComponentId = renderer.AssignRootComponentId(parentComponent);
|
||||||
parentComponent.TriggerRender();
|
parentComponent.TriggerRender();
|
||||||
var nestedComponentFrame = renderer.Batches.Single()
|
var nestedComponentFrame = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -173,7 +206,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
OnTest = args => { receivedArgs = args; }
|
OnTest = args => { receivedArgs = args; }
|
||||||
};
|
};
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var eventHandlerId = renderer.Batches.Single()
|
var eventHandlerId = renderer.Batches.Single()
|
||||||
|
|
@ -201,7 +234,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
OnClick = args => { receivedArgs = args; }
|
OnClick = args => { receivedArgs = args; }
|
||||||
};
|
};
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var eventHandlerId = renderer.Batches.Single()
|
var eventHandlerId = renderer.Batches.Single()
|
||||||
|
|
@ -229,7 +262,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
OnClickAction = () => { receivedArgs = new object(); }
|
OnClickAction = () => { receivedArgs = new object(); }
|
||||||
};
|
};
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var eventHandlerId = renderer.Batches.Single()
|
var eventHandlerId = renderer.Batches.Single()
|
||||||
|
|
@ -258,7 +291,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.OpenComponent<EventComponent>(0);
|
builder.OpenComponent<EventComponent>(0);
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
var parentComponentId = renderer.AssignRootComponentId(parentComponent);
|
||||||
parentComponent.TriggerRender();
|
parentComponent.TriggerRender();
|
||||||
|
|
||||||
// Arrange: Render nested component
|
// Arrange: Render nested component
|
||||||
|
|
@ -298,7 +331,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseElement();
|
builder.CloseElement();
|
||||||
});
|
});
|
||||||
|
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var eventHandlerId = renderer.Batches.Single()
|
var eventHandlerId = renderer.Batches.Single()
|
||||||
|
|
@ -336,9 +369,9 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var renderer1 = new TestRenderer();
|
var renderer1 = new TestRenderer();
|
||||||
var renderer2 = new TestRenderer();
|
var renderer2 = new TestRenderer();
|
||||||
var component = new MultiRendererComponent();
|
var component = new MultiRendererComponent();
|
||||||
var renderer1ComponentId = renderer1.AssignComponentId(component);
|
var renderer1ComponentId = renderer1.AssignRootComponentId(component);
|
||||||
renderer2.AssignComponentId(new TestComponent(null)); // Just so they don't get the same IDs
|
renderer2.AssignRootComponentId(new TestComponent(null)); // Just so they don't get the same IDs
|
||||||
var renderer2ComponentId = renderer2.AssignComponentId(component);
|
var renderer2ComponentId = renderer2.AssignRootComponentId(component);
|
||||||
|
|
||||||
// Act/Assert
|
// Act/Assert
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
@ -376,7 +409,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var nestedComponentFrame = renderer.Batches.Single()
|
var nestedComponentFrame = renderer.Batches.Single()
|
||||||
|
|
@ -417,7 +450,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var originalComponentFrame = renderer.Batches.Single()
|
var originalComponentFrame = renderer.Batches.Single()
|
||||||
|
|
@ -453,7 +486,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
||||||
var childComponentId = renderer.Batches.Single()
|
var childComponentId = renderer.Batches.Single()
|
||||||
|
|
@ -495,7 +528,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignRootComponentId(component);
|
||||||
|
|
||||||
// Act/Assert 1: First render, capturing child component IDs
|
// Act/Assert 1: First render, capturing child component IDs
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
@ -534,7 +567,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var eventCount = 0;
|
var eventCount = 0;
|
||||||
Action<UIEventArgs> origEventHandler = args => { eventCount++; };
|
Action<UIEventArgs> origEventHandler = args => { eventCount++; };
|
||||||
var component = new EventComponent { OnTest = origEventHandler };
|
var component = new EventComponent { OnTest = origEventHandler };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var origEventHandlerId = renderer.Batches.Single()
|
var origEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -571,7 +604,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var eventCount = 0;
|
var eventCount = 0;
|
||||||
Action<UIEventArgs> origEventHandler = args => { eventCount++; };
|
Action<UIEventArgs> origEventHandler = args => { eventCount++; };
|
||||||
var component = new EventComponent { OnTest = origEventHandler };
|
var component = new EventComponent { OnTest = origEventHandler };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var origEventHandlerId = renderer.Batches.Single()
|
var origEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -611,7 +644,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{ nameof(EventComponent.OnTest), origEventHandler }
|
{ nameof(EventComponent.OnTest), origEventHandler }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
||||||
|
|
@ -653,7 +686,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var eventCount = 0;
|
var eventCount = 0;
|
||||||
Action<UIEventArgs> origEventHandler = args => { eventCount++; };
|
Action<UIEventArgs> origEventHandler = args => { eventCount++; };
|
||||||
var component = new EventComponent { OnTest = origEventHandler };
|
var component = new EventComponent { OnTest = origEventHandler };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var origEventHandlerId = renderer.Batches.Single()
|
var origEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -699,7 +732,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
var rootComponentId = renderer.AssignComponentId(rootComponent);
|
var rootComponentId = renderer.AssignRootComponentId(rootComponent);
|
||||||
rootComponent.TriggerRender();
|
rootComponent.TriggerRender();
|
||||||
var origBatchReferenceFrames = renderer.Batches.Single().ReferenceFrames;
|
var origBatchReferenceFrames = renderer.Batches.Single().ReferenceFrames;
|
||||||
var childComponentFrame = origBatchReferenceFrames
|
var childComponentFrame = origBatchReferenceFrames
|
||||||
|
|
@ -781,7 +814,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
builder.AddContent(0, $"Render count: {++renderCount}");
|
builder.AddContent(0, $"Render count: {++renderCount}");
|
||||||
});
|
});
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
|
|
||||||
// Act/Assert: Can trigger initial render
|
// Act/Assert: Can trigger initial render
|
||||||
Assert.Equal(0, renderCount);
|
Assert.Equal(0, renderCount);
|
||||||
|
|
@ -817,7 +850,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
builder.AddContent(2, $"Parent render count: {++parentRenderCount}");
|
builder.AddContent(2, $"Parent render count: {++parentRenderCount}");
|
||||||
});
|
});
|
||||||
var parentComponentId = renderer.AssignComponentId(parent);
|
var parentComponentId = renderer.AssignRootComponentId(parent);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
parent.TriggerRender();
|
parent.TriggerRender();
|
||||||
|
|
@ -891,7 +924,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var childComponentId = renderer.Batches.Single()
|
var childComponentId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -928,7 +961,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
// Arrange: Rendered with textbox enabled
|
// Arrange: Rendered with textbox enabled
|
||||||
var renderer = new TestRenderer();
|
var renderer = new TestRenderer();
|
||||||
var component = new BindPlusConditionalAttributeComponent();
|
var component = new BindPlusConditionalAttributeComponent();
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignRootComponentId(component);
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
var checkboxChangeEventHandlerId = renderer.Batches.Single()
|
var checkboxChangeEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -971,7 +1004,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseElement();
|
builder.CloseElement();
|
||||||
});
|
});
|
||||||
var renderer = new TestRenderer();
|
var renderer = new TestRenderer();
|
||||||
renderer.AssignComponentId(component);
|
renderer.AssignRootComponentId(component);
|
||||||
|
|
||||||
// Act: Update the attribute value on the parent
|
// Act: Update the attribute value on the parent
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
@ -1001,7 +1034,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
OnUpdateDisplay = _ => onAfterRenderCallCountLog.Add(component.OnAfterRenderCallCount)
|
OnUpdateDisplay = _ => onAfterRenderCallCountLog.Add(component.OnAfterRenderCallCount)
|
||||||
};
|
};
|
||||||
renderer.AssignComponentId(component);
|
renderer.AssignRootComponentId(component);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
component.TriggerRender();
|
component.TriggerRender();
|
||||||
|
|
@ -1042,7 +1075,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var renderer = new TestRenderer();
|
var renderer = new TestRenderer();
|
||||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
var parentComponentId = renderer.AssignRootComponentId(parentComponent);
|
||||||
|
|
||||||
// Act: First render
|
// Act: First render
|
||||||
parentComponent.TriggerRender();
|
parentComponent.TriggerRender();
|
||||||
|
|
@ -1077,8 +1110,8 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public new int AssignComponentId(IComponent component)
|
public new int AssignRootComponentId(IComponent component)
|
||||||
=> base.AssignComponentId(component);
|
=> base.AssignRootComponentId(component);
|
||||||
|
|
||||||
protected override void UpdateDisplay(in RenderBatch renderBatch)
|
protected override void UpdateDisplay(in RenderBatch renderBatch)
|
||||||
{
|
{
|
||||||
|
|
@ -1330,5 +1363,25 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class AncestryComponent : AutoRenderComponent
|
||||||
|
{
|
||||||
|
[Parameter] public int NumDescendants { get; private set; }
|
||||||
|
|
||||||
|
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||||
|
{
|
||||||
|
// Recursively renders more of the same until NumDescendants == 0
|
||||||
|
if (NumDescendants > 0)
|
||||||
|
{
|
||||||
|
builder.OpenComponent<AncestryComponent>(0);
|
||||||
|
builder.AddAttribute(1, nameof(NumDescendants), NumDescendants - 1);
|
||||||
|
builder.CloseComponent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.AddContent(1, "I'm the final descendant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -24,8 +24,8 @@ namespace Microsoft.AspNetCore.Blazor.Test.Helpers
|
||||||
public List<CapturedBatch> Batches { get; }
|
public List<CapturedBatch> Batches { get; }
|
||||||
= new List<CapturedBatch>();
|
= new List<CapturedBatch>();
|
||||||
|
|
||||||
public new int AssignComponentId(IComponent component)
|
public new int AssignRootComponentId(IComponent component)
|
||||||
=> base.AssignComponentId(component);
|
=> base.AssignRootComponentId(component);
|
||||||
|
|
||||||
public new void DispatchEvent(int componentId, int eventHandlerId, UIEventArgs args)
|
public new void DispatchEvent(int componentId, int eventHandlerId, UIEventArgs args)
|
||||||
=> base.DispatchEvent(componentId, eventHandlerId, args);
|
=> base.DispatchEvent(componentId, eventHandlerId, args);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue