Various renames of diff-related types, plus XML docs for newly-public types.
This commit is contained in:
parent
7c30d51be9
commit
bea15241f2
|
|
@ -5,321 +5,20 @@ using System;
|
||||||
|
|
||||||
namespace Microsoft.Blazor.RenderTree
|
namespace Microsoft.Blazor.RenderTree
|
||||||
{
|
{
|
||||||
internal class RenderTreeDiff
|
/// <summary>
|
||||||
|
/// Describes changes to a component's render tree between successive renders.
|
||||||
|
/// </summary>
|
||||||
|
public struct RenderTreeDiff
|
||||||
{
|
{
|
||||||
private const int MinBufferLength = 10;
|
/// <summary>
|
||||||
private RenderTreeDiffEntry[] _entries = new RenderTreeDiffEntry[10];
|
/// Describes the render tree changes as a sequence of edit operations.
|
||||||
private int _entriesInUse;
|
/// </summary>
|
||||||
|
public RenderTreeEdit[] Entries { get; private set; }
|
||||||
|
|
||||||
public ArraySegment<RenderTreeDiffEntry> ComputeDifference(
|
/// <summary>
|
||||||
ArraySegment<RenderTreeNode> oldTree,
|
/// An array of <see cref="RenderTreeNode"/> structures that may be referred to
|
||||||
ArraySegment<RenderTreeNode> newTree)
|
/// by entries in the <see cref="Entries"/> property.
|
||||||
{
|
/// </summary>
|
||||||
_entriesInUse = 0;
|
public ArraySegment<RenderTreeNode> ReferenceTree { get; private set; }
|
||||||
AppendDiffEntriesForRange(oldTree.Array, 0, oldTree.Count, newTree.Array, 0, newTree.Count);
|
|
||||||
TrimTrailingContinueNodes();
|
|
||||||
|
|
||||||
// If the previous usage of the buffer showed that we have allocated
|
|
||||||
// much more space than needed, free up the excess memory
|
|
||||||
var shrinkToLength = Math.Max(MinBufferLength, _entries.Length / 2);
|
|
||||||
if (_entriesInUse < shrinkToLength)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _entries, shrinkToLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ArraySegment<RenderTreeDiffEntry>(_entries, 0, _entriesInUse);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AppendDiffEntriesForRange(
|
|
||||||
RenderTreeNode[] oldTree, int oldStartIndex, int oldEndIndexExcl,
|
|
||||||
RenderTreeNode[] newTree, int newStartIndex, int newEndIndexExcl)
|
|
||||||
{
|
|
||||||
var hasMoreOld = oldEndIndexExcl > oldStartIndex;
|
|
||||||
var hasMoreNew = newEndIndexExcl > newStartIndex;
|
|
||||||
var prevOldSeq = -1;
|
|
||||||
var prevNewSeq = -1;
|
|
||||||
while (hasMoreOld || hasMoreNew)
|
|
||||||
{
|
|
||||||
var oldSeq = hasMoreOld ? oldTree[oldStartIndex].Sequence : int.MaxValue;
|
|
||||||
var newSeq = hasMoreNew ? newTree[newStartIndex].Sequence : int.MaxValue;
|
|
||||||
|
|
||||||
if (oldSeq == newSeq)
|
|
||||||
{
|
|
||||||
AppendDiffEntriesForNodesWithSameSequence(oldTree, oldStartIndex, newTree, newStartIndex);
|
|
||||||
oldStartIndex = NextSiblingIndex(oldTree, oldStartIndex);
|
|
||||||
newStartIndex = NextSiblingIndex(newTree, newStartIndex);
|
|
||||||
hasMoreOld = oldEndIndexExcl > oldStartIndex;
|
|
||||||
hasMoreNew = newEndIndexExcl > newStartIndex;
|
|
||||||
prevOldSeq = oldSeq;
|
|
||||||
prevNewSeq = newSeq;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool treatAsInsert;
|
|
||||||
var oldLoopedBack = oldSeq <= prevOldSeq;
|
|
||||||
var newLoopedBack = newSeq <= prevNewSeq;
|
|
||||||
if (oldLoopedBack == newLoopedBack)
|
|
||||||
{
|
|
||||||
// Both sequences are proceeding through the same loop block, so do a simple
|
|
||||||
// preordered merge join (picking from whichever side brings us closer to being
|
|
||||||
// back in sync)
|
|
||||||
treatAsInsert = newSeq < oldSeq;
|
|
||||||
|
|
||||||
if (oldLoopedBack)
|
|
||||||
{
|
|
||||||
// If both old and new have now looped back, we must reset their 'looped back'
|
|
||||||
// tracker so we can treat them as proceeding through the same loop block
|
|
||||||
prevOldSeq = prevNewSeq = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (oldLoopedBack)
|
|
||||||
{
|
|
||||||
// Old sequence looped back but new one didn't
|
|
||||||
// The new sequence either has some extra trailing elements in the current loop block
|
|
||||||
// which we should insert, or omits some old trailing loop blocks which we should delete
|
|
||||||
// TODO: Find a way of not recomputing this next flag on every iteration
|
|
||||||
var newLoopsBackLater = false;
|
|
||||||
for (var testIndex = newStartIndex + 1; testIndex < newEndIndexExcl; testIndex++)
|
|
||||||
{
|
|
||||||
if (newTree[testIndex].Sequence < newSeq)
|
|
||||||
{
|
|
||||||
newLoopsBackLater = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the new sequence loops back later to an earlier point than this,
|
|
||||||
// then we know it's part of the existing loop block (so should be inserted).
|
|
||||||
// If not, then it's unrelated to the previous loop block (so we should treat
|
|
||||||
// the old items as trailing loop blocks to be removed).
|
|
||||||
treatAsInsert = newLoopsBackLater;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// New sequence looped back but old one didn't
|
|
||||||
// The old sequence either has some extra trailing elements in the current loop block
|
|
||||||
// which we should delete, or the new sequence has extra trailing loop blocks which we
|
|
||||||
// should insert
|
|
||||||
// TODO: Find a way of not recomputing this next flag on every iteration
|
|
||||||
var oldLoopsBackLater = false;
|
|
||||||
for (var testIndex = oldStartIndex + 1; testIndex < oldEndIndexExcl; testIndex++)
|
|
||||||
{
|
|
||||||
if (oldTree[testIndex].Sequence < oldSeq)
|
|
||||||
{
|
|
||||||
oldLoopsBackLater = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the old sequence loops back later to an earlier point than this,
|
|
||||||
// then we know it's part of the existing loop block (so should be removed).
|
|
||||||
// If not, then it's unrelated to the previous loop block (so we should treat
|
|
||||||
// the new items as trailing loop blocks to be inserted).
|
|
||||||
treatAsInsert = !oldLoopsBackLater;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (treatAsInsert)
|
|
||||||
{
|
|
||||||
if (newTree[newStartIndex].NodeType == RenderTreeNodeType.Attribute)
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.SetAttribute(newStartIndex));
|
|
||||||
newStartIndex++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.PrependNode(newStartIndex));
|
|
||||||
newStartIndex = NextSiblingIndex(newTree, newStartIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasMoreNew = newEndIndexExcl > newStartIndex;
|
|
||||||
prevNewSeq = newSeq;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (oldTree[oldStartIndex].NodeType == RenderTreeNodeType.Attribute)
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.RemoveAttribute(oldTree[oldStartIndex].AttributeName));
|
|
||||||
oldStartIndex++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.RemoveNode());
|
|
||||||
oldStartIndex = NextSiblingIndex(oldTree, oldStartIndex);
|
|
||||||
}
|
|
||||||
hasMoreOld = oldEndIndexExcl > oldStartIndex;
|
|
||||||
prevOldSeq = oldSeq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int NextSiblingIndex(RenderTreeNode[] tree, int nodeIndex)
|
|
||||||
{
|
|
||||||
var descendantsEndIndex = tree[nodeIndex].ElementDescendantsEndIndex;
|
|
||||||
return (descendantsEndIndex == 0 ? nodeIndex : descendantsEndIndex) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AppendDiffEntriesForNodesWithSameSequence(
|
|
||||||
RenderTreeNode[] oldTree, int oldNodeIndex,
|
|
||||||
RenderTreeNode[] newTree, int newNodeIndex)
|
|
||||||
{
|
|
||||||
// We can assume that the old and new nodes are of the same type, because they correspond
|
|
||||||
// to the same sequence number (and if not, the behaviour is undefined).
|
|
||||||
switch (newTree[newNodeIndex].NodeType)
|
|
||||||
{
|
|
||||||
case RenderTreeNodeType.Text:
|
|
||||||
{
|
|
||||||
var oldText = oldTree[oldNodeIndex].TextContent;
|
|
||||||
var newText = newTree[newNodeIndex].TextContent;
|
|
||||||
if (string.Equals(oldText, newText, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.Continue());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.UpdateText(newNodeIndex));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RenderTreeNodeType.Element:
|
|
||||||
{
|
|
||||||
var oldElementName = oldTree[oldNodeIndex].ElementName;
|
|
||||||
var newElementName = newTree[newNodeIndex].ElementName;
|
|
||||||
if (string.Equals(oldElementName, newElementName, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var oldNodeAttributesEndIndexExcl = GetAttributesEndIndexExclusive(oldTree, oldNodeIndex);
|
|
||||||
var newNodeAttributesEndIndexExcl = GetAttributesEndIndexExclusive(newTree, newNodeIndex);
|
|
||||||
|
|
||||||
// Diff the attributes
|
|
||||||
AppendDiffEntriesForRange(
|
|
||||||
oldTree, oldNodeIndex + 1, oldNodeAttributesEndIndexExcl,
|
|
||||||
newTree, newNodeIndex + 1, newNodeAttributesEndIndexExcl);
|
|
||||||
|
|
||||||
// Diff the children
|
|
||||||
var oldNodeChildrenEndIndexExcl = oldTree[oldNodeIndex].ElementDescendantsEndIndex + 1;
|
|
||||||
var newNodeChildrenEndIndexExcl = newTree[newNodeIndex].ElementDescendantsEndIndex + 1;
|
|
||||||
var hasChildrenToProcess =
|
|
||||||
oldNodeChildrenEndIndexExcl > oldNodeAttributesEndIndexExcl ||
|
|
||||||
newNodeChildrenEndIndexExcl > newNodeAttributesEndIndexExcl;
|
|
||||||
if (hasChildrenToProcess)
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.StepIn());
|
|
||||||
AppendDiffEntriesForRange(
|
|
||||||
oldTree, oldNodeAttributesEndIndexExcl, oldNodeChildrenEndIndexExcl,
|
|
||||||
newTree, newNodeAttributesEndIndexExcl, newNodeChildrenEndIndexExcl);
|
|
||||||
Append(RenderTreeDiffEntry.StepOut());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.Continue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Elements with different names are treated as completely unrelated
|
|
||||||
Append(RenderTreeDiffEntry.PrependNode(newNodeIndex));
|
|
||||||
Append(RenderTreeDiffEntry.RemoveNode());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RenderTreeNodeType.Component:
|
|
||||||
{
|
|
||||||
var oldComponentType = oldTree[oldNodeIndex].ComponentType;
|
|
||||||
var newComponentType = newTree[newNodeIndex].ComponentType;
|
|
||||||
if (oldComponentType == newComponentType)
|
|
||||||
{
|
|
||||||
// TODO: Compare attributes and notify the existing child component
|
|
||||||
// instance of any changes
|
|
||||||
// TODO: Also copy the existing child component instance to the new
|
|
||||||
// tree so we can preserve it across multiple updates
|
|
||||||
|
|
||||||
Append(RenderTreeDiffEntry.Continue());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Child components of different types are treated as completely unrelated
|
|
||||||
Append(RenderTreeDiffEntry.PrependNode(newNodeIndex));
|
|
||||||
Append(RenderTreeDiffEntry.RemoveNode());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case RenderTreeNodeType.Attribute:
|
|
||||||
{
|
|
||||||
var oldName = oldTree[oldNodeIndex].AttributeName;
|
|
||||||
var newName = newTree[newNodeIndex].AttributeName;
|
|
||||||
if (string.Equals(oldName, newName, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
var changed =
|
|
||||||
!string.Equals(oldTree[oldNodeIndex].AttributeValue, newTree[newNodeIndex].AttributeValue, StringComparison.Ordinal)
|
|
||||||
|| oldTree[oldNodeIndex].AttributeEventHandlerValue != newTree[newNodeIndex].AttributeEventHandlerValue;
|
|
||||||
if (changed)
|
|
||||||
{
|
|
||||||
Append(RenderTreeDiffEntry.SetAttribute(newNodeIndex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 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(RenderTreeDiffEntry.SetAttribute(newNodeIndex));
|
|
||||||
Append(RenderTreeDiffEntry.RemoveAttribute(oldName));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new NotImplementedException($"Encountered unsupported node type during diffing: {newTree[newNodeIndex].NodeType}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetAttributesEndIndexExclusive(RenderTreeNode[] tree, int rootIndex)
|
|
||||||
{
|
|
||||||
var descendantsEndIndex = tree[rootIndex].ElementDescendantsEndIndex;
|
|
||||||
var index = rootIndex + 1;
|
|
||||||
for (; index <= descendantsEndIndex; index++)
|
|
||||||
{
|
|
||||||
if (tree[index].NodeType != RenderTreeNodeType.Attribute)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Append(RenderTreeDiffEntry entry)
|
|
||||||
{
|
|
||||||
if (entry.Type == RenderTreeDiffEntryType.StepOut)
|
|
||||||
{
|
|
||||||
TrimTrailingContinueNodes();
|
|
||||||
|
|
||||||
// If the preceding node is now a StepIn, then we can coalesce the StepIn+StepOut
|
|
||||||
// down to a single Continue
|
|
||||||
if (_entriesInUse > 0 && _entries[_entriesInUse - 1].Type == RenderTreeDiffEntryType.StepIn)
|
|
||||||
{
|
|
||||||
_entriesInUse--;
|
|
||||||
entry = RenderTreeDiffEntry.Continue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_entriesInUse == _entries.Length)
|
|
||||||
{
|
|
||||||
Array.Resize(ref _entries, _entries.Length * 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
_entries[_entriesInUse++] = entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TrimTrailingContinueNodes()
|
|
||||||
{
|
|
||||||
while (_entriesInUse > 0 && _entries[_entriesInUse - 1].Type == RenderTreeDiffEntryType.Continue)
|
|
||||||
{
|
|
||||||
_entriesInUse--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,325 @@
|
||||||
|
// 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.Blazor.RenderTree
|
||||||
|
{
|
||||||
|
internal class RenderTreeDiffComputer
|
||||||
|
{
|
||||||
|
private const int MinBufferLength = 10;
|
||||||
|
private RenderTreeEdit[] _entries = new RenderTreeEdit[10];
|
||||||
|
private int _entriesInUse;
|
||||||
|
|
||||||
|
public ArraySegment<RenderTreeEdit> ComputeDifference(
|
||||||
|
ArraySegment<RenderTreeNode> oldTree,
|
||||||
|
ArraySegment<RenderTreeNode> newTree)
|
||||||
|
{
|
||||||
|
_entriesInUse = 0;
|
||||||
|
AppendDiffEntriesForRange(oldTree.Array, 0, oldTree.Count, newTree.Array, 0, newTree.Count);
|
||||||
|
TrimTrailingContinueNodes();
|
||||||
|
|
||||||
|
// If the previous usage of the buffer showed that we have allocated
|
||||||
|
// much more space than needed, free up the excess memory
|
||||||
|
var shrinkToLength = Math.Max(MinBufferLength, _entries.Length / 2);
|
||||||
|
if (_entriesInUse < shrinkToLength)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _entries, shrinkToLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArraySegment<RenderTreeEdit>(_entries, 0, _entriesInUse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendDiffEntriesForRange(
|
||||||
|
RenderTreeNode[] oldTree, int oldStartIndex, int oldEndIndexExcl,
|
||||||
|
RenderTreeNode[] newTree, int newStartIndex, int newEndIndexExcl)
|
||||||
|
{
|
||||||
|
var hasMoreOld = oldEndIndexExcl > oldStartIndex;
|
||||||
|
var hasMoreNew = newEndIndexExcl > newStartIndex;
|
||||||
|
var prevOldSeq = -1;
|
||||||
|
var prevNewSeq = -1;
|
||||||
|
while (hasMoreOld || hasMoreNew)
|
||||||
|
{
|
||||||
|
var oldSeq = hasMoreOld ? oldTree[oldStartIndex].Sequence : int.MaxValue;
|
||||||
|
var newSeq = hasMoreNew ? newTree[newStartIndex].Sequence : int.MaxValue;
|
||||||
|
|
||||||
|
if (oldSeq == newSeq)
|
||||||
|
{
|
||||||
|
AppendDiffEntriesForNodesWithSameSequence(oldTree, oldStartIndex, newTree, newStartIndex);
|
||||||
|
oldStartIndex = NextSiblingIndex(oldTree, oldStartIndex);
|
||||||
|
newStartIndex = NextSiblingIndex(newTree, newStartIndex);
|
||||||
|
hasMoreOld = oldEndIndexExcl > oldStartIndex;
|
||||||
|
hasMoreNew = newEndIndexExcl > newStartIndex;
|
||||||
|
prevOldSeq = oldSeq;
|
||||||
|
prevNewSeq = newSeq;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool treatAsInsert;
|
||||||
|
var oldLoopedBack = oldSeq <= prevOldSeq;
|
||||||
|
var newLoopedBack = newSeq <= prevNewSeq;
|
||||||
|
if (oldLoopedBack == newLoopedBack)
|
||||||
|
{
|
||||||
|
// Both sequences are proceeding through the same loop block, so do a simple
|
||||||
|
// preordered merge join (picking from whichever side brings us closer to being
|
||||||
|
// back in sync)
|
||||||
|
treatAsInsert = newSeq < oldSeq;
|
||||||
|
|
||||||
|
if (oldLoopedBack)
|
||||||
|
{
|
||||||
|
// If both old and new have now looped back, we must reset their 'looped back'
|
||||||
|
// tracker so we can treat them as proceeding through the same loop block
|
||||||
|
prevOldSeq = prevNewSeq = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (oldLoopedBack)
|
||||||
|
{
|
||||||
|
// Old sequence looped back but new one didn't
|
||||||
|
// The new sequence either has some extra trailing elements in the current loop block
|
||||||
|
// which we should insert, or omits some old trailing loop blocks which we should delete
|
||||||
|
// TODO: Find a way of not recomputing this next flag on every iteration
|
||||||
|
var newLoopsBackLater = false;
|
||||||
|
for (var testIndex = newStartIndex + 1; testIndex < newEndIndexExcl; testIndex++)
|
||||||
|
{
|
||||||
|
if (newTree[testIndex].Sequence < newSeq)
|
||||||
|
{
|
||||||
|
newLoopsBackLater = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the new sequence loops back later to an earlier point than this,
|
||||||
|
// then we know it's part of the existing loop block (so should be inserted).
|
||||||
|
// If not, then it's unrelated to the previous loop block (so we should treat
|
||||||
|
// the old items as trailing loop blocks to be removed).
|
||||||
|
treatAsInsert = newLoopsBackLater;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// New sequence looped back but old one didn't
|
||||||
|
// The old sequence either has some extra trailing elements in the current loop block
|
||||||
|
// which we should delete, or the new sequence has extra trailing loop blocks which we
|
||||||
|
// should insert
|
||||||
|
// TODO: Find a way of not recomputing this next flag on every iteration
|
||||||
|
var oldLoopsBackLater = false;
|
||||||
|
for (var testIndex = oldStartIndex + 1; testIndex < oldEndIndexExcl; testIndex++)
|
||||||
|
{
|
||||||
|
if (oldTree[testIndex].Sequence < oldSeq)
|
||||||
|
{
|
||||||
|
oldLoopsBackLater = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the old sequence loops back later to an earlier point than this,
|
||||||
|
// then we know it's part of the existing loop block (so should be removed).
|
||||||
|
// If not, then it's unrelated to the previous loop block (so we should treat
|
||||||
|
// the new items as trailing loop blocks to be inserted).
|
||||||
|
treatAsInsert = !oldLoopsBackLater;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (treatAsInsert)
|
||||||
|
{
|
||||||
|
if (newTree[newStartIndex].NodeType == RenderTreeNodeType.Attribute)
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.SetAttribute(newStartIndex));
|
||||||
|
newStartIndex++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.PrependNode(newStartIndex));
|
||||||
|
newStartIndex = NextSiblingIndex(newTree, newStartIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMoreNew = newEndIndexExcl > newStartIndex;
|
||||||
|
prevNewSeq = newSeq;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (oldTree[oldStartIndex].NodeType == RenderTreeNodeType.Attribute)
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.RemoveAttribute(oldTree[oldStartIndex].AttributeName));
|
||||||
|
oldStartIndex++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.RemoveNode());
|
||||||
|
oldStartIndex = NextSiblingIndex(oldTree, oldStartIndex);
|
||||||
|
}
|
||||||
|
hasMoreOld = oldEndIndexExcl > oldStartIndex;
|
||||||
|
prevOldSeq = oldSeq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int NextSiblingIndex(RenderTreeNode[] tree, int nodeIndex)
|
||||||
|
{
|
||||||
|
var descendantsEndIndex = tree[nodeIndex].ElementDescendantsEndIndex;
|
||||||
|
return (descendantsEndIndex == 0 ? nodeIndex : descendantsEndIndex) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AppendDiffEntriesForNodesWithSameSequence(
|
||||||
|
RenderTreeNode[] oldTree, int oldNodeIndex,
|
||||||
|
RenderTreeNode[] newTree, int newNodeIndex)
|
||||||
|
{
|
||||||
|
// We can assume that the old and new nodes are of the same type, because they correspond
|
||||||
|
// to the same sequence number (and if not, the behaviour is undefined).
|
||||||
|
switch (newTree[newNodeIndex].NodeType)
|
||||||
|
{
|
||||||
|
case RenderTreeNodeType.Text:
|
||||||
|
{
|
||||||
|
var oldText = oldTree[oldNodeIndex].TextContent;
|
||||||
|
var newText = newTree[newNodeIndex].TextContent;
|
||||||
|
if (string.Equals(oldText, newText, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.Continue());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.UpdateText(newNodeIndex));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RenderTreeNodeType.Element:
|
||||||
|
{
|
||||||
|
var oldElementName = oldTree[oldNodeIndex].ElementName;
|
||||||
|
var newElementName = newTree[newNodeIndex].ElementName;
|
||||||
|
if (string.Equals(oldElementName, newElementName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var oldNodeAttributesEndIndexExcl = GetAttributesEndIndexExclusive(oldTree, oldNodeIndex);
|
||||||
|
var newNodeAttributesEndIndexExcl = GetAttributesEndIndexExclusive(newTree, newNodeIndex);
|
||||||
|
|
||||||
|
// Diff the attributes
|
||||||
|
AppendDiffEntriesForRange(
|
||||||
|
oldTree, oldNodeIndex + 1, oldNodeAttributesEndIndexExcl,
|
||||||
|
newTree, newNodeIndex + 1, newNodeAttributesEndIndexExcl);
|
||||||
|
|
||||||
|
// Diff the children
|
||||||
|
var oldNodeChildrenEndIndexExcl = oldTree[oldNodeIndex].ElementDescendantsEndIndex + 1;
|
||||||
|
var newNodeChildrenEndIndexExcl = newTree[newNodeIndex].ElementDescendantsEndIndex + 1;
|
||||||
|
var hasChildrenToProcess =
|
||||||
|
oldNodeChildrenEndIndexExcl > oldNodeAttributesEndIndexExcl ||
|
||||||
|
newNodeChildrenEndIndexExcl > newNodeAttributesEndIndexExcl;
|
||||||
|
if (hasChildrenToProcess)
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.StepIn());
|
||||||
|
AppendDiffEntriesForRange(
|
||||||
|
oldTree, oldNodeAttributesEndIndexExcl, oldNodeChildrenEndIndexExcl,
|
||||||
|
newTree, newNodeAttributesEndIndexExcl, newNodeChildrenEndIndexExcl);
|
||||||
|
Append(RenderTreeEdit.StepOut());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.Continue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Elements with different names are treated as completely unrelated
|
||||||
|
Append(RenderTreeEdit.PrependNode(newNodeIndex));
|
||||||
|
Append(RenderTreeEdit.RemoveNode());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RenderTreeNodeType.Component:
|
||||||
|
{
|
||||||
|
var oldComponentType = oldTree[oldNodeIndex].ComponentType;
|
||||||
|
var newComponentType = newTree[newNodeIndex].ComponentType;
|
||||||
|
if (oldComponentType == newComponentType)
|
||||||
|
{
|
||||||
|
// TODO: Compare attributes and notify the existing child component
|
||||||
|
// instance of any changes
|
||||||
|
// TODO: Also copy the existing child component instance to the new
|
||||||
|
// tree so we can preserve it across multiple updates
|
||||||
|
|
||||||
|
Append(RenderTreeEdit.Continue());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Child components of different types are treated as completely unrelated
|
||||||
|
Append(RenderTreeEdit.PrependNode(newNodeIndex));
|
||||||
|
Append(RenderTreeEdit.RemoveNode());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RenderTreeNodeType.Attribute:
|
||||||
|
{
|
||||||
|
var oldName = oldTree[oldNodeIndex].AttributeName;
|
||||||
|
var newName = newTree[newNodeIndex].AttributeName;
|
||||||
|
if (string.Equals(oldName, newName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
var changed =
|
||||||
|
!string.Equals(oldTree[oldNodeIndex].AttributeValue, newTree[newNodeIndex].AttributeValue, StringComparison.Ordinal)
|
||||||
|
|| oldTree[oldNodeIndex].AttributeEventHandlerValue != newTree[newNodeIndex].AttributeEventHandlerValue;
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
Append(RenderTreeEdit.SetAttribute(newNodeIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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(newNodeIndex));
|
||||||
|
Append(RenderTreeEdit.RemoveAttribute(oldName));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"Encountered unsupported node type during diffing: {newTree[newNodeIndex].NodeType}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetAttributesEndIndexExclusive(RenderTreeNode[] tree, int rootIndex)
|
||||||
|
{
|
||||||
|
var descendantsEndIndex = tree[rootIndex].ElementDescendantsEndIndex;
|
||||||
|
var index = rootIndex + 1;
|
||||||
|
for (; index <= descendantsEndIndex; index++)
|
||||||
|
{
|
||||||
|
if (tree[index].NodeType != RenderTreeNodeType.Attribute)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Append(RenderTreeEdit entry)
|
||||||
|
{
|
||||||
|
if (entry.Type == RenderTreeEditType.StepOut)
|
||||||
|
{
|
||||||
|
TrimTrailingContinueNodes();
|
||||||
|
|
||||||
|
// If the preceding node is now a StepIn, then we can coalesce the StepIn+StepOut
|
||||||
|
// down to a single Continue
|
||||||
|
if (_entriesInUse > 0 && _entries[_entriesInUse - 1].Type == RenderTreeEditType.StepIn)
|
||||||
|
{
|
||||||
|
_entriesInUse--;
|
||||||
|
entry = RenderTreeEdit.Continue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_entriesInUse == _entries.Length)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _entries, _entries.Length * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
_entries[_entriesInUse++] = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TrimTrailingContinueNodes()
|
||||||
|
{
|
||||||
|
while (_entriesInUse > 0 && _entries[_entriesInUse - 1].Type == RenderTreeEditType.Continue)
|
||||||
|
{
|
||||||
|
_entriesInUse--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
// 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;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Microsoft.Blazor.RenderTree
|
|
||||||
{
|
|
||||||
internal struct RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
public RenderTreeDiffEntryType Type { get; private set; }
|
|
||||||
public int NewTreeIndex { get; private set; }
|
|
||||||
public string RemovedAttributeName { get; private set; }
|
|
||||||
|
|
||||||
public static RenderTreeDiffEntry Continue() => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.Continue
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry RemoveNode() => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.RemoveNode
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry PrependNode(int newTreeIndex) => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.PrependNode,
|
|
||||||
NewTreeIndex = newTreeIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry UpdateText(int newTreeIndex) => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.UpdateText,
|
|
||||||
NewTreeIndex = newTreeIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry SetAttribute(int newNodeIndex) => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.SetAttribute,
|
|
||||||
NewTreeIndex = newNodeIndex
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry RemoveAttribute(string name) => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.RemoveAttribute,
|
|
||||||
RemovedAttributeName = name
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry StepIn() => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.StepIn
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static RenderTreeDiffEntry StepOut() => new RenderTreeDiffEntry
|
|
||||||
{
|
|
||||||
Type = RenderTreeDiffEntryType.StepOut
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
namespace Microsoft.Blazor.RenderTree
|
|
||||||
{
|
|
||||||
internal enum RenderTreeDiffEntryType: int
|
|
||||||
{
|
|
||||||
Continue = 1,
|
|
||||||
PrependNode = 2,
|
|
||||||
RemoveNode = 3,
|
|
||||||
SetAttribute = 4,
|
|
||||||
RemoveAttribute = 5,
|
|
||||||
UpdateText = 6,
|
|
||||||
StepIn = 7,
|
|
||||||
StepOut = 8,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.Blazor.RenderTree
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a single edit operation on a component's render tree.
|
||||||
|
/// </summary>
|
||||||
|
public struct RenderTreeEdit
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type of the edit operation.
|
||||||
|
/// </summary>
|
||||||
|
public RenderTreeEditType Type { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the index of related data in an associated render tree. For example, if the
|
||||||
|
/// <see cref="Type"/> value is <see cref="RenderTreeEditType.PrependNode"/>, gets the
|
||||||
|
/// index of the new node data in an associated render tree.
|
||||||
|
/// </summary>
|
||||||
|
public int NewTreeIndex { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the <see cref="Type"/> value is <see cref="RenderTreeEditType.RemoveAttribute"/>,
|
||||||
|
/// gets the name of the attribute that is being removed.
|
||||||
|
/// </summary>
|
||||||
|
public string RemovedAttributeName { get; private set; }
|
||||||
|
|
||||||
|
internal static RenderTreeEdit Continue() => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.Continue
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit RemoveNode() => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.RemoveNode
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit PrependNode(int newTreeIndex) => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.PrependNode,
|
||||||
|
NewTreeIndex = newTreeIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit UpdateText(int newTreeIndex) => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.UpdateText,
|
||||||
|
NewTreeIndex = newTreeIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit SetAttribute(int newNodeIndex) => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.SetAttribute,
|
||||||
|
NewTreeIndex = newNodeIndex
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit RemoveAttribute(string name) => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.RemoveAttribute,
|
||||||
|
RemovedAttributeName = name
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit StepIn() => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.StepIn
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static RenderTreeEdit StepOut() => new RenderTreeEdit
|
||||||
|
{
|
||||||
|
Type = RenderTreeEditType.StepOut
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
namespace Microsoft.Blazor.RenderTree
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the type of a render tree edit operation.
|
||||||
|
/// </summary>
|
||||||
|
public enum RenderTreeEditType: int
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that there are no further operations on the current tree node, and
|
||||||
|
/// so the edit position should move to the next sibling (or if there is no next
|
||||||
|
/// sibling, then to the position where one would be).
|
||||||
|
/// </summary>
|
||||||
|
Continue = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that a new node should be inserted before the current tree node.
|
||||||
|
/// </summary>
|
||||||
|
PrependNode = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the current tree node should be removed, and that the edit position
|
||||||
|
/// should then move to the next sibling (or if there is no next sibling, then to the
|
||||||
|
/// position where one would be).
|
||||||
|
/// </summary>
|
||||||
|
RemoveNode = 3,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that an attribute value should be applied to the current node.
|
||||||
|
/// This may be a change to an existing attribute, or the addition of a new attribute.
|
||||||
|
/// </summary>
|
||||||
|
SetAttribute = 4,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that a named attribute should be removed from the current node.
|
||||||
|
/// </summary>
|
||||||
|
RemoveAttribute = 5,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the text content of the current node (which must be a text node)
|
||||||
|
/// should be updated.
|
||||||
|
/// </summary>
|
||||||
|
UpdateText = 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the edit position should move inside the current node to its first
|
||||||
|
/// child (or, if there are no children, to a point where a first child would be).
|
||||||
|
/// </summary>
|
||||||
|
StepIn = 7,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that there are no further edit operations on the current node, and the
|
||||||
|
/// edit position should move to the next sibling of the parent node (or if it does not
|
||||||
|
/// have a next sibling, then to the position where one would be).
|
||||||
|
/// </summary>
|
||||||
|
StepOut = 8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,7 @@ using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.Blazor.Test
|
namespace Microsoft.Blazor.Test
|
||||||
{
|
{
|
||||||
public class RenderTreeDiffTest
|
public class RenderTreeDiffComputerTest
|
||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[MemberData(nameof(RecognizesEquivalentNodesAsSameCases))]
|
[MemberData(nameof(RecognizesEquivalentNodesAsSameCases))]
|
||||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
appendAction(oldTree);
|
appendAction(oldTree);
|
||||||
appendAction(newTree);
|
appendAction(newTree);
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "text0");
|
oldTree.AddText(0, "text0");
|
||||||
oldTree.AddText(2, "text2");
|
oldTree.AddText(2, "text2");
|
||||||
newTree.AddText(0, "text0");
|
newTree.AddText(0, "text0");
|
||||||
|
|
@ -63,10 +63,10 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(1, entry.NewTreeIndex);
|
Assert.Equal(1, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "text0");
|
oldTree.AddText(0, "text0");
|
||||||
oldTree.AddText(1, "text1");
|
oldTree.AddText(1, "text1");
|
||||||
oldTree.AddText(2, "text2");
|
oldTree.AddText(2, "text2");
|
||||||
|
|
@ -89,8 +89,8 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -99,7 +99,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "x"); // Loop start
|
oldTree.AddText(0, "x"); // Loop start
|
||||||
oldTree.AddText(1, "x"); // Will be removed
|
oldTree.AddText(1, "x"); // Will be removed
|
||||||
oldTree.AddText(2, "x"); // Will be removed
|
oldTree.AddText(2, "x"); // Will be removed
|
||||||
|
|
@ -112,9 +112,9 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -123,7 +123,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "x"); // Loop start
|
oldTree.AddText(0, "x"); // Loop start
|
||||||
oldTree.AddText(0, "x"); // Loop start
|
oldTree.AddText(0, "x"); // Loop start
|
||||||
newTree.AddText(0, "x"); // Loop start
|
newTree.AddText(0, "x"); // Loop start
|
||||||
|
|
@ -136,15 +136,15 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(1, entry.NewTreeIndex);
|
Assert.Equal(1, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(2, entry.NewTreeIndex);
|
Assert.Equal(2, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -155,7 +155,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "x");
|
oldTree.AddText(0, "x");
|
||||||
oldTree.AddText(1, "x");
|
oldTree.AddText(1, "x");
|
||||||
oldTree.AddText(0, "x"); // Will be removed
|
oldTree.AddText(0, "x"); // Will be removed
|
||||||
|
|
@ -168,10 +168,10 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -180,7 +180,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "x");
|
oldTree.AddText(0, "x");
|
||||||
oldTree.AddText(1, "x");
|
oldTree.AddText(1, "x");
|
||||||
newTree.AddText(0, "x");
|
newTree.AddText(0, "x");
|
||||||
|
|
@ -193,16 +193,16 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(2, entry.NewTreeIndex);
|
Assert.Equal(2, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(3, entry.NewTreeIndex);
|
Assert.Equal(3, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(2, "x");
|
oldTree.AddText(2, "x");
|
||||||
oldTree.AddText(2, "x"); // Note that the '0' and '1' items are not present on this iteration
|
oldTree.AddText(2, "x"); // Note that the '0' and '1' items are not present on this iteration
|
||||||
newTree.AddText(2, "x");
|
newTree.AddText(2, "x");
|
||||||
|
|
@ -226,15 +226,15 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(1, entry.NewTreeIndex);
|
Assert.Equal(1, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(2, entry.NewTreeIndex);
|
Assert.Equal(2, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +245,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(2, "x");
|
oldTree.AddText(2, "x");
|
||||||
oldTree.AddText(0, "x");
|
oldTree.AddText(0, "x");
|
||||||
oldTree.AddText(1, "x");
|
oldTree.AddText(1, "x");
|
||||||
|
|
@ -258,9 +258,9 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -269,7 +269,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(0, "text");
|
oldTree.AddText(0, "text");
|
||||||
newTree.AddText(1, "text");
|
newTree.AddText(1, "text");
|
||||||
|
|
||||||
|
|
@ -278,8 +278,8 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.PrependNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -288,7 +288,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(123, "old text");
|
oldTree.AddText(123, "old text");
|
||||||
newTree.AddText(123, "new text");
|
newTree.AddText(123, "new text");
|
||||||
|
|
||||||
|
|
@ -299,7 +299,7 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.UpdateText, entry.Type);
|
Assert.Equal(RenderTreeEditType.UpdateText, entry.Type);
|
||||||
Assert.Equal(0, entry.NewTreeIndex);
|
Assert.Equal(0, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +314,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(123, "old element");
|
oldTree.OpenElement(123, "old element");
|
||||||
oldTree.CloseElement();
|
oldTree.CloseElement();
|
||||||
newTree.OpenElement(123, "new element");
|
newTree.OpenElement(123, "new element");
|
||||||
|
|
@ -327,10 +327,10 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(0, entry.NewTreeIndex);
|
Assert.Equal(0, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -339,7 +339,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddComponent<FakeComponent>(123);
|
oldTree.AddComponent<FakeComponent>(123);
|
||||||
newTree.AddComponent<FakeComponent2>(123);
|
newTree.AddComponent<FakeComponent2>(123);
|
||||||
|
|
||||||
|
|
@ -350,10 +350,10 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.PrependNode, entry.Type);
|
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||||
Assert.Equal(0, entry.NewTreeIndex);
|
Assert.Equal(0, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.RemoveNode, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -362,7 +362,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(0, "My element");
|
oldTree.OpenElement(0, "My element");
|
||||||
oldTree.AddAttribute(1, "existing", "existing value");
|
oldTree.AddAttribute(1, "existing", "existing value");
|
||||||
oldTree.CloseElement();
|
oldTree.CloseElement();
|
||||||
|
|
@ -378,7 +378,7 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.SetAttribute, entry.Type);
|
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||||
Assert.Equal(2, entry.NewTreeIndex);
|
Assert.Equal(2, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +389,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(0, "My element");
|
oldTree.OpenElement(0, "My element");
|
||||||
oldTree.AddAttribute(1, "will be removed", "will be removed value");
|
oldTree.AddAttribute(1, "will be removed", "will be removed value");
|
||||||
oldTree.AddAttribute(2, "will survive", "surviving value");
|
oldTree.AddAttribute(2, "will survive", "surviving value");
|
||||||
|
|
@ -405,7 +405,7 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.RemoveAttribute, entry.Type);
|
Assert.Equal(RenderTreeEditType.RemoveAttribute, entry.Type);
|
||||||
Assert.Equal("will be removed", entry.RemovedAttributeName);
|
Assert.Equal("will be removed", entry.RemovedAttributeName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +416,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(0, "My element");
|
oldTree.OpenElement(0, "My element");
|
||||||
oldTree.AddAttribute(1, "will remain", "will remain value");
|
oldTree.AddAttribute(1, "will remain", "will remain value");
|
||||||
oldTree.AddAttribute(2, "will change", "will change value");
|
oldTree.AddAttribute(2, "will change", "will change value");
|
||||||
|
|
@ -433,7 +433,7 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.SetAttribute, entry.Type);
|
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||||
Assert.Equal(2, entry.NewTreeIndex);
|
Assert.Equal(2, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -444,7 +444,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
UIEventHandler retainedHandler = _ => { };
|
UIEventHandler retainedHandler = _ => { };
|
||||||
UIEventHandler removedHandler = _ => { };
|
UIEventHandler removedHandler = _ => { };
|
||||||
UIEventHandler addedHandler = _ => { };
|
UIEventHandler addedHandler = _ => { };
|
||||||
|
|
@ -464,7 +464,7 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.SetAttribute, entry.Type);
|
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||||
Assert.Equal(2, entry.NewTreeIndex);
|
Assert.Equal(2, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +475,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(0, "My element");
|
oldTree.OpenElement(0, "My element");
|
||||||
oldTree.AddAttribute(1, "oldname", "same value");
|
oldTree.AddAttribute(1, "oldname", "same value");
|
||||||
oldTree.CloseElement();
|
oldTree.CloseElement();
|
||||||
|
|
@ -490,12 +490,12 @@ namespace Microsoft.Blazor.Test
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.SetAttribute, entry.Type);
|
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||||
Assert.Equal(1, entry.NewTreeIndex);
|
Assert.Equal(1, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.RemoveAttribute, entry.Type);
|
Assert.Equal(RenderTreeEditType.RemoveAttribute, entry.Type);
|
||||||
Assert.Equal("oldname", entry.RemovedAttributeName);
|
Assert.Equal("oldname", entry.RemovedAttributeName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -506,7 +506,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(10, "root");
|
oldTree.OpenElement(10, "root");
|
||||||
oldTree.OpenElement(11, "child");
|
oldTree.OpenElement(11, "child");
|
||||||
oldTree.OpenElement(12, "grandchild");
|
oldTree.OpenElement(12, "grandchild");
|
||||||
|
|
@ -528,17 +528,17 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepIn, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepIn, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepIn, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.UpdateText, entry.Type);
|
Assert.Equal(RenderTreeEditType.UpdateText, entry.Type);
|
||||||
Assert.Equal(3, entry.NewTreeIndex);
|
Assert.Equal(3, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepOut, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.StepOut, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepOut, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.StepOut, entry.Type),
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepOut, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.StepOut, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -547,7 +547,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.OpenElement(10, "root");
|
oldTree.OpenElement(10, "root");
|
||||||
oldTree.AddText(11, "Text that will change");
|
oldTree.AddText(11, "Text that will change");
|
||||||
oldTree.OpenElement(12, "Subtree that will not change");
|
oldTree.OpenElement(12, "Subtree that will not change");
|
||||||
|
|
@ -571,13 +571,13 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepIn, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.UpdateText, entry.Type);
|
Assert.Equal(RenderTreeEditType.UpdateText, entry.Type);
|
||||||
Assert.Equal(1, entry.NewTreeIndex);
|
Assert.Equal(1, entry.NewTreeIndex);
|
||||||
},
|
},
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.StepOut, entry.Type));
|
entry => Assert.Equal(RenderTreeEditType.StepOut, entry.Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -586,7 +586,7 @@ namespace Microsoft.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
var oldTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
var newTree = new RenderTreeBuilder(new FakeRenderer());
|
||||||
var diff = new RenderTreeDiff();
|
var diff = new RenderTreeDiffComputer();
|
||||||
oldTree.AddText(10, "text1");
|
oldTree.AddText(10, "text1");
|
||||||
oldTree.AddText(11, "text2");
|
oldTree.AddText(11, "text2");
|
||||||
oldTree.AddText(12, "text3");
|
oldTree.AddText(12, "text3");
|
||||||
|
|
@ -601,10 +601,10 @@ namespace Microsoft.Blazor.Test
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Collection(result,
|
Assert.Collection(result,
|
||||||
entry => Assert.Equal(RenderTreeDiffEntryType.Continue, entry.Type),
|
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||||
entry =>
|
entry =>
|
||||||
{
|
{
|
||||||
Assert.Equal(RenderTreeDiffEntryType.UpdateText, entry.Type);
|
Assert.Equal(RenderTreeEditType.UpdateText, entry.Type);
|
||||||
Assert.Equal(1, entry.NewTreeIndex);
|
Assert.Equal(1, entry.NewTreeIndex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue