diff --git a/src/Microsoft.Blazor.Browser/Rendering/BrowserRenderer.cs b/src/Microsoft.Blazor.Browser/Rendering/BrowserRenderer.cs
index a0b04e96a5..333397f940 100644
--- a/src/Microsoft.Blazor.Browser/Rendering/BrowserRenderer.cs
+++ b/src/Microsoft.Blazor.Browser/Rendering/BrowserRenderer.cs
@@ -68,7 +68,7 @@ namespace Microsoft.Blazor.Browser.Rendering
///
protected override void UpdateDisplay(
int componentId,
- ArraySegment renderTree)
+ RenderTreeDiff renderTreeDiff)
{
RegisteredFunction.InvokeUnmarshalled(
"renderRenderTree",
@@ -76,8 +76,8 @@ namespace Microsoft.Blazor.Browser.Rendering
{
BrowserRendererId = _browserRendererId,
ComponentId = componentId,
- RenderTree = renderTree.Array,
- RenderTreeLength = renderTree.Count
+ RenderTree = renderTreeDiff.CurrentState.Array,
+ RenderTreeLength = renderTreeDiff.CurrentState.Count
});
}
diff --git a/src/Microsoft.Blazor/RenderTree/RenderTreeDiff.cs b/src/Microsoft.Blazor/RenderTree/RenderTreeDiff.cs
index 5b27cab8f7..497ddc1231 100644
--- a/src/Microsoft.Blazor/RenderTree/RenderTreeDiff.cs
+++ b/src/Microsoft.Blazor/RenderTree/RenderTreeDiff.cs
@@ -6,19 +6,28 @@ using System;
namespace Microsoft.Blazor.RenderTree
{
///
- /// Describes changes to a component's render tree between successive renders.
+ /// Describes changes to a component's render tree between successive renders,
+ /// as well as the resulting state.
///
public struct RenderTreeDiff
{
///
- /// Describes the render tree changes as a sequence of edit operations.
+ /// Gets the changes to the render tree since a previous state.
///
- public RenderTreeEdit[] Entries { get; private set; }
+ public ArraySegment Edits { get; private set; }
///
- /// An array of structures that may be referred to
- /// by entries in the property.
+ /// Gets the latest render tree. That is, the result of applying the
+ /// to the previous state.
///
- public ArraySegment ReferenceTree { get; private set; }
+ public ArraySegment CurrentState { get; private set; }
+
+ internal RenderTreeDiff(
+ ArraySegment entries,
+ ArraySegment referenceTree)
+ {
+ Edits = entries;
+ CurrentState = referenceTree;
+ }
}
}
diff --git a/src/Microsoft.Blazor/RenderTree/RenderTreeDiffComputer.cs b/src/Microsoft.Blazor/RenderTree/RenderTreeDiffComputer.cs
index 254ed64305..cd2b84246e 100644
--- a/src/Microsoft.Blazor/RenderTree/RenderTreeDiffComputer.cs
+++ b/src/Microsoft.Blazor/RenderTree/RenderTreeDiffComputer.cs
@@ -11,7 +11,7 @@ namespace Microsoft.Blazor.RenderTree
private RenderTreeEdit[] _entries = new RenderTreeEdit[10];
private int _entriesInUse;
- public ArraySegment ComputeDifference(
+ public RenderTreeDiff ComputeDifference(
ArraySegment oldTree,
ArraySegment newTree)
{
@@ -27,7 +27,9 @@ namespace Microsoft.Blazor.RenderTree
Array.Resize(ref _entries, shrinkToLength);
}
- return new ArraySegment(_entries, 0, _entriesInUse);
+ return new RenderTreeDiff(
+ new ArraySegment(_entries, 0, _entriesInUse),
+ newTree);
}
private void AppendDiffEntriesForRange(
diff --git a/src/Microsoft.Blazor/Rendering/ComponentState.cs b/src/Microsoft.Blazor/Rendering/ComponentState.cs
index ccbebab4da..0d5794fdac 100644
--- a/src/Microsoft.Blazor/Rendering/ComponentState.cs
+++ b/src/Microsoft.Blazor/Rendering/ComponentState.cs
@@ -17,7 +17,9 @@ namespace Microsoft.Blazor.Rendering
private readonly int _componentId; // TODO: Change the type to 'long' when the Mono runtime has more complete support for passing longs in .NET->JS calls
private readonly IComponent _component;
private readonly Renderer _renderer;
- private readonly RenderTreeBuilder _renderTreeBuilder;
+ private readonly RenderTreeDiffComputer _diffComputer;
+ private RenderTreeBuilder _renderTreeBuilderCurrent;
+ private RenderTreeBuilder _renderTreeBuilderPrevious;
///
/// Constructs an instance of .
@@ -30,7 +32,9 @@ namespace Microsoft.Blazor.Rendering
_componentId = componentId;
_component = component ?? throw new ArgumentNullException(nameof(component));
_renderer = renderer ?? throw new ArgumentNullException(nameof(renderer));
- _renderTreeBuilder = new RenderTreeBuilder(renderer);
+ _diffComputer = new RenderTreeDiffComputer();
+ _renderTreeBuilderCurrent = new RenderTreeBuilder(renderer);
+ _renderTreeBuilderPrevious = new RenderTreeBuilder(renderer);
}
///
@@ -39,12 +43,16 @@ namespace Microsoft.Blazor.Rendering
///
public void Render()
{
- _renderTreeBuilder.Clear();
- _component.BuildRenderTree(_renderTreeBuilder);
+ // Swap the old and new tree builders
+ (_renderTreeBuilderCurrent, _renderTreeBuilderPrevious) = (_renderTreeBuilderPrevious, _renderTreeBuilderCurrent);
- var renderTree = _renderTreeBuilder.GetNodes();
- EnsureChildComponentsInstantiated(renderTree);
- _renderer.UpdateDisplay(_componentId, renderTree);
+ _renderTreeBuilderCurrent.Clear();
+ _component.BuildRenderTree(_renderTreeBuilderCurrent);
+ var diff = _diffComputer.ComputeDifference(
+ _renderTreeBuilderPrevious.GetNodes(),
+ _renderTreeBuilderCurrent.GetNodes());
+ EnsureChildComponentsInstantiated(diff.CurrentState); // TODO: Move this into the diff phase
+ _renderer.UpdateDisplay(_componentId, diff);
}
private void EnsureChildComponentsInstantiated(ArraySegment renderTree)
@@ -76,7 +84,7 @@ namespace Microsoft.Blazor.Rendering
throw new ArgumentNullException(nameof(eventArgs));
}
- var nodes = _renderTreeBuilder.GetNodes();
+ var nodes = _renderTreeBuilderCurrent.GetNodes();
var eventHandler = nodes.Array[renderTreeIndex].AttributeEventHandlerValue;
if (eventHandler == null)
{
diff --git a/src/Microsoft.Blazor/Rendering/Renderer.cs b/src/Microsoft.Blazor/Rendering/Renderer.cs
index 436c7d3f4e..8c05afc083 100644
--- a/src/Microsoft.Blazor/Rendering/Renderer.cs
+++ b/src/Microsoft.Blazor/Rendering/Renderer.cs
@@ -47,8 +47,9 @@ namespace Microsoft.Blazor.Rendering
/// at the location corresponding to the .
///
/// The identifier for the updated .
- /// The updated render tree to be displayed.
- internal protected abstract void UpdateDisplay(int componentId, ArraySegment renderTree);
+ /// The changes to the render tree since the component was last rendered.
+ internal protected abstract void UpdateDisplay(
+ int componentId, RenderTreeDiff renderTreeDiff);
///
/// Updates the rendered state of the specified .
diff --git a/test/Microsoft.Blazor.Build.Test/RazorCompilerTest.cs b/test/Microsoft.Blazor.Build.Test/RazorCompilerTest.cs
index b8b5188f2c..439d140ad3 100644
--- a/test/Microsoft.Blazor.Build.Test/RazorCompilerTest.cs
+++ b/test/Microsoft.Blazor.Build.Test/RazorCompilerTest.cs
@@ -442,7 +442,7 @@ namespace Microsoft.Blazor.Build.Test
private class TestRenderer : Renderer
{
- protected override void UpdateDisplay(int componentId, ArraySegment renderTree)
+ protected override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
=> throw new NotImplementedException();
}
}
diff --git a/test/Microsoft.Blazor.Test/RenderTreeBuilderTest.cs b/test/Microsoft.Blazor.Test/RenderTreeBuilderTest.cs
index 1a7832d5e7..aebf92cd26 100644
--- a/test/Microsoft.Blazor.Test/RenderTreeBuilderTest.cs
+++ b/test/Microsoft.Blazor.Test/RenderTreeBuilderTest.cs
@@ -298,7 +298,7 @@ namespace Microsoft.Blazor.Test
private class TestRenderer : Renderer
{
- internal protected override void UpdateDisplay(int componentId, ArraySegment renderTree)
+ protected internal override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
=> throw new NotImplementedException();
}
}
diff --git a/test/Microsoft.Blazor.Test/RenderTreeDiffComputerTest.cs b/test/Microsoft.Blazor.Test/RenderTreeDiffComputerTest.cs
index 5144ccdff6..a618e6cb86 100644
--- a/test/Microsoft.Blazor.Test/RenderTreeDiffComputerTest.cs
+++ b/test/Microsoft.Blazor.Test/RenderTreeDiffComputerTest.cs
@@ -28,7 +28,7 @@ namespace Microsoft.Blazor.Test
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
// Assert
- Assert.Empty(result);
+ Assert.Empty(result.Edits);
}
public static IEnumerable