Support "Region" frames in diffing

This commit is contained in:
Steve Sanderson 2018-02-14 22:45:19 +00:00
parent a9822216f1
commit 848f24536a
2 changed files with 158 additions and 0 deletions

View File

@ -247,6 +247,15 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
break;
}
case RenderTreeFrameType.Region:
{
AppendDiffEntriesForRange(
ref diffContext,
oldFrameIndex + 1, oldFrameIndex + oldFrame.RegionSubtreeLength,
newFrameIndex + 1, newFrameIndex + newFrame.RegionSubtreeLength);
break;
}
case RenderTreeFrameType.Component:
{
if (oldFrame.ComponentType == newFrame.ComponentType)
@ -328,6 +337,17 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
diffContext.SiblingIndex++;
break;
}
case RenderTreeFrameType.Region:
{
var regionChildFrameIndex = newFrameIndex + 1;
var regionChildFrameEndIndexExcl = newFrameIndex + newFrame.RegionSubtreeLength;
while (regionChildFrameIndex < regionChildFrameEndIndexExcl)
{
InsertNewFrame(ref diffContext, regionChildFrameIndex);
regionChildFrameIndex = NextSiblingIndex(newTree[regionChildFrameIndex], regionChildFrameIndex);
}
break;
}
case RenderTreeFrameType.Text:
{
var referenceFrameIndex = diffContext.ReferenceFrames.Append(newFrame);
@ -361,6 +381,17 @@ namespace Microsoft.AspNetCore.Blazor.RenderTree
diffContext.Edits.Append(RenderTreeEdit.RemoveFrame(diffContext.SiblingIndex));
break;
}
case RenderTreeFrameType.Region:
{
var regionChildFrameIndex = oldFrameIndex + 1;
var regionChildFrameEndIndexExcl = oldFrameIndex + oldFrame.RegionSubtreeLength;
while (regionChildFrameIndex < regionChildFrameEndIndexExcl)
{
RemoveOldFrame(ref diffContext, regionChildFrameIndex);
regionChildFrameIndex = NextSiblingIndex(oldTree[regionChildFrameIndex], regionChildFrameIndex);
}
break;
}
case RenderTreeFrameType.Text:
{
diffContext.Edits.Append(RenderTreeEdit.RemoveFrame(diffContext.SiblingIndex));

View File

@ -579,6 +579,133 @@ namespace Microsoft.AspNetCore.Blazor.Test
AssertFrame.Text(referenceFrames[0], "text2modified", 11);
}
[Fact]
public void PassesThroughRegionsInsidePrependedElements()
{
// Arrange
oldTree.AddText(0, "Will not change");
newTree.AddText(0, "Will not change");
newTree.OpenElement(1, "root");
newTree.OpenRegion(2);
newTree.AddText(0, "text1");
newTree.CloseRegion();
newTree.CloseElement();
// Act
var (result, referenceFrames) = GetSingleUpdatedComponent();
// Assert
Assert.Collection(result.Edits,
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 1);
Assert.Equal(0, entry.ReferenceFrameIndex);
});
Assert.Collection(referenceFrames,
frame => AssertFrame.Element(frame, "root", 3, 1),
frame => AssertFrame.Region(frame, 2, 2),
frame => AssertFrame.Text(frame, "text1"));
}
[Fact]
public void RecognizesInsertedRegions()
{
// Arrange
oldTree.AddText(1, "Start");
oldTree.AddText(3, "End");
newTree.AddText(1, "Start");
newTree.OpenRegion(2);
newTree.AddText(4, "Text inside region"); // Sequence number is unrelated to outside the region
newTree.OpenRegion(5);
newTree.AddText(6, "Text inside nested region");
newTree.CloseRegion();
newTree.CloseRegion();
newTree.AddText(3, "End");
// Act
var (result, referenceFrames) = GetSingleUpdatedComponent();
// Assert
Assert.Collection(result.Edits,
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 1);
AssertFrame.Text(
referenceFrames[entry.ReferenceFrameIndex], "Text inside region");
},
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 2);
AssertFrame.Text(
referenceFrames[entry.ReferenceFrameIndex], "Text inside nested region");
});
}
[Fact]
public void RecognizesRemovedRegions()
{
// Arrange
oldTree.AddText(1, "Start");
oldTree.OpenRegion(2);
oldTree.AddText(4, "Text inside region"); // Sequence number is unrelated to outside the region
oldTree.OpenRegion(5);
oldTree.AddText(6, "Text inside nested region");
oldTree.CloseRegion();
oldTree.CloseRegion();
oldTree.AddText(3, "End");
newTree.AddText(1, "Start");
newTree.AddText(3, "End");
// Act
var (result, referenceFrames) = GetSingleUpdatedComponent();
// Assert
Assert.Collection(result.Edits,
entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1),
entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 1));
}
[Fact]
public void RecognizesEquivalentRegions()
{
// Arrange
oldTree.AddText(1, "Start");
oldTree.OpenRegion(2);
oldTree.AddText(4, "Text inside region");
oldTree.AddText(5, "Text to move");
oldTree.OpenRegion(6);
oldTree.CloseRegion();
oldTree.CloseRegion();
oldTree.AddText(3, "End");
newTree.AddText(1, "Start");
newTree.OpenRegion(2);
newTree.AddText(4, "Changed text inside region");
newTree.OpenRegion(6);
newTree.AddText(5, "Text to move"); // Although it's the same sequence and content, it's now in a different region so not the same
newTree.CloseRegion();
newTree.CloseRegion();
newTree.AddText(3, "End");
// Act
var (result, referenceFrames) = GetSingleUpdatedComponent();
// Assert
Assert.Collection(result.Edits,
entry =>
{
AssertEdit(entry, RenderTreeEditType.UpdateText, 1);
AssertFrame.Text(
referenceFrames[entry.ReferenceFrameIndex], "Changed text inside region");
},
entry => AssertEdit(entry, RenderTreeEditType.RemoveFrame, 2),
entry =>
{
AssertEdit(entry, RenderTreeEditType.PrependFrame, 2);
AssertFrame.Text(
referenceFrames[entry.ReferenceFrameIndex], "Text to move");
});
}
[Fact]
public void InstantiatesChildComponentsForInsertedFrames()
{