Skip to content

Conversation

@DustinCampbell
Copy link
Member

@DustinCampbell DustinCampbell commented Aug 21, 2025

This change simplifies and reduces allocations during tag helper matching in DefaultRazorIntermediateNodeLoweringPhase. In addition, a handful of related intermediate nodes have been cleaned up somewhat, reducing the number of fields and making things a bit lazier. I recommend reviewing commit-by-commit as each commit has a descriptive message.


CI Build: https://dev.azure.com/dnceng/internal/_build/results?buildId=2777461&view=results
Test Insertion: https://dev.azure.com/devdiv/DevDiv/_git/VS/pullrequest/663965
Toolset Run: https://dev.azure.com/dnceng/internal/_build/results?buildId=2777462&view=results

It's unnecessary to create a new List<TagHelperDescriptor> for the TagHelperIntermediateNode.TagHelpers property and add tag helpers to it. Since TagHelperBinding.Descriptors is already an ImmutableArray<TagHelperDescriptor>, it can just be assigned to TagHelperIntermediateNode.TagHelpers.
Many intermediate nodes store several related tag helper objects. For example, TagHelperPropertyIntermediateNode stores both a BoundAttributeDesccriptor and a TagHelperDescriptor. However, for all intermediate nodes, the tag helper objects are always have a parent-child relationship. Now that tag helper objects actually provide a Parent property, we can use that and avoid extra fields.
TagHelperMatchingConventions.TryGetFirstBoundAttributeMatch(...) has four out parameters. This change consolidates them into a single out parameter of type TagHelperAttributeMatch. This allows some logic based on the out parameters to be encapsulated, such as whether a match expects a boolean or string value.
Add helper method to collect matches and use it throughout DefaultRazorIntermediateNodeLoweringPhase to reduce LINQ-related allocations.
The polyfill extension method in SpanExtensions were causing ambiguities on .NET builds.
Introduce DirectiveAttributeName helper struct that uses spans to defer creating strings until necessary.
- Enable nullability
- Make Children property lazy
- Remove unnecessary argument-null checks
- Add constructor that takes an TagHelperAttributeMatch and verifies that its a parameter match.
- Change IsIndexerNameMatch and BoundAttributeParameter properties to computed properties that return values from TagHelperAttributeMatch.
- Change other properties to init-only
- Make AttributeName, AttributeNameWithoutParameter, OriginalAttributeName, and AttributeStructure as required.
- Enable nullability
- Make Children property lazy
- Remove unnecessary argument-null checks
- Add constructor that takes an TagHelperAttributeMatch
- Change IsIndexerNameMatch and BoundAttribute properties to computed properties that return values from TagHelperAttributeMatch.
- Change other properties to init-only
- Make AttributeName, OriginalAttributeName, and AttributeStructure as required.
- Enable nullability
- Make Children property lazy
- Remove unnecessary argument-null checks
- Add constructor that takes an TagHelperAttributeMatch
- Change IsIndexerNameMatch and BoundAttribute properties to computed properties that return values from TagHelperAttributeMatch.
- Change other properties to init-only
- Make AttributeName, and AttributeStructure as required.
- Enable nullability
- Make Children property lazy
- Remove unnecessary argument-null checks
- Change properties to init-only
- Mark AttributeName, and AttributeStructure as required.
- Enable nullability
- Make Children property lazy
- Remove unnecessary argument-null checks
- Change properties to init-only
- Mark TagMode, and TagName as required.
@DustinCampbell DustinCampbell requested a review from a team as a code owner August 21, 2025 21:58
@DustinCampbell DustinCampbell requested review from a team and ToddGrun August 21, 2025 22:01
Copy link
Contributor

@ToddGrun ToddGrun left a comment

Choose a reason for hiding this comment

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

:shipit:

@DustinCampbell DustinCampbell merged commit 0c1a63f into dotnet:main Aug 22, 2025
11 checks passed
@DustinCampbell DustinCampbell deleted the reduce-allocations-in-tag-helper-matching branch August 22, 2025 16:32
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Aug 22, 2025
@akhera99 akhera99 modified the milestones: Next, 18.0 P1 Sep 22, 2025
@akhera99 akhera99 added this to the 18.0 P2 milestone Sep 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants