-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensure ComponentState is always disposed #48406
Conversation
@@ -34,7 +35,6 @@ Microsoft.AspNetCore.Components.Rendering.ComponentState | |||
Microsoft.AspNetCore.Components.Rendering.ComponentState.Component.get -> Microsoft.AspNetCore.Components.IComponent! | |||
Microsoft.AspNetCore.Components.Rendering.ComponentState.ComponentId.get -> int | |||
Microsoft.AspNetCore.Components.Rendering.ComponentState.ComponentState(Microsoft.AspNetCore.Components.RenderTree.Renderer! renderer, int componentId, Microsoft.AspNetCore.Components.IComponent! component, Microsoft.AspNetCore.Components.Rendering.ComponentState? parentComponentState) -> void | |||
Microsoft.AspNetCore.Components.Rendering.ComponentState.Dispose() -> void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a breaking change because ComponentState
is only becoming public
in 8.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.
I looked into ways this could be validated in tests or even at runtime normally, but didn't find a great option:
We would need to do something like treat the renderer as the boundary for a context in which We do have unit tests already that show component instances do get disposed during renderer disposal. Since this PR changes the disposal logic so that components are only disposed through disposal of their ComponentState, we do effectively have at least that level of coverage. |
Could we add some tracking logic on our TestRenderer to know when a ComponentState instance gets created and when it gets disposed? That should give us a way to track this in tests, isn't it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, just one comment about the tests
It's a good idea, so I've done it. However this has led to some further changes, so please re-review:
I think the end result is much clearer - this collapses about 6 different disposal code paths into just two (during a renderbatch, and during renderer teardown). The only drawback is that |
I think the virtual call on ComponentState is fine. Hopefully the JIT is able to see that there is only one implementation and devirtualize the calls. |
/backport to release/8.0-preview5 |
Started backporting to release/8.0-preview5: https://github.com/dotnet/aspnetcore/actions/runs/5070919992 |
Addresses an issue where
RenderTreeFrame[]
pooling became ineffective becauseComponentState
instances were only disposed if the component itself wasIDisposable
(and notIAsyncDisposable
).The approach is:
Renderer
, stop varying the code path based on different disposability patterns for the component. Just callcomponentState.DisposeAsync
in all cases.componentState.DisposeAsync
unconditionally releases the buffers before looking at the disposability pattern for the component and callingDispose
orDisposeAsync
as appropriate.