Ensure render batches aren't started from inside each other (#12917)
This commit is contained in:
parent
594916344d
commit
08349aba69
|
|
@ -409,6 +409,12 @@ namespace Microsoft.AspNetCore.Components.Rendering
|
|||
private void ProcessRenderQueue()
|
||||
{
|
||||
EnsureSynchronizationContext();
|
||||
|
||||
if (_isBatchInProgress)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot start a batch when one is already in progress.");
|
||||
}
|
||||
|
||||
_isBatchInProgress = true;
|
||||
var updateDisplayTask = Task.CompletedTask;
|
||||
|
||||
|
|
|
|||
|
|
@ -3395,6 +3395,27 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CannotStartOverlappingBatches()
|
||||
{
|
||||
// Arrange
|
||||
var renderer = new InvalidRecursiveRenderer();
|
||||
var component = new CallbackOnRenderComponent(() =>
|
||||
{
|
||||
// The renderer disallows one batch to be started inside another, because that
|
||||
// would violate all kinds of state tracking invariants. It's not something that
|
||||
// would ever happen except if you subclass the renderer and do something unsupported
|
||||
// that commences batches from inside each other.
|
||||
renderer.ProcessPendingRender();
|
||||
});
|
||||
var componentId = renderer.AssignRootComponentId(component);
|
||||
|
||||
// Act/Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(
|
||||
() => renderer.RenderRootComponent(componentId));
|
||||
Assert.Contains("Cannot start a batch when one is already in progress.", ex.Message);
|
||||
}
|
||||
|
||||
private class NoOpRenderer : Renderer
|
||||
{
|
||||
public NoOpRenderer() : base(new TestServiceProvider(), NullLoggerFactory.Instance)
|
||||
|
|
@ -4109,5 +4130,24 @@ namespace Microsoft.AspNetCore.Components.Test
|
|||
private class DerivedEventArgs : EventArgs
|
||||
{
|
||||
}
|
||||
|
||||
class CallbackOnRenderComponent : AutoRenderComponent
|
||||
{
|
||||
private readonly Action _callback;
|
||||
|
||||
public CallbackOnRenderComponent(Action callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
protected override void BuildRenderTree(RenderTreeBuilder builder)
|
||||
=> _callback();
|
||||
}
|
||||
|
||||
class InvalidRecursiveRenderer : TestRenderer
|
||||
{
|
||||
public new void ProcessPendingRender()
|
||||
=> base.ProcessPendingRender();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue