Skip to content

API review rename of AnchorMode#67313

Open
ilonatommy wants to merge 3 commits into
mainfrom
rename-api-review-66799
Open

API review rename of AnchorMode#67313
ilonatommy wants to merge 3 commits into
mainfrom
rename-api-review-66799

Conversation

@ilonatommy

@ilonatommy ilonatommy commented Jun 19, 2026

Copy link
Copy Markdown
Member

Rename following the decision in #66799 (comment).

Fixes #66799

@ilonatommy ilonatommy self-assigned this Jun 19, 2026
Copilot AI review requested due to automatic review settings June 19, 2026 08:37
@ilonatommy ilonatommy requested a review from a team as a code owner June 19, 2026 08:37
@ilonatommy ilonatommy added the area-blazor Includes: Blazor, Razor Components label Jun 19, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements the API review decision to rename VirtualizeAnchorMode.Beginning to VirtualizeAnchorMode.Start, updates Virtualize<TItem>.AnchorMode’s default accordingly, and adjusts the VirtualizeItemComparerAnalyzer to use concurrent collections.

Changes:

  • Rename VirtualizeAnchorMode.Beginning to Start, including XML docs and Virtualize<TItem>.AnchorMode default value.
  • Update Components unit tests and BasicTestApp test assets to use Start.
  • Change the analyzer’s per-operation-block tracking collections to concurrent variants.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/Components/Web/test/Virtualization/VirtualizeTest.cs Updates test helper default anchor mode to Start.
src/Components/Web/src/Virtualization/VirtualizeAnchorMode.cs Renames enum member BeginningStart and updates docs.
src/Components/Web/src/Virtualization/Virtualize.cs Updates AnchorMode default and doc reference to Start.
src/Components/Web/src/PublicAPI.Unshipped.txt Updates public API baseline for the renamed enum member.
src/Components/test/testassets/BasicTestApp/VirtualizationAnchorModeWindowScroll.razor Updates UI and defaults to use Start.
src/Components/test/testassets/BasicTestApp/VirtualizationAnchorMode.razor Updates UI and defaults to use Start.
src/Components/Analyzers/src/VirtualizeItemComparerAnalyzer.cs Switches internal tracking collections to concurrent types.

Comment thread src/Components/Web/src/Virtualization/VirtualizeAnchorMode.cs
{
var componentStack = new Stack<ComponentState>();
var completedVirtualizeComponents = new List<ComponentState>();
var componentStack = new ConcurrentStack<ComponentState>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm somewhat still confused. While this is a thread-safe collection, I don't get how the logic can work deterministically.

Roslyn will be invoking multiple operation actions concurrently. So there is no guarantee of order of Push/TryPeek calls.

Is the implementation relying on the order of method calls in user code and relying on getting the callbacks in the same order? I don't think this would work reliable and I'm quite surprised there are no flaky tests because of that (maybe it's somehow working by chance or there is something obvious I'm missing?)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the fact that we didn't have any flaky tests related to this analyzer before switching to the concurrent collection is also concerning.

@ilonatommy ilonatommy Jun 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I might have been too fast with agreeing the problem exists. In https://github.com/dotnet/aspnetcore/blame/a097744953e211590f86d0947dfcfafe14b6789d/src/Framework/AspNetCoreAnalyzers/src/Analyzers/RouteHandlers/RouteHandlerAnalyzer.cs#L45 that I used as an example of thread safe analyzer, the concurrent data structure is used in multiple blocks (RegisterOperationBlockStartAction, RegisterOperationBlockEndAction).
Blocks can run in parallel but code inside of one block (operation actions) always runs sequentially in the given thread:
https://github.com/dotnet/roslyn/blob/ab4cbf6de14bebf0b90771aaa1de52d780984e58/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerExecutor.cs#L1289

That's why nothing failed before and that's why we also have other non-thread safe structures in other analyzers, as long as they are block-scoped:

var capturedDiagnosticLocations = new HashSet<Location>();

I will remove the type change from this PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the implementation relying on the order of method calls in user code and relying on getting the callbacks in the same order?

Yes but for the analyzer to stop working correctly, the implementation for ExecuteOperationActions's loop would have to change, e.g. be transformed to be parallel or some sorting/reordering would need to be added before Roslyn enters that loop.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you mean operation callbacks are not called in parallel? That's quite surprising to me and sounds unexpected. @333fred is it safe to assume a guaranteed ordering of operation actions?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think it is safe to assume this. If you want to iterate via a stack, you should do so yourself via RegisterOperationBlockAction, and then iterating through ChildOperations manually.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words, we would not consider it a breaking change to start doing callbacks in parallel or out of order in any fashion, so long as Start comes before End.

var componentStack = new Stack<ComponentState>();
var completedVirtualizeComponents = new List<ComponentState>();
var componentStack = new ConcurrentStack<ComponentState>();
var completedVirtualizeComponents = new ConcurrentBag<ComponentState>();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@halter73 pointed to me in another PR that ConcurrentBag has big perf implications and ConcurrentQueue might be preferred in most cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API proposal for AnchorMode

4 participants