diff --git a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts
index 09168332aa..1087f182db 100644
--- a/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts
+++ b/src/Microsoft.AspNetCore.Blazor.Browser.JS/src/Rendering/BrowserRenderer.ts
@@ -229,7 +229,7 @@ function removeAttributeFromDOM(parent: Element, childIndex: number, attributeNa
element.removeAttribute(attributeName);
}
-function raiseEvent(browserRendererId: number, componentId: number, renderTreeFrameIndex: number, eventInfoType: EventInfoType, eventInfo: any) {
+function raiseEvent(browserRendererId: number, componentId: number, referenceTreeFrameIndex: number, eventInfoType: EventInfoType, eventInfo: any) {
if (!raiseEventMethod) {
raiseEventMethod = platform.findMethod(
'Microsoft.AspNetCore.Blazor.Browser', 'Microsoft.AspNetCore.Blazor.Browser.Rendering', 'BrowserRendererEventDispatcher', 'DispatchEvent'
@@ -239,7 +239,7 @@ function raiseEvent(browserRendererId: number, componentId: number, renderTreeFr
const eventDescriptor = {
BrowserRendererId: browserRendererId,
ComponentId: componentId,
- RenderTreeFrameIndex: renderTreeFrameIndex,
+ ReferenceTreeFrameIndex: referenceTreeFrameIndex,
EventArgsType: eventInfoType
};
diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs
index 49d5091672..947af8a3e4 100644
--- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs
+++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRenderer.cs
@@ -32,8 +32,8 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
_browserRendererId = BrowserRendererRegistry.Add(this);
}
- internal void DispatchBrowserEvent(int componentId, int renderTreeIndex, UIEventArgs eventArgs)
- => DispatchEvent(componentId, renderTreeIndex, eventArgs);
+ internal void DispatchBrowserEvent(int componentId, int referenceTreeIndex, UIEventArgs eventArgs)
+ => DispatchEvent(componentId, referenceTreeIndex, eventArgs);
internal void RenderNewBatchInternal(int componentId)
=> RenderNewBatch(componentId);
diff --git a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs
index a82582a3a8..51cab8fa7c 100644
--- a/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs
+++ b/src/Microsoft.AspNetCore.Blazor.Browser/Rendering/BrowserRendererEventDispatcher.cs
@@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
var browserRenderer = BrowserRendererRegistry.Find(eventDescriptor.BrowserRendererId);
browserRenderer.DispatchBrowserEvent(
eventDescriptor.ComponentId,
- eventDescriptor.RenderTreeFrameIndex,
+ eventDescriptor.ReferenceTreeFrameIndex,
eventArgs);
}
@@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
{
public int BrowserRendererId { get; set; }
public int ComponentId { get; set; }
- public int RenderTreeFrameIndex { get; set; }
+ public int ReferenceTreeFrameIndex { get; set; }
public string EventArgsType { get; set; }
}
}
diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/ArrayBuilder.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/ArrayBuilder.cs
index d11c136fc6..1a68fcdf5a 100644
--- a/src/Microsoft.AspNetCore.Blazor/RenderTree/ArrayBuilder.cs
+++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/ArrayBuilder.cs
@@ -51,15 +51,40 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
/// Appends a new item, automatically resizing the underlying array if necessary.
///
/// The item to append.
+ /// The index of the appended item.
[MethodImpl(MethodImplOptions.AggressiveInlining)] // Just like System.Collections.Generic.List
- public void Append(in T item)
+ public int Append(in T item)
{
if (_itemsInUse == _items.Length)
{
SetCapacity(_itemsInUse * 2, preserveContents: true);
}
- _items[_itemsInUse++] = item;
+ var indexOfAppendedItem = _itemsInUse++;
+ _items[indexOfAppendedItem] = item;
+ return indexOfAppendedItem;
+ }
+
+ internal int Append(T[] source, int startIndex, int length)
+ {
+ // Expand storage if needed. Using same doubling approach as would
+ // be used if you inserted the items one-by-one.
+ var requiredCapacity = _itemsInUse + length;
+ if (_items.Length < requiredCapacity)
+ {
+ var candidateCapacity = _itemsInUse * 2;
+ while (candidateCapacity < requiredCapacity)
+ {
+ candidateCapacity *= 2;
+ }
+
+ SetCapacity(candidateCapacity, preserveContents: true);
+ }
+
+ Array.Copy(source, startIndex, _items, _itemsInUse, length);
+ var startIndexOfAppendedItems = _itemsInUse;
+ _itemsInUse += length;
+ return startIndexOfAppendedItems;
}
///
@@ -94,9 +119,9 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
{
SetCapacity((previousItemsInUse + _items.Length) / 2, preserveContents: false);
}
- else
+ else if (previousItemsInUse > 0)
{
- Array.Clear(_items, 0, _itemsInUse); // Release to GC
+ Array.Clear(_items, 0, previousItemsInUse); // Release to GC
}
}
diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs
index 7da223a010..d8ff75ec59 100644
--- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs
+++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiff.cs
@@ -1,13 +1,10 @@
// 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.
-using System;
-
namespace Microsoft.AspNetCore.Blazor.RenderTree
{
///
- /// Describes changes to a component's render tree between successive renders,
- /// as well as the resulting state.
+ /// Describes changes to a component's render tree between successive renders.
///
public readonly struct RenderTreeDiff
{
@@ -22,19 +19,20 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
public ArrayRange Edits { get; }
///
- /// Gets the latest render tree. That is, the result of applying the
- /// to the previous state.
+ /// Gets render frames that may be referenced by entries in .
+ /// For example, edit entries of type
+ /// will point to an entry in this array to specify the subtree to be prepended.
///
- public ArrayRange CurrentState { get; }
+ public ArrayRange ReferenceFrames { get; }
internal RenderTreeDiff(
int componentId,
ArrayRange entries,
- ArrayRange referenceTree)
+ ArrayRange referenceFrames)
{
ComponentId = componentId;
Edits = entries;
- CurrentState = referenceTree;
+ ReferenceFrames = referenceFrames;
}
}
}
diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs
index a432cabd3e..138462758f 100644
--- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs
+++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeDiffComputer.cs
@@ -12,6 +12,7 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
{
private readonly Renderer _renderer;
private readonly ArrayBuilder _entries = new ArrayBuilder(10);
+ private readonly ArrayBuilder _referenceFrames = new ArrayBuilder(10);
public RenderTreeDiffComputer(Renderer renderer)
{
@@ -31,13 +32,14 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
ArrayRange newTree)
{
_entries.Clear();
+ _referenceFrames.Clear();
var siblingIndex = 0;
var slotId = batchBuilder.ReserveUpdatedComponentSlotId();
AppendDiffEntriesForRange(batchBuilder, oldTree.Array, 0, oldTree.Count, newTree.Array, 0, newTree.Count, ref siblingIndex);
batchBuilder.SetUpdatedComponent(
slotId,
- new RenderTreeDiff(componentId, _entries.ToRange(), newTree));
+ new RenderTreeDiff(componentId, _entries.ToRange(), _referenceFrames.ToRange()));
}
private void AppendDiffEntriesForRange(
@@ -136,7 +138,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
var newFrameType = newFrame.FrameType;
if (newFrameType == RenderTreeFrameType.Attribute)
{
- Append(RenderTreeEdit.SetAttribute(siblingIndex, newStartIndex));
+ var referenceFrameIndex = _referenceFrames.Append(newFrame);
+ Append(RenderTreeEdit.SetAttribute(siblingIndex, referenceFrameIndex));
newStartIndex++;
}
else
@@ -146,7 +149,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
InstantiateChildComponents(batchBuilder, newTree, newStartIndex);
}
- Append(RenderTreeEdit.PrependFrame(siblingIndex, newStartIndex));
+ var referenceFrameIndex = AppendSubtreeToReferenceFrames(newTree, newStartIndex);
+ Append(RenderTreeEdit.PrependFrame(siblingIndex, referenceFrameIndex));
newStartIndex = NextSiblingIndex(newFrame, newStartIndex);
siblingIndex++;
}
@@ -180,6 +184,35 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
}
}
+ public UIEventHandler TemporaryGetEventHandlerMethod(int referenceFrameIndex)
+ {
+ // TODO: Change how event handlers are referenced
+ // The approach used here is invalid. We can't really assume that the event handler exists
+ // in the most recent diff's _referenceFrames. Nor can we assume that its index in the
+ // ComponentState's _renderTreeBuilderCurrent frames array is unchanged (any number of rerenders
+ // might have taken place since then, inserting frames before it, but not actually changing
+ // the delegate instance and therefore not including it in any _referenceFrames).
+ // Need some way of referencing event handlers that is independent of this.
+ var eventHandler = _referenceFrames.Buffer[referenceFrameIndex].AttributeValue as UIEventHandler;
+ return eventHandler
+ ?? throw new ArgumentException($"The reference frame at index {referenceFrameIndex} does not specify a {nameof(UIEventHandler)}.");
+ }
+
+ private int AppendSubtreeToReferenceFrames(RenderTreeFrame[] fromTree, int fromIndex)
+ {
+ ref var rootFrame = ref fromTree[fromIndex];
+ var subtreeLength = rootFrame.ElementSubtreeLength;
+ if (subtreeLength == 0)
+ {
+ // It's just a single frame (e.g., a text frame)
+ return _referenceFrames.Append(rootFrame);
+ }
+ else
+ {
+ return _referenceFrames.Append(fromTree, fromIndex, subtreeLength);
+ }
+ }
+
private void UpdateRetainedChildComponent(
RenderBatchBuilder batchBuilder,
RenderTreeFrame[] oldTree, int oldComponentIndex,
@@ -340,7 +373,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
var newText = newFrame.TextContent;
if (!string.Equals(oldText, newText, StringComparison.Ordinal))
{
- Append(RenderTreeEdit.UpdateText(siblingIndex, newFrameIndex));
+ var referenceFrameIndex = _referenceFrames.Append(newFrame);
+ Append(RenderTreeEdit.UpdateText(siblingIndex, referenceFrameIndex));
}
siblingIndex++;
break;
@@ -390,7 +424,9 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
// Elements with different names are treated as completely unrelated
InstantiateChildComponents(batchBuilder, newTree, newFrameIndex);
DisposeChildComponents(batchBuilder, oldTree, oldFrameIndex);
- Append(RenderTreeEdit.PrependFrame(siblingIndex, newFrameIndex));
+
+ var referenceFrameIndex = AppendSubtreeToReferenceFrames(newTree, newFrameIndex);
+ Append(RenderTreeEdit.PrependFrame(siblingIndex, referenceFrameIndex));
siblingIndex++;
Append(RenderTreeEdit.RemoveFrame(siblingIndex));
}
@@ -415,7 +451,9 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
// Child components of different types are treated as completely unrelated
InstantiateChildComponents(batchBuilder, newTree, newFrameIndex);
DisposeChildComponents(batchBuilder, oldTree, oldFrameIndex);
- Append(RenderTreeEdit.PrependFrame(siblingIndex, newFrameIndex));
+
+ var referenceFrameIndex = AppendSubtreeToReferenceFrames(newTree, newFrameIndex);
+ Append(RenderTreeEdit.PrependFrame(siblingIndex, referenceFrameIndex));
siblingIndex++;
Append(RenderTreeEdit.RemoveFrame(siblingIndex));
}
@@ -432,7 +470,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
var valueChanged = !Equals(oldFrame.AttributeValue, newFrame.AttributeValue);
if (valueChanged)
{
- Append(RenderTreeEdit.SetAttribute(siblingIndex, newFrameIndex));
+ var referenceFrameIndex = _referenceFrames.Append(newFrame);
+ Append(RenderTreeEdit.SetAttribute(siblingIndex, referenceFrameIndex));
}
}
else
@@ -440,7 +479,8 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
// Since this code path is never reachable for Razor components (because you
// can't have two different attribute names from the same source sequence), we
// could consider removing the 'name equality' check entirely for perf
- Append(RenderTreeEdit.SetAttribute(siblingIndex, newFrameIndex));
+ var referenceFrameIndex = _referenceFrames.Append(newFrame);
+ Append(RenderTreeEdit.SetAttribute(siblingIndex, referenceFrameIndex));
Append(RenderTreeEdit.RemoveAttribute(siblingIndex, oldName));
}
break;
diff --git a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs
index 2b641bcad5..ffefbd510a 100644
--- a/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs
+++ b/src/Microsoft.AspNetCore.Blazor/RenderTree/RenderTreeEdit.cs
@@ -19,11 +19,11 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
public readonly int SiblingIndex;
///
- /// Gets the index of related data in an associated render tree. For example, if the
+ /// Gets the index of related data in an associated render frames array. For example, if the
/// value is , gets the
/// index of the new frame data in an associated render tree.
///
- public readonly int NewTreeIndex;
+ public readonly int ReferenceFrameIndex;
///
/// If the value is ,
@@ -42,11 +42,11 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
SiblingIndex = siblingIndex;
}
- private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, int newTreeIndex) : this()
+ private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, int referenceFrameIndex) : this()
{
Type = type;
SiblingIndex = siblingIndex;
- NewTreeIndex = newTreeIndex;
+ ReferenceFrameIndex = referenceFrameIndex;
}
private RenderTreeEdit(RenderTreeEditType type, int siblingIndex, string removedAttributeName) : this()
@@ -59,14 +59,14 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
internal static RenderTreeEdit RemoveFrame(int siblingIndex)
=> new RenderTreeEdit(RenderTreeEditType.RemoveFrame, siblingIndex);
- internal static RenderTreeEdit PrependFrame(int siblingIndex, int newTreeIndex)
- => new RenderTreeEdit(RenderTreeEditType.PrependFrame, siblingIndex, newTreeIndex);
+ internal static RenderTreeEdit PrependFrame(int siblingIndex, int referenceFrameIndex)
+ => new RenderTreeEdit(RenderTreeEditType.PrependFrame, siblingIndex, referenceFrameIndex);
- internal static RenderTreeEdit UpdateText(int siblingIndex, int newTreeIndex)
- => new RenderTreeEdit(RenderTreeEditType.UpdateText, siblingIndex, newTreeIndex);
+ internal static RenderTreeEdit UpdateText(int siblingIndex, int referenceFrameIndex)
+ => new RenderTreeEdit(RenderTreeEditType.UpdateText, siblingIndex, referenceFrameIndex);
- internal static RenderTreeEdit SetAttribute(int siblingIndex, int newTreeIndex)
- => new RenderTreeEdit(RenderTreeEditType.SetAttribute, siblingIndex, newTreeIndex);
+ internal static RenderTreeEdit SetAttribute(int siblingIndex, int referenceFrameIndex)
+ => new RenderTreeEdit(RenderTreeEditType.SetAttribute, siblingIndex, referenceFrameIndex);
internal static RenderTreeEdit RemoveAttribute(int siblingIndex, string name)
=> new RenderTreeEdit(RenderTreeEditType.RemoveAttribute, siblingIndex, name);
diff --git a/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs b/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs
index 3c8c441f12..119fb3e058 100644
--- a/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs
+++ b/src/Microsoft.AspNetCore.Blazor/Rendering/ComponentState.cs
@@ -58,22 +58,16 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
///
/// Invokes the handler corresponding to an event.
///
- /// The index of the current render tree frame that holds the event handler to be invoked.
+ /// The index of the frame in the latest diff reference tree that holds the event handler to be invoked.
/// Arguments to be passed to the event handler.
- public void DispatchEvent(int renderTreeIndex, UIEventArgs eventArgs)
+ public void DispatchEvent(int referenceTreeIndex, UIEventArgs eventArgs)
{
if (eventArgs == null)
{
throw new ArgumentNullException(nameof(eventArgs));
}
- var frames = _renderTreeBuilderCurrent.GetFrames();
- var eventHandler = frames.Array[renderTreeIndex].AttributeValue as UIEventHandler;
- if (eventHandler == null)
- {
- throw new ArgumentException($"The render tree frame at index {renderTreeIndex} does not specify a {nameof(UIEventHandler)}.");
- }
-
+ var eventHandler = _diffComputer.TemporaryGetEventHandlerMethod(referenceTreeIndex);
eventHandler.Invoke(eventArgs);
// After any event, we synchronously re-render. Most of the time this means that
diff --git a/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs b/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs
index 7c2d3fa4d1..75902d6a85 100644
--- a/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs
+++ b/src/Microsoft.AspNetCore.Blazor/Rendering/Renderer.cs
@@ -106,10 +106,10 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
/// Notifies the specified component that an event has occurred.
///
/// The unique identifier for the component within the scope of this .
- /// The index into the component's current render tree that specifies which event handler to invoke.
+ /// The index into the component's latest diff reference tree that specifies which event handler to invoke.
/// Arguments to be passed to the event handler.
- protected void DispatchEvent(int componentId, int renderTreeIndex, UIEventArgs eventArgs)
- => GetRequiredComponentState(componentId).DispatchEvent(renderTreeIndex, eventArgs);
+ protected void DispatchEvent(int componentId, int referenceTreeIndex, UIEventArgs eventArgs)
+ => GetRequiredComponentState(componentId).DispatchEvent(referenceTreeIndex, eventArgs);
internal void InstantiateChildComponent(RenderTreeFrame[] frames, int componentFrameIndex)
{
diff --git a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs
index 6b80b81db9..cdcd043f03 100644
--- a/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs
+++ b/test/Microsoft.AspNetCore.Blazor.Test/RenderTreeDiffComputerTest.cs
@@ -74,7 +74,8 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 1);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
+ AssertFrame.Text(result.ReferenceFrames.Array[0], "text1", 1);
});
}
@@ -120,12 +121,12 @@ namespace Microsoft.AspNetCore.Blazor.Test
public void RecognizesTrailingSequenceWithinLoopBlockBeingAppended()
{
// Arrange
- oldTree.AddText(0, "x"); // Loop start
- oldTree.AddText(0, "x"); // Loop start
- newTree.AddText(0, "x"); // Loop start
- newTree.AddText(1, "x"); // Will be added
- newTree.AddText(2, "x"); // Will be added
- newTree.AddText(0, "x"); // Loop start
+ oldTree.AddText(10, "x"); // Loop start
+ oldTree.AddText(10, "x"); // Loop start
+ newTree.AddText(10, "x"); // Loop start
+ newTree.AddText(11, "x"); // Will be added
+ newTree.AddText(12, "x"); // Will be added
+ newTree.AddText(10, "x"); // Loop start
// Act
var result = GetSingleUpdatedComponent();
@@ -135,13 +136,16 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 1);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 2);
- Assert.Equal(2, entry.NewTreeIndex);
+ Assert.Equal(1, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "x", 11),
+ frame => AssertFrame.Text(frame, "x", 12));
}
[Fact]
@@ -168,12 +172,12 @@ namespace Microsoft.AspNetCore.Blazor.Test
public void RecognizesTrailingLoopBlockBeingAdded()
{
// Arrange
- oldTree.AddText(0, "x");
- oldTree.AddText(1, "x");
- newTree.AddText(0, "x");
- newTree.AddText(1, "x");
- newTree.AddText(0, "x"); // Will be added
- newTree.AddText(1, "x"); // Will be added
+ oldTree.AddText(10, "x");
+ oldTree.AddText(11, "x");
+ newTree.AddText(10, "x");
+ newTree.AddText(11, "x");
+ newTree.AddText(10, "x"); // Will be added
+ newTree.AddText(11, "x"); // Will be added
// Act
var result = GetSingleUpdatedComponent();
@@ -183,25 +187,28 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 2);
- Assert.Equal(2, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 3);
- Assert.Equal(3, entry.NewTreeIndex);
+ Assert.Equal(1, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "x", 10),
+ frame => AssertFrame.Text(frame, "x", 11));
}
[Fact]
public void RecognizesLeadingLoopBlockItemsBeingAdded()
{
// Arrange
- oldTree.AddText(2, "x");
- oldTree.AddText(2, "x"); // Note that the '0' and '1' items are not present on this iteration
- newTree.AddText(2, "x");
- newTree.AddText(0, "x");
- newTree.AddText(1, "x");
- newTree.AddText(2, "x");
+ oldTree.AddText(12, "x");
+ oldTree.AddText(12, "x"); // Note that the '0' and '1' items are not present on this iteration
+ newTree.AddText(12, "x");
+ newTree.AddText(10, "x");
+ newTree.AddText(11, "x");
+ newTree.AddText(12, "x");
// Act
var result = GetSingleUpdatedComponent();
@@ -211,13 +218,16 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 1);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 2);
- Assert.Equal(2, entry.NewTreeIndex);
+ Assert.Equal(1, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "x", 10),
+ frame => AssertFrame.Text(frame, "x", 11));
}
[Fact]
@@ -273,12 +283,12 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.UpdateText, 0);
- Assert.Equal(0, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.UpdateText, 1);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(1, entry.ReferenceFrameIndex);
});
}
@@ -303,7 +313,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 0);
- Assert.Equal(0, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1));
}
@@ -333,8 +343,8 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 0);
- Assert.Equal(0, entry.NewTreeIndex);
- Assert.IsType(updatedComponent1.CurrentState.Array[0].Component);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
+ Assert.IsType(updatedComponent1.ReferenceFrames.Array[0].Component);
},
entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1));
@@ -344,7 +354,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 0);
- Assert.Equal(0, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
});
}
@@ -368,8 +378,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.SetAttribute, 0);
- Assert.Equal(2, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Attribute(frame, "added", "added value"));
}
[Fact]
@@ -417,8 +429,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.SetAttribute, 0);
- Assert.Equal(2, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Attribute(frame, "will change", "did change value"));
}
[Fact]
@@ -445,8 +459,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.SetAttribute, 0);
- Assert.Equal(2, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Attribute(frame, "will change", addedHandler));
}
[Fact]
@@ -468,13 +484,15 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.SetAttribute, 0);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.RemoveAttribute, 0);
Assert.Equal("oldname", entry.RemovedAttributeName);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Attribute(frame, "newname", "same value"));
}
[Fact]
@@ -510,11 +528,13 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.UpdateText, 0);
- Assert.Equal(4, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0),
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0),
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0));
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "grandchild new text", 13));
}
[Fact]
@@ -548,9 +568,11 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.UpdateText, 0);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0));
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "Text that has changed", 11));
}
[Fact]
@@ -574,8 +596,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.UpdateText, 1);
- Assert.Equal(1, entry.NewTreeIndex);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
});
+ Assert.Collection(result.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "text2modified", 11));
}
[Fact]
@@ -606,35 +630,30 @@ namespace Microsoft.AspNetCore.Blazor.Test
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 0);
- Assert.Equal(2, entry.NewTreeIndex);
-
- var newTreeFrame = newTree.GetFrames().Array[entry.NewTreeIndex];
- Assert.Equal(0, newTreeFrame.ComponentId);
- Assert.IsType(newTreeFrame.Component);
+ Assert.Equal(0, entry.ReferenceFrameIndex);
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 1);
- Assert.Equal(3, entry.NewTreeIndex);
-
- var newTreeFrame = newTree.GetFrames().Array[entry.NewTreeIndex];
- Assert.Equal(1, newTreeFrame.ComponentId);
- Assert.IsType(newTreeFrame.Component);
+ Assert.Equal(1, entry.ReferenceFrameIndex);
},
entry => AssertEdit(entry, RenderTreeEditType.StepOut, 0));
+ Assert.Collection(firstComponentDiff.ReferenceFrames,
+ frame => AssertFrame.ComponentWithInstance(frame, 0, 12),
+ frame => AssertFrame.ComponentWithInstance(frame, 1, 13));
// Second in batch is the first child component
var secondComponentDiff = renderBatch.UpdatedComponents.Array[1];
Assert.Equal(0, secondComponentDiff.ComponentId);
Assert.Empty(secondComponentDiff.Edits); // Because FakeComponent produces no frames
- Assert.Empty(secondComponentDiff.CurrentState); // Because FakeComponent produces no frames
+ Assert.Empty(secondComponentDiff.ReferenceFrames); // Because FakeComponent produces no frames
// Third in batch is the second child component
var thirdComponentDiff = renderBatch.UpdatedComponents.Array[2];
Assert.Equal(1, thirdComponentDiff.ComponentId);
Assert.Collection(thirdComponentDiff.Edits,
entry => AssertEdit(entry, RenderTreeEditType.PrependFrame, 0));
- Assert.Collection(thirdComponentDiff.CurrentState,
+ Assert.Collection(thirdComponentDiff.ReferenceFrames,
frame => AssertFrame.Text(frame, $"Hello from {nameof(FakeComponent2)}"));
}
@@ -776,7 +795,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
var diffForChildComponent = batch.UpdatedComponents.Array[1];
// Assert
- Assert.Collection(diffForChildComponent.CurrentState,
+ Assert.Collection(diffForChildComponent.ReferenceFrames,
frame => AssertFrame.Text(frame, "Notifications: 1", 0));
}
@@ -799,10 +818,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
// Act/Assert 0: Initial render
var batch0 = GetRenderedBatch(new RenderTreeBuilder(renderer), oldTree);
var diffForChildComponent0 = batch0.UpdatedComponents.Array[1];
- var childComponentFrame = batch0.UpdatedComponents.Array[0].CurrentState.Array[0];
+ var childComponentFrame = batch0.UpdatedComponents.Array[0].ReferenceFrames.Array[0];
var childComponentInstance = (HandlePropertiesChangedComponent)childComponentFrame.Component;
Assert.Equal(1, childComponentInstance.NotificationsCount);
- Assert.Collection(diffForChildComponent0.CurrentState,
+ Assert.Collection(diffForChildComponent0.ReferenceFrames,
frame => AssertFrame.Text(frame, "Notifications: 1", 0));
// Act/Assert 1: If properties didn't change, we don't notify
@@ -813,7 +832,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
var batch2 = GetRenderedBatch(newTree1, newTree2);
var diffForChildComponent2 = batch2.UpdatedComponents.Array[1];
Assert.Equal(2, childComponentInstance.NotificationsCount);
- Assert.Collection(diffForChildComponent2.CurrentState,
+ Assert.Collection(diffForChildComponent2.ReferenceFrames,
frame => AssertFrame.Text(frame, "Notifications: 2", 0));
}
diff --git a/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs b/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs
index 540016c0b3..2429cc1411 100644
--- a/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs
+++ b/test/Microsoft.AspNetCore.Blazor.Test/RendererTest.cs
@@ -31,7 +31,14 @@ namespace Microsoft.AspNetCore.Blazor.Test
renderer.RenderNewBatch(componentId);
// Assert
- Assert.Collection(renderer.Batches.Single().RenderTreesByComponentId[componentId],
+ var diff = renderer.Batches.Single().DiffsByComponentId[componentId].Single();
+ Assert.Collection(diff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(diff.ReferenceFrames,
frame => AssertFrame.Element(frame, "my element", 2),
frame => AssertFrame.Text(frame, "some text"));
}
@@ -52,15 +59,23 @@ namespace Microsoft.AspNetCore.Blazor.Test
// Act/Assert
var componentId = renderer.AssignComponentId(component);
renderer.RenderNewBatch(componentId);
- var componentFrame = renderer.Batches.Single().RenderTreesByComponentId[componentId]
+ var batch = renderer.Batches.Single();
+ var componentFrame = batch.DiffsByComponentId[componentId].Single().ReferenceFrames
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
var nestedComponentId = componentFrame.ComponentId;
+ var nestedComponentDiff = batch.DiffsByComponentId[nestedComponentId].Single();
// The nested component exists
Assert.IsType(componentFrame.Component);
// The nested component was rendered as part of the batch
- Assert.Collection(renderer.Batches.Single().RenderTreesByComponentId[nestedComponentId],
+ Assert.Collection(nestedComponentDiff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(nestedComponentDiff.ReferenceFrames,
frame => AssertFrame.Text(frame, "Nested component output"));
}
@@ -74,13 +89,27 @@ namespace Microsoft.AspNetCore.Blazor.Test
// Act/Assert: first render
renderer.RenderNewBatch(componentId);
- Assert.Collection(renderer.Batches.Single().RenderTreesByComponentId[componentId],
+ var firstDiff = renderer.Batches.Single().DiffsByComponentId[componentId].Single();
+ Assert.Collection(firstDiff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(firstDiff.ReferenceFrames,
frame => AssertFrame.Text(frame, "Initial message"));
// Act/Assert: second render
component.Message = "Modified message";
renderer.RenderNewBatch(componentId);
- Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[componentId],
+ var secondDiff = renderer.Batches.Skip(1).Single().DiffsByComponentId[componentId].Single();
+ Assert.Collection(firstDiff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(firstDiff.ReferenceFrames,
frame => AssertFrame.Text(frame, "Modified message"));
}
@@ -96,21 +125,37 @@ namespace Microsoft.AspNetCore.Blazor.Test
});
var parentComponentId = renderer.AssignComponentId(parentComponent);
renderer.RenderNewBatch(parentComponentId);
- var nestedComponentFrame = renderer.Batches.Single().RenderTreesByComponentId[parentComponentId]
+ var nestedComponentFrame = renderer.Batches.Single().DiffsByComponentId[parentComponentId]
+ .Single()
+ .ReferenceFrames
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
var nestedComponent = (MessageComponent)nestedComponentFrame.Component;
var nestedComponentId = nestedComponentFrame.ComponentId;
- // Act/Assert: inital render
+ // Assert: inital render
nestedComponent.Message = "Render 1";
renderer.RenderNewBatch(nestedComponentId);
- Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[nestedComponentId],
+ var firstDiff = renderer.Batches[1].DiffsByComponentId[nestedComponentId].Single();
+ Assert.Collection(firstDiff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(firstDiff.ReferenceFrames,
frame => AssertFrame.Text(frame, "Render 1"));
// Act/Assert: re-render
nestedComponent.Message = "Render 2";
renderer.RenderNewBatch(nestedComponentId);
- Assert.Collection(renderer.Batches[2].RenderTreesByComponentId[nestedComponentId],
+ var secondDiff = renderer.Batches[2].DiffsByComponentId[nestedComponentId].Single();
+ Assert.Collection(firstDiff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(firstDiff.ReferenceFrames,
frame => AssertFrame.Text(frame, "Render 2"));
}
@@ -129,7 +174,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
renderer.RenderNewBatch(componentId);
var (eventHandlerFrameIndex, _) = FirstWithIndex(
- renderer.Batches.Single().RenderTreesByComponentId[componentId],
+ renderer.Batches.Single().DiffsByComponentId[componentId].Single().ReferenceFrames,
frame => frame.AttributeValue != null);
// Assert: Event not yet fired
@@ -157,7 +202,9 @@ namespace Microsoft.AspNetCore.Blazor.Test
renderer.RenderNewBatch(parentComponentId);
// Arrange: Render nested component
- var nestedComponentFrame = renderer.Batches.Single().RenderTreesByComponentId[parentComponentId]
+ var nestedComponentFrame = renderer.Batches.Single().DiffsByComponentId[parentComponentId]
+ .Single()
+ .ReferenceFrames
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
var nestedComponent = (EventComponent)nestedComponentFrame.Component;
nestedComponent.Handler = args => { receivedArgs = args; };
@@ -166,7 +213,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
// Find nested component's event handler ndoe
var (eventHandlerFrameIndex, _) = FirstWithIndex(
- renderer.Batches[1].RenderTreesByComponentId[nestedComponentId],
+ renderer.Batches[1].DiffsByComponentId[nestedComponentId].Single().ReferenceFrames,
frame => frame.AttributeValue != null);
// Assert: Event not yet fired
@@ -217,12 +264,12 @@ namespace Microsoft.AspNetCore.Blazor.Test
// Act/Assert: Render component in renderer1
renderer1.RenderNewBatch(renderer1ComponentId);
- Assert.True(renderer1.Batches.Single().RenderTreesByComponentId.ContainsKey(renderer1ComponentId));
+ Assert.True(renderer1.Batches.Single().DiffsByComponentId.ContainsKey(renderer1ComponentId));
Assert.Empty(renderer2.Batches);
// Act/Assert: Render same component in renderer2
renderer2.RenderNewBatch(renderer2ComponentId);
- Assert.True(renderer2.Batches.Single().RenderTreesByComponentId.ContainsKey(renderer2ComponentId));
+ Assert.True(renderer2.Batches.Single().DiffsByComponentId.ContainsKey(renderer2ComponentId));
}
[Fact]
@@ -313,18 +360,29 @@ namespace Microsoft.AspNetCore.Blazor.Test
var rootComponentId = renderer.AssignComponentId(component);
renderer.RenderNewBatch(rootComponentId);
- var nestedComponentInstance = (MessageComponent)renderer.Batches.Single().RenderTreesByComponentId[rootComponentId]
- .Single(frame => frame.FrameType == RenderTreeFrameType.Component)
- .Component;
+ var nestedComponentFrame = renderer.Batches.Single()
+ .DiffsByComponentId[rootComponentId]
+ .Single()
+ .ReferenceFrames
+ .Single(frame => frame.FrameType == RenderTreeFrameType.Component);
+ var nestedComponentInstance = (MessageComponent)nestedComponentFrame.Component;
// Act: Second render
message = "Modified message";
renderer.RenderNewBatch(rootComponentId);
// Assert
- Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[rootComponentId],
- frame => AssertFrame.Text(frame, "Modified message"),
- frame => Assert.Same(nestedComponentInstance, frame.Component));
+ var batch = renderer.Batches[1];
+ var diff = batch.DiffsByComponentId[rootComponentId].Single();
+ Assert.Collection(diff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(diff.ReferenceFrames,
+ frame => AssertFrame.Text(frame, "Modified message"));
+ Assert.False(batch.DiffsByComponentId.ContainsKey(nestedComponentFrame.ComponentId));
}
[Fact]
@@ -346,28 +404,25 @@ namespace Microsoft.AspNetCore.Blazor.Test
var rootComponentId = renderer.AssignComponentId(component);
renderer.RenderNewBatch(rootComponentId);
- var originalComponentInstance = (FakeComponent)renderer.Batches.Single().RenderTreesByComponentId[rootComponentId]
- .Single(frame => frame.FrameType == RenderTreeFrameType.Component)
- .Component;
+ var originalComponentFrame = renderer.Batches.Single().DiffsByComponentId[rootComponentId]
+ .Single()
+ .ReferenceFrames
+ .Single(frame => frame.FrameType == RenderTreeFrameType.Component);
+ var childComponentInstance = (FakeComponent)originalComponentFrame.Component;
// Assert 1: properties were assigned
- Assert.Equal(123, originalComponentInstance.IntProperty);
- Assert.Equal("String that will change", originalComponentInstance.StringProperty);
- Assert.Same(objectThatWillNotChange, originalComponentInstance.ObjectProperty);
+ Assert.Equal(123, childComponentInstance.IntProperty);
+ Assert.Equal("String that will change", childComponentInstance.StringProperty);
+ Assert.Same(objectThatWillNotChange, childComponentInstance.ObjectProperty);
// Act: Second render
firstRender = false;
renderer.RenderNewBatch(rootComponentId);
- var updatedComponentInstance = (FakeComponent)renderer.Batches[1].RenderTreesByComponentId[rootComponentId]
- .Single(frame => frame.FrameType == RenderTreeFrameType.Component)
- .Component;
-
// Assert
- Assert.Same(originalComponentInstance, updatedComponentInstance);
- Assert.Equal(256, updatedComponentInstance.IntProperty);
- Assert.Equal("String that did change", updatedComponentInstance.StringProperty);
- Assert.Same(objectThatWillNotChange, updatedComponentInstance.ObjectProperty);
+ Assert.Equal(256, childComponentInstance.IntProperty);
+ Assert.Equal("String that did change", childComponentInstance.StringProperty);
+ Assert.Same(objectThatWillNotChange, childComponentInstance.ObjectProperty);
}
[Fact]
@@ -386,19 +441,25 @@ namespace Microsoft.AspNetCore.Blazor.Test
var rootComponentId = renderer.AssignComponentId(component);
renderer.RenderNewBatch(rootComponentId);
- var childComponentId = renderer.Batches.Single().RenderTreesByComponentId[rootComponentId]
+ var childComponentId = renderer.Batches.Single().DiffsByComponentId[rootComponentId]
+ .Single()
+ .ReferenceFrames
.Single(frame => frame.FrameType == RenderTreeFrameType.Component)
.ComponentId;
// Act: Second render
firstRender = false;
renderer.RenderNewBatch(rootComponentId);
-
- var updatedComponentFrame = renderer.Batches[1].RenderTreesByComponentId[rootComponentId]
- .Single(frame => frame.FrameType == RenderTreeFrameType.Component);
+ var diff = renderer.Batches[1].DiffsByComponentId[childComponentId].Single();
// Assert
- Assert.Collection(renderer.Batches[1].RenderTreesByComponentId[updatedComponentFrame.ComponentId],
+ Assert.Collection(diff.Edits,
+ edit =>
+ {
+ Assert.Equal(RenderTreeEditType.UpdateText, edit.Type);
+ Assert.Equal(0, edit.ReferenceFrameIndex);
+ });
+ Assert.Collection(diff.ReferenceFrames,
frame => AssertFrame.Text(frame, "second"));
}
@@ -427,7 +488,9 @@ namespace Microsoft.AspNetCore.Blazor.Test
// Act/Assert 1: First render, capturing child component IDs
renderer.RenderNewBatch(rootComponentId);
- var childComponentIds = renderer.Batches.Single().RenderTreesByComponentId[rootComponentId]
+ var childComponentIds = renderer.Batches.Single().DiffsByComponentId[rootComponentId]
+ .Single()
+ .ReferenceFrames
.Where(frame => frame.FrameType == RenderTreeFrameType.Component)
.Select(frame => frame.ComponentId)
.ToList();
@@ -476,8 +539,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
for (var i = 0; i < renderBatch.UpdatedComponents.Count; i++)
{
ref var renderTreeDiff = ref renderBatch.UpdatedComponents.Array[i];
- capturedBatch.RenderTreesByComponentId[renderTreeDiff.ComponentId] =
- renderTreeDiff.CurrentState.ToArray();
+ capturedBatch.AddDiff(renderTreeDiff);
}
capturedBatch.DisposedComponentIDs = renderBatch.DisposedComponentIDs.ToList();
@@ -486,10 +548,20 @@ namespace Microsoft.AspNetCore.Blazor.Test
private class CapturedBatch
{
- public IDictionary RenderTreesByComponentId { get; }
- = new Dictionary();
+ public IDictionary> DiffsByComponentId { get; }
+ = new Dictionary>();
public IList DisposedComponentIDs { get; set; }
+
+ internal void AddDiff(RenderTreeDiff diff)
+ {
+ var componentId = diff.ComponentId;
+ if (!DiffsByComponentId.ContainsKey(componentId))
+ {
+ DiffsByComponentId.Add(componentId, new List());
+ }
+ DiffsByComponentId[componentId].Add(diff);
+ }
}
private class TestComponent : IComponent
diff --git a/test/shared/AssertFrame.cs b/test/shared/AssertFrame.cs
index ad2bd6b1cf..faa9b1d497 100644
--- a/test/shared/AssertFrame.cs
+++ b/test/shared/AssertFrame.cs
@@ -60,6 +60,13 @@ namespace Microsoft.AspNetCore.Blazor.Test.Shared
AssertFrame.Sequence(frame, sequence);
}
+ public static void ComponentWithInstance(RenderTreeFrame frame, int componentId, int? sequence = null) where T : IComponent
+ {
+ AssertFrame.Component(frame, sequence);
+ Assert.IsType(frame.Component);
+ Assert.Equal(componentId, frame.ComponentId);
+ }
+
public static void Whitespace(RenderTreeFrame frame, int? sequence = null)
{
Assert.Equal(RenderTreeFrameType.Text, frame.FrameType);
diff --git a/test/testapps/BasicTestApp/KeyPressEventComponent.cshtml b/test/testapps/BasicTestApp/KeyPressEventComponent.cshtml
index f929f23651..82a1e0fbfd 100644
--- a/test/testapps/BasicTestApp/KeyPressEventComponent.cshtml
+++ b/test/testapps/BasicTestApp/KeyPressEventComponent.cshtml
@@ -1,6 +1,6 @@
@using System.Collections.Generic
@using Microsoft.AspNetCore.Blazor.RenderTree
-Type here:
+Type here:
@foreach (var key in keysPressed)
{
@@ -11,7 +11,22 @@ Type here:
@functions {
List keysPressed = new List();
- void OnKeyPressed(UIEventArgs eventArgs)
+ // TODO: Fix this
+ // Currently, you can only trigger an event handler whose value changed in the most
+ // recent render cycle. That's because we reference the event handlers by their index
+ // into the current diff's ReferenceFrames array. We need some better mechanism of
+ // locating the delegates that is independent of whether the corresponding attribute
+ // changed in the last diff, and not assuming the attribute in the original render
+ // tree is still at the same index.
+ // Once that's fixed, remove the 'CreateNewDelegateInstance' method entirely and
+ // the 'irrelevantObject' arg from below, and simplify to onkeypress=@OnKeyPressed
+ UIEventHandler CreateNewDelegateInstance()
+ {
+ var irrelevantObject = new object();
+ return args => OnKeyPressed(args, irrelevantObject);
+ }
+
+ void OnKeyPressed(UIEventArgs eventArgs, object irrelevantObject)
{
keysPressed.Add(((UIKeyboardEventArgs)eventArgs).Key);
}