Remove externally-callable Renderer.RenderInNewBatch() now that rendering is triggered by components themselves
This commit is contained in:
parent
804ab2d89f
commit
70a3ee3d98
|
|
@ -29,9 +29,6 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
||||||
internal void DispatchBrowserEvent(int componentId, int eventHandlerId, UIEventArgs eventArgs)
|
internal void DispatchBrowserEvent(int componentId, int eventHandlerId, UIEventArgs eventArgs)
|
||||||
=> DispatchEvent(componentId, eventHandlerId, eventArgs);
|
=> DispatchEvent(componentId, eventHandlerId, eventArgs);
|
||||||
|
|
||||||
internal void RenderNewBatchInternal(int componentId)
|
|
||||||
=> RenderNewBatch(componentId);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attaches a new root component to the renderer,
|
/// Attaches a new root component to the renderer,
|
||||||
/// causing it to be displayed in the specified DOM element.
|
/// causing it to be displayed in the specified DOM element.
|
||||||
|
|
@ -59,7 +56,7 @@ namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
|
||||||
_browserRendererId,
|
_browserRendererId,
|
||||||
domElementSelector,
|
domElementSelector,
|
||||||
componentId);
|
componentId);
|
||||||
RenderNewBatch(componentId);
|
component.SetParameters(ParameterCollection.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,14 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly struct ParameterCollection
|
public readonly struct ParameterCollection
|
||||||
{
|
{
|
||||||
|
private static readonly RenderTreeFrame[] _emptyCollectionFrames = new RenderTreeFrame[]
|
||||||
|
{
|
||||||
|
RenderTreeFrame.Element(0, string.Empty).WithComponentSubtreeLength(1)
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly ParameterCollection _emptyCollection
|
||||||
|
= new ParameterCollection(_emptyCollectionFrames, 0);
|
||||||
|
|
||||||
private readonly RenderTreeFrame[] _frames;
|
private readonly RenderTreeFrame[] _frames;
|
||||||
private readonly int _ownerIndex;
|
private readonly int _ownerIndex;
|
||||||
|
|
||||||
|
|
@ -20,6 +28,11 @@ namespace Microsoft.AspNetCore.Blazor.Components
|
||||||
_ownerIndex = ownerIndex;
|
_ownerIndex = ownerIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an empty <see cref="ParameterCollection"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static ParameterCollection Empty => _emptyCollection;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns an enumerator that iterates through the <see cref="ParameterCollection"/>.
|
/// Returns an enumerator that iterates through the <see cref="ParameterCollection"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -64,52 +64,6 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
/// <param name="renderBatch">The changes to the UI since the previous call.</param>
|
/// <param name="renderBatch">The changes to the UI since the previous call.</param>
|
||||||
protected abstract void UpdateDisplay(RenderBatch renderBatch);
|
protected abstract void UpdateDisplay(RenderBatch renderBatch);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Updates the rendered state of the specified <see cref="IComponent"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="componentId">The identifier of the <see cref="IComponent"/> to render.</param>
|
|
||||||
protected void RenderNewBatch(int componentId)
|
|
||||||
{
|
|
||||||
// It's very important that components' rendering logic has no side-effects, and in particular
|
|
||||||
// components must *not* trigger Render from inside their render logic, otherwise you could
|
|
||||||
// easily get hard-to-debug infinite loops.
|
|
||||||
// Since rendering is currently synchronous and single-threaded, we can enforce the above by
|
|
||||||
// checking here that no other rendering process is already underway. This also means we only
|
|
||||||
// need a single _renderBatchBuilder instance that can be reused throughout the lifetime of
|
|
||||||
// the Renderer instance, which also means we're not allocating on a typical render cycle.
|
|
||||||
// In the future, if rendering becomes async, we'll need a more sophisticated system of
|
|
||||||
// capturing successive diffs from each component and probably serializing them for the
|
|
||||||
// interop calls instead of using shared memory.
|
|
||||||
|
|
||||||
// Note that Monitor.TryEnter is not yet supported in Mono WASM, so using the following instead
|
|
||||||
var renderAlreadyRunning = Interlocked.CompareExchange(ref _renderBatchLock, 1, 0) == 1;
|
|
||||||
if (renderAlreadyRunning)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Cannot render while a render is already in progress. " +
|
|
||||||
"Render logic must not have side-effects such as manually triggering other rendering.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_sharedRenderBatchBuilder.ComponentRenderQueue.Enqueue(componentId);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Process render queue until empty
|
|
||||||
while (_sharedRenderBatchBuilder.ComponentRenderQueue.Count > 0)
|
|
||||||
{
|
|
||||||
var nextComponentIdToRender = _sharedRenderBatchBuilder.ComponentRenderQueue.Dequeue();
|
|
||||||
RenderInExistingBatch(_sharedRenderBatchBuilder, nextComponentIdToRender);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateDisplay(_sharedRenderBatchBuilder.ToBatch());
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
RemoveEventHandlerIds(_sharedRenderBatchBuilder.DisposedEventHandlerIds.ToRange());
|
|
||||||
_sharedRenderBatchBuilder.Clear();
|
|
||||||
Interlocked.Exchange(ref _renderBatchLock, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Notifies the specified component that an event has occurred.
|
/// Notifies the specified component that an event has occurred.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -171,6 +125,48 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
|
||||||
? componentState
|
? componentState
|
||||||
: throw new ArgumentException($"The renderer does not have a component with ID {componentId}.");
|
: throw new ArgumentException($"The renderer does not have a component with ID {componentId}.");
|
||||||
|
|
||||||
|
private void RenderNewBatch(int componentId)
|
||||||
|
{
|
||||||
|
// It's very important that components' rendering logic has no side-effects, and in particular
|
||||||
|
// components must *not* trigger Render from inside their render logic, otherwise you could
|
||||||
|
// easily get hard-to-debug infinite loops.
|
||||||
|
// Since rendering is currently synchronous and single-threaded, we can enforce the above by
|
||||||
|
// checking here that no other rendering process is already underway. This also means we only
|
||||||
|
// need a single _renderBatchBuilder instance that can be reused throughout the lifetime of
|
||||||
|
// the Renderer instance, which also means we're not allocating on a typical render cycle.
|
||||||
|
// In the future, if rendering becomes async, we'll need a more sophisticated system of
|
||||||
|
// capturing successive diffs from each component and probably serializing them for the
|
||||||
|
// interop calls instead of using shared memory.
|
||||||
|
|
||||||
|
// Note that Monitor.TryEnter is not yet supported in Mono WASM, so using the following instead
|
||||||
|
var renderAlreadyRunning = Interlocked.CompareExchange(ref _renderBatchLock, 1, 0) == 1;
|
||||||
|
if (renderAlreadyRunning)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Cannot render while a render is already in progress. " +
|
||||||
|
"Render logic must not have side-effects such as manually triggering other rendering.");
|
||||||
|
}
|
||||||
|
|
||||||
|
_sharedRenderBatchBuilder.ComponentRenderQueue.Enqueue(componentId);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Process render queue until empty
|
||||||
|
while (_sharedRenderBatchBuilder.ComponentRenderQueue.Count > 0)
|
||||||
|
{
|
||||||
|
var nextComponentIdToRender = _sharedRenderBatchBuilder.ComponentRenderQueue.Dequeue();
|
||||||
|
RenderInExistingBatch(_sharedRenderBatchBuilder, nextComponentIdToRender);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDisplay(_sharedRenderBatchBuilder.ToBatch());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
RemoveEventHandlerIds(_sharedRenderBatchBuilder.DisposedEventHandlerIds.ToRange());
|
||||||
|
_sharedRenderBatchBuilder.Clear();
|
||||||
|
Interlocked.Exchange(ref _renderBatchLock, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void RenderInExistingBatch(RenderBatchBuilder batchBuilder, int componentId)
|
private void RenderInExistingBatch(RenderBatchBuilder batchBuilder, int componentId)
|
||||||
{
|
{
|
||||||
GetRequiredComponentState(componentId).RenderIntoBatch(batchBuilder);
|
GetRequiredComponentState(componentId).RenderIntoBatch(batchBuilder);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,10 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
public void SetParameters(ParameterCollection parameters)
|
public void SetParameters(ParameterCollection parameters)
|
||||||
{
|
{
|
||||||
parameters.AssignToProperties(this);
|
parameters.AssignToProperties(this);
|
||||||
_renderHandle.Render();
|
TriggerRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TriggerRender()
|
||||||
|
=> _renderHandle.Render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
|
|
@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act/Assert
|
// Act/Assert
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
var componentFrame = batch.ReferenceFrames
|
var componentFrame = batch.ReferenceFrames
|
||||||
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
|
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
|
||||||
|
|
@ -91,7 +91,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
|
|
||||||
// Act/Assert: first render
|
// Act/Assert: first render
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
var firstDiff = batch.DiffsByComponentId[componentId].Single();
|
var firstDiff = batch.DiffsByComponentId[componentId].Single();
|
||||||
Assert.Collection(firstDiff.Edits,
|
Assert.Collection(firstDiff.Edits,
|
||||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act/Assert: second render
|
// Act/Assert: second render
|
||||||
component.Message = "Modified message";
|
component.Message = "Modified message";
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
var secondBatch = renderer.Batches.Skip(1).Single();
|
var secondBatch = renderer.Batches.Skip(1).Single();
|
||||||
var secondDiff = secondBatch.DiffsByComponentId[componentId].Single();
|
var secondDiff = secondBatch.DiffsByComponentId[componentId].Single();
|
||||||
Assert.Collection(secondDiff.Edits,
|
Assert.Collection(secondDiff.Edits,
|
||||||
|
|
@ -127,7 +127,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
||||||
renderer.RenderNewBatch(parentComponentId);
|
parentComponent.TriggerRender();
|
||||||
var nestedComponentFrame = renderer.Batches.Single()
|
var nestedComponentFrame = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
|
.Single(frame => frame.FrameType == RenderTreeFrameType.Component);
|
||||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Assert: inital render
|
// Assert: inital render
|
||||||
nestedComponent.Message = "Render 1";
|
nestedComponent.Message = "Render 1";
|
||||||
renderer.RenderNewBatch(nestedComponentId);
|
nestedComponent.TriggerRender();
|
||||||
var batch = renderer.Batches[1];
|
var batch = renderer.Batches[1];
|
||||||
var firstDiff = batch.DiffsByComponentId[nestedComponentId].Single();
|
var firstDiff = batch.DiffsByComponentId[nestedComponentId].Single();
|
||||||
Assert.Collection(firstDiff.Edits,
|
Assert.Collection(firstDiff.Edits,
|
||||||
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act/Assert: re-render
|
// Act/Assert: re-render
|
||||||
nestedComponent.Message = "Render 2";
|
nestedComponent.Message = "Render 2";
|
||||||
renderer.RenderNewBatch(nestedComponentId);
|
nestedComponent.TriggerRender();
|
||||||
var secondBatch = renderer.Batches[2];
|
var secondBatch = renderer.Batches[2];
|
||||||
var secondDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single();
|
var secondDiff = secondBatch.DiffsByComponentId[nestedComponentId].Single();
|
||||||
Assert.Collection(secondDiff.Edits,
|
Assert.Collection(secondDiff.Edits,
|
||||||
|
|
@ -173,7 +173,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
Handler = args => { receivedArgs = args; }
|
Handler = args => { receivedArgs = args; }
|
||||||
};
|
};
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
var eventHandlerId = renderer.Batches.Single()
|
var eventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -202,7 +202,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.CloseComponent();
|
builder.CloseComponent();
|
||||||
});
|
});
|
||||||
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
var parentComponentId = renderer.AssignComponentId(parentComponent);
|
||||||
renderer.RenderNewBatch(parentComponentId);
|
parentComponent.TriggerRender();
|
||||||
|
|
||||||
// Arrange: Render nested component
|
// Arrange: Render nested component
|
||||||
var nestedComponentFrame = renderer.Batches.Single()
|
var nestedComponentFrame = renderer.Batches.Single()
|
||||||
|
|
@ -211,7 +211,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var nestedComponent = (EventComponent)nestedComponentFrame.Component;
|
var nestedComponent = (EventComponent)nestedComponentFrame.Component;
|
||||||
nestedComponent.Handler = args => { receivedArgs = args; };
|
nestedComponent.Handler = args => { receivedArgs = args; };
|
||||||
var nestedComponentId = nestedComponentFrame.ComponentId;
|
var nestedComponentId = nestedComponentFrame.ComponentId;
|
||||||
renderer.RenderNewBatch(nestedComponentId);
|
nestedComponent.TriggerRender();
|
||||||
|
|
||||||
// Find nested component's event handler ID
|
// Find nested component's event handler ID
|
||||||
var eventHandlerId = renderer.Batches[1]
|
var eventHandlerId = renderer.Batches[1]
|
||||||
|
|
@ -242,7 +242,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
|
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
var eventHandlerId = renderer.Batches.Single()
|
var eventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -259,19 +259,6 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
$"events because it does not implement {typeof(IHandleEvent).FullName}.", ex.Message);
|
$"events because it does not implement {typeof(IHandleEvent).FullName}.", ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void CannotRenderUnknownComponents()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var renderer = new TestRenderer();
|
|
||||||
|
|
||||||
// Act/Assert
|
|
||||||
Assert.Throws<ArgumentException>(() =>
|
|
||||||
{
|
|
||||||
renderer.RenderNewBatch(123);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CannotDispatchEventsToUnknownComponents()
|
public void CannotDispatchEventsToUnknownComponents()
|
||||||
{
|
{
|
||||||
|
|
@ -291,19 +278,32 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var renderer1 = new TestRenderer();
|
var renderer1 = new TestRenderer();
|
||||||
var renderer2 = new TestRenderer();
|
var renderer2 = new TestRenderer();
|
||||||
var component = new MessageComponent { Message = "Hello, world!" };
|
var component = new MultiRendererComponent();
|
||||||
var renderer1ComponentId = renderer1.AssignComponentId(component);
|
var renderer1ComponentId = renderer1.AssignComponentId(component);
|
||||||
renderer2.AssignComponentId(new TestComponent(null)); // Just so they don't get the same IDs
|
renderer2.AssignComponentId(new TestComponent(null)); // Just so they don't get the same IDs
|
||||||
var renderer2ComponentId = renderer2.AssignComponentId(component);
|
var renderer2ComponentId = renderer2.AssignComponentId(component);
|
||||||
|
|
||||||
// Act/Assert: Render component in renderer1
|
// Act/Assert
|
||||||
renderer1.RenderNewBatch(renderer1ComponentId);
|
component.TriggerRender();
|
||||||
Assert.True(renderer1.Batches.Single().DiffsByComponentId.ContainsKey(renderer1ComponentId));
|
var renderer1Batch = renderer1.Batches.Single();
|
||||||
Assert.Empty(renderer2.Batches);
|
var renderer1Diff = renderer1Batch.DiffsByComponentId[renderer1ComponentId].Single();
|
||||||
|
Assert.Collection(renderer1Diff.Edits,
|
||||||
|
edit =>
|
||||||
|
{
|
||||||
|
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||||
|
AssertFrame.Text(renderer1Batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||||
|
$"Hello from {nameof(MultiRendererComponent)}", 0);
|
||||||
|
});
|
||||||
|
|
||||||
// Act/Assert: Render same component in renderer2
|
var renderer2Batch = renderer2.Batches.Single();
|
||||||
renderer2.RenderNewBatch(renderer2ComponentId);
|
var renderer2Diff = renderer2Batch.DiffsByComponentId[renderer2ComponentId].Single();
|
||||||
Assert.True(renderer2.Batches.Single().DiffsByComponentId.ContainsKey(renderer2ComponentId));
|
Assert.Collection(renderer2Diff.Edits,
|
||||||
|
edit =>
|
||||||
|
{
|
||||||
|
Assert.Equal(RenderTreeEditType.PrependFrame, edit.Type);
|
||||||
|
AssertFrame.Text(renderer2Batch.ReferenceFrames[edit.ReferenceFrameIndex],
|
||||||
|
$"Hello from {nameof(MultiRendererComponent)}", 0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -320,7 +320,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
var nestedComponentFrame = renderer.Batches.Single()
|
var nestedComponentFrame = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -329,7 +329,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act: Second render
|
// Act: Second render
|
||||||
message = "Modified message";
|
message = "Modified message";
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var batch = renderer.Batches[1];
|
var batch = renderer.Batches[1];
|
||||||
|
|
@ -361,7 +361,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
var originalComponentFrame = renderer.Batches.Single()
|
var originalComponentFrame = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -375,7 +375,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act: Second render
|
// Act: Second render
|
||||||
firstRender = false;
|
firstRender = false;
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(256, childComponentInstance.IntProperty);
|
Assert.Equal(256, childComponentInstance.IntProperty);
|
||||||
|
|
@ -397,7 +397,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
});
|
});
|
||||||
|
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
var childComponentId = renderer.Batches.Single()
|
var childComponentId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
|
|
@ -406,7 +406,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act: Second render
|
// Act: Second render
|
||||||
firstRender = false;
|
firstRender = false;
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
var diff = renderer.Batches[1].DiffsByComponentId[childComponentId].Single();
|
var diff = renderer.Batches[1].DiffsByComponentId[childComponentId].Single();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -441,7 +441,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignComponentId(component);
|
||||||
|
|
||||||
// Act/Assert 1: First render, capturing child component IDs
|
// Act/Assert 1: First render, capturing child component IDs
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
||||||
var childComponentIds = rootComponentDiff
|
var childComponentIds = rootComponentDiff
|
||||||
|
|
@ -454,7 +454,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Act: Second render
|
// Act: Second render
|
||||||
firstRender = false;
|
firstRender = false;
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Assert: Applicable children are included in disposal list
|
// Assert: Applicable children are included in disposal list
|
||||||
Assert.Equal(new[] { 1, 3 }, renderer.Batches[1].DisposedComponentIDs);
|
Assert.Equal(new[] { 1, 3 }, renderer.Batches[1].DisposedComponentIDs);
|
||||||
|
|
@ -469,7 +469,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
UIEventHandler origEventHandler = args => { eventCount++; };
|
UIEventHandler origEventHandler = args => { eventCount++; };
|
||||||
var component = new EventComponent { Handler = origEventHandler };
|
var component = new EventComponent { Handler = origEventHandler };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
var origEventHandlerId = renderer.Batches.Single()
|
var origEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
||||||
|
|
@ -484,7 +484,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
// Now change the attribute value
|
// Now change the attribute value
|
||||||
var newEventCount = 0;
|
var newEventCount = 0;
|
||||||
component.Handler = args => { newEventCount++; };
|
component.Handler = args => { newEventCount++; };
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Act/Assert 2: Can no longer fire the original event, but can fire the new event
|
// Act/Assert 2: Can no longer fire the original event, but can fire the new event
|
||||||
Assert.Throws<ArgumentException>(() =>
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
|
@ -506,7 +506,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
UIEventHandler origEventHandler = args => { eventCount++; };
|
UIEventHandler origEventHandler = args => { eventCount++; };
|
||||||
var component = new EventComponent { Handler = origEventHandler };
|
var component = new EventComponent { Handler = origEventHandler };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
var origEventHandlerId = renderer.Batches.Single()
|
var origEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
||||||
|
|
@ -520,7 +520,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Now remove the event attribute
|
// Now remove the event attribute
|
||||||
component.Handler = null;
|
component.Handler = null;
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Act/Assert 2: Can no longer fire the original event
|
// Act/Assert 2: Can no longer fire the original event
|
||||||
Assert.Throws<ArgumentException>(() =>
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
|
@ -546,7 +546,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var rootComponentId = renderer.AssignComponentId(component);
|
var rootComponentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
var rootComponentDiff = batch.DiffsByComponentId[rootComponentId].Single();
|
||||||
var rootComponentFrame = batch.ReferenceFrames[0];
|
var rootComponentFrame = batch.ReferenceFrames[0];
|
||||||
|
|
@ -569,7 +569,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Now remove the EventComponent
|
// Now remove the EventComponent
|
||||||
component.IncludeChild = false;
|
component.IncludeChild = false;
|
||||||
renderer.RenderNewBatch(rootComponentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Act/Assert 2: Can no longer fire the original event
|
// Act/Assert 2: Can no longer fire the original event
|
||||||
Assert.Throws<ArgumentException>(() =>
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
|
@ -588,7 +588,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
UIEventHandler origEventHandler = args => { eventCount++; };
|
UIEventHandler origEventHandler = args => { eventCount++; };
|
||||||
var component = new EventComponent { Handler = origEventHandler };
|
var component = new EventComponent { Handler = origEventHandler };
|
||||||
var componentId = renderer.AssignComponentId(component);
|
var componentId = renderer.AssignComponentId(component);
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
var origEventHandlerId = renderer.Batches.Single()
|
var origEventHandlerId = renderer.Batches.Single()
|
||||||
.ReferenceFrames
|
.ReferenceFrames
|
||||||
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
.Where(f => f.FrameType == RenderTreeFrameType.Attribute)
|
||||||
|
|
@ -602,7 +602,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
|
|
||||||
// Now remove the ancestor element
|
// Now remove the ancestor element
|
||||||
component.SkipElement = true;
|
component.SkipElement = true;
|
||||||
renderer.RenderNewBatch(componentId);
|
component.TriggerRender();
|
||||||
|
|
||||||
// Act/Assert 2: Can no longer fire the original event
|
// Act/Assert 2: Can no longer fire the original event
|
||||||
Assert.Throws<ArgumentException>(() =>
|
Assert.Throws<ArgumentException>(() =>
|
||||||
|
|
@ -675,7 +675,7 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
var parentComponentId = renderer.AssignComponentId(parent);
|
var parentComponentId = renderer.AssignComponentId(parent);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
renderer.RenderNewBatch(parentComponentId);
|
parent.TriggerRender();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var batch = renderer.Batches.Single();
|
var batch = renderer.Batches.Single();
|
||||||
|
|
@ -739,9 +739,6 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
public new int AssignComponentId(IComponent component)
|
public new int AssignComponentId(IComponent component)
|
||||||
=> base.AssignComponentId(component);
|
=> base.AssignComponentId(component);
|
||||||
|
|
||||||
public new void RenderNewBatch(int componentId)
|
|
||||||
=> base.RenderNewBatch(componentId);
|
|
||||||
|
|
||||||
public new void DispatchEvent(int componentId, int eventHandlerId, UIEventArgs args)
|
public new void DispatchEvent(int componentId, int eventHandlerId, UIEventArgs args)
|
||||||
=> base.DispatchEvent(componentId, eventHandlerId, args);
|
=> base.DispatchEvent(componentId, eventHandlerId, args);
|
||||||
|
|
||||||
|
|
@ -910,5 +907,29 @@ namespace Microsoft.AspNetCore.Blazor.Test
|
||||||
builder.AddText(0, "Child is here");
|
builder.AddText(0, "Child is here");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class MultiRendererComponent : IComponent
|
||||||
|
{
|
||||||
|
private readonly List<RenderHandle> _renderHandles
|
||||||
|
= new List<RenderHandle>();
|
||||||
|
|
||||||
|
public void BuildRenderTree(RenderTreeBuilder builder)
|
||||||
|
=> builder.AddText(0, $"Hello from {nameof(MultiRendererComponent)}");
|
||||||
|
|
||||||
|
public void Init(RenderHandle renderHandle)
|
||||||
|
=> _renderHandles.Add(renderHandle);
|
||||||
|
|
||||||
|
public void SetParameters(ParameterCollection parameters)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TriggerRender()
|
||||||
|
{
|
||||||
|
foreach (var renderHandle in _renderHandles)
|
||||||
|
{
|
||||||
|
renderHandle.Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue