Skip to content

Commit

Permalink
fix: ensure dispose checks are performed before and after entering re…
Browse files Browse the repository at this point in the history
…nder lock
  • Loading branch information
egil committed Jul 11, 2023
1 parent c8508f7 commit e766065
Showing 1 changed file with 31 additions and 13 deletions.
44 changes: 31 additions & 13 deletions src/bunit.core/Rendering/TestRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ public Task DispatchEventAsync(
// if the event contains associated data.
lock (renderTreeUpdateLock)
{
if (disposed)
throw new ObjectDisposedException(nameof(TestRenderer));

var result = Dispatcher.InvokeAsync(() =>
{
ResetUnhandledException();
Expand Down Expand Up @@ -190,10 +193,16 @@ public void DisposeComponents()
/// <inheritdoc/>
internal void SetDirectParameters(IRenderedFragmentBase renderedComponent, ParameterView parameters)
{
if (disposed)
throw new ObjectDisposedException(nameof(TestRenderer));

// Calling SetDirectParameters updates the render tree
// if the event contains associated data.
lock (renderTreeUpdateLock)
{
if (disposed)
throw new ObjectDisposedException(nameof(TestRenderer));

var result = Dispatcher.InvokeAsync(() =>
{
try
Expand Down Expand Up @@ -240,20 +249,20 @@ protected override void ProcessPendingRender()
// so there is no need to lock in that method.
lock (renderTreeUpdateLock)
{
if (disposed)
{
logger.LogRenderCycleActiveAfterDispose();
return;
}

base.ProcessPendingRender();
}
}

/// <inheritdoc/>
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
{
if (disposed)
{
return Task.CompletedTask;
}

var renderEvent = new RenderEvent();

PrepareRenderEvent(renderBatch);
InvokeApplyRenderEvent();

Expand All @@ -273,7 +282,7 @@ void PrepareRenderEvent(in RenderBatch renderBatch)
renderEvent.SetUpdated(update.ComponentId, update.Edits.Count > 0);
}

foreach (var (key, rc) in renderedComponents)
foreach (var (_, rc) in renderedComponents)
{
LoadChangesIntoRenderEvent(rc.ComponentId);
}
Expand Down Expand Up @@ -394,10 +403,13 @@ protected override void Dispose(bool disposing)
if (disposed)
return;

disposed = true;

lock (renderTreeUpdateLock)
{
if (disposed)
return;

disposed = true;

if (disposing)
{
foreach (var rc in renderedComponents.Values)
Expand Down Expand Up @@ -467,6 +479,9 @@ private IReadOnlyList<IRenderedComponentBase<TComponent>> FindComponents<TCompon
// while this method searches through it.
lock (renderTreeUpdateLock)
{
if (disposed)
throw new ObjectDisposedException(nameof(TestRenderer));

FindComponentsInRenderTree(parentComponent.ComponentId);
}

Expand Down Expand Up @@ -548,9 +563,9 @@ private ArrayRange<RenderTreeFrame> GetOrLoadRenderTreeFrame(RenderTreeFrameDict
}

/// <inheritdoc/>
protected override void HandleException(Exception exception)
protected override void HandleException([NotNull] Exception exception)
{
if (exception is null || disposed)
if (disposed)
return;

logger.LogUnhandledException(exception);
Expand Down Expand Up @@ -579,11 +594,14 @@ private void AssertNoUnhandledExceptions()
// tests failing that should not be failing.
lock (renderTreeUpdateLock)
{
if (capturedUnhandledException is Exception unhandled && !disposed)
if (disposed)
return;

if (capturedUnhandledException is { } unhandled)
{
capturedUnhandledException = null;

if (unhandled is AggregateException aggregateException && aggregateException.InnerExceptions.Count == 1)
if (unhandled is AggregateException { InnerExceptions.Count: 1 } aggregateException)
{
ExceptionDispatchInfo.Capture(aggregateException.InnerExceptions[0]).Throw();
}
Expand Down

0 comments on commit e766065

Please sign in to comment.