Update rendering APIs to supply the diff as well as the final state
This commit is contained in:
parent
bea15241f2
commit
5435582c0e
|
|
@ -68,7 +68,7 @@ namespace Microsoft.Blazor.Browser.Rendering
|
|||
/// <inheritdoc />
|
||||
protected override void UpdateDisplay(
|
||||
int componentId,
|
||||
ArraySegment<RenderTreeNode> renderTree)
|
||||
RenderTreeDiff renderTreeDiff)
|
||||
{
|
||||
RegisteredFunction.InvokeUnmarshalled<RenderComponentArgs, object>(
|
||||
"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
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,19 +6,28 @@ using System;
|
|||
namespace Microsoft.Blazor.RenderTree
|
||||
{
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
public struct RenderTreeDiff
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the render tree changes as a sequence of edit operations.
|
||||
/// Gets the changes to the render tree since a previous state.
|
||||
/// </summary>
|
||||
public RenderTreeEdit[] Entries { get; private set; }
|
||||
public ArraySegment<RenderTreeEdit> Edits { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// An array of <see cref="RenderTreeNode"/> structures that may be referred to
|
||||
/// by entries in the <see cref="Entries"/> property.
|
||||
/// Gets the latest render tree. That is, the result of applying the <see cref="Edits"/>
|
||||
/// to the previous state.
|
||||
/// </summary>
|
||||
public ArraySegment<RenderTreeNode> ReferenceTree { get; private set; }
|
||||
public ArraySegment<RenderTreeNode> CurrentState { get; private set; }
|
||||
|
||||
internal RenderTreeDiff(
|
||||
ArraySegment<RenderTreeEdit> entries,
|
||||
ArraySegment<RenderTreeNode> referenceTree)
|
||||
{
|
||||
Edits = entries;
|
||||
CurrentState = referenceTree;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Microsoft.Blazor.RenderTree
|
|||
private RenderTreeEdit[] _entries = new RenderTreeEdit[10];
|
||||
private int _entriesInUse;
|
||||
|
||||
public ArraySegment<RenderTreeEdit> ComputeDifference(
|
||||
public RenderTreeDiff ComputeDifference(
|
||||
ArraySegment<RenderTreeNode> oldTree,
|
||||
ArraySegment<RenderTreeNode> newTree)
|
||||
{
|
||||
|
|
@ -27,7 +27,9 @@ namespace Microsoft.Blazor.RenderTree
|
|||
Array.Resize(ref _entries, shrinkToLength);
|
||||
}
|
||||
|
||||
return new ArraySegment<RenderTreeEdit>(_entries, 0, _entriesInUse);
|
||||
return new RenderTreeDiff(
|
||||
new ArraySegment<RenderTreeEdit>(_entries, 0, _entriesInUse),
|
||||
newTree);
|
||||
}
|
||||
|
||||
private void AppendDiffEntriesForRange(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs an instance of <see cref="ComponentState"/>.
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -39,12 +43,16 @@ namespace Microsoft.Blazor.Rendering
|
|||
/// </summary>
|
||||
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<RenderTreeNode> 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,8 +47,9 @@ namespace Microsoft.Blazor.Rendering
|
|||
/// at the location corresponding to the <paramref name="componentId"/>.
|
||||
/// </summary>
|
||||
/// <param name="componentId">The identifier for the updated <see cref="IComponent"/>.</param>
|
||||
/// <param name="renderTree">The updated render tree to be displayed.</param>
|
||||
internal protected abstract void UpdateDisplay(int componentId, ArraySegment<RenderTreeNode> renderTree);
|
||||
/// <param name="renderTreeDiff">The changes to the render tree since the component was last rendered.</param>
|
||||
internal protected abstract void UpdateDisplay(
|
||||
int componentId, RenderTreeDiff renderTreeDiff);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the rendered state of the specified <see cref="IComponent"/>.
|
||||
|
|
|
|||
|
|
@ -442,7 +442,7 @@ namespace Microsoft.Blazor.Build.Test
|
|||
|
||||
private class TestRenderer : Renderer
|
||||
{
|
||||
protected override void UpdateDisplay(int componentId, ArraySegment<RenderTreeNode> renderTree)
|
||||
protected override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ namespace Microsoft.Blazor.Test
|
|||
|
||||
private class TestRenderer : Renderer
|
||||
{
|
||||
internal protected override void UpdateDisplay(int componentId, ArraySegment<RenderTreeNode> renderTree)
|
||||
protected internal override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<object[]> RecognizesEquivalentNodesAsSameCases()
|
||||
|
|
@ -62,7 +62,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry =>
|
||||
{
|
||||
|
|
@ -88,7 +88,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||
|
|
@ -135,7 +135,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry =>
|
||||
{
|
||||
|
|
@ -167,7 +167,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||
|
|
@ -192,7 +192,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry =>
|
||||
|
|
@ -225,7 +225,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry =>
|
||||
{
|
||||
|
|
@ -257,7 +257,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type));
|
||||
|
|
@ -277,7 +277,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.RemoveNode, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.PrependNode, entry.Type));
|
||||
}
|
||||
|
|
@ -296,7 +296,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.UpdateText, entry.Type);
|
||||
|
|
@ -324,7 +324,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||
|
|
@ -347,7 +347,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.PrependNode, entry.Type);
|
||||
|
|
@ -375,7 +375,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||
|
|
@ -402,7 +402,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.RemoveAttribute, entry.Type);
|
||||
|
|
@ -430,7 +430,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||
|
|
@ -461,7 +461,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||
|
|
@ -487,7 +487,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry =>
|
||||
{
|
||||
Assert.Equal(RenderTreeEditType.SetAttribute, entry.Type);
|
||||
|
|
@ -527,7 +527,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||
|
|
@ -570,7 +570,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.StepIn, entry.Type),
|
||||
entry =>
|
||||
{
|
||||
|
|
@ -600,7 +600,7 @@ namespace Microsoft.Blazor.Test
|
|||
var result = diff.ComputeDifference(oldTree.GetNodes(), newTree.GetNodes());
|
||||
|
||||
// Assert
|
||||
Assert.Collection(result,
|
||||
Assert.Collection(result.Edits,
|
||||
entry => Assert.Equal(RenderTreeEditType.Continue, entry.Type),
|
||||
entry =>
|
||||
{
|
||||
|
|
@ -611,7 +611,7 @@ namespace Microsoft.Blazor.Test
|
|||
|
||||
private class FakeRenderer : Renderer
|
||||
{
|
||||
internal protected override void UpdateDisplay(int componentId, ArraySegment<RenderTreeNode> renderTree)
|
||||
internal protected override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ namespace Microsoft.Blazor.Test
|
|||
public new void RenderComponent(int componentId)
|
||||
=> base.RenderComponent(componentId);
|
||||
|
||||
internal protected override void UpdateDisplay(int componentId, ArraySegment<RenderTreeNode> renderTree)
|
||||
protected internal override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -325,9 +325,9 @@ namespace Microsoft.Blazor.Test
|
|||
public new void DispatchEvent(int componentId, int renderTreeIndex, UIEventArgs args)
|
||||
=> base.DispatchEvent(componentId, renderTreeIndex, args);
|
||||
|
||||
internal protected override void UpdateDisplay(int componentId, ArraySegment<RenderTreeNode> renderTree)
|
||||
protected internal override void UpdateDisplay(int componentId, RenderTreeDiff renderTreeDiff)
|
||||
{
|
||||
RenderTreesByComponentId[componentId] = renderTree;
|
||||
RenderTreesByComponentId[componentId] = renderTreeDiff.CurrentState;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue