Skip to content

[Net11]Improve label mapping performance and ensure complete coverage including ToPlatform and subsequent property changes#35892

Open
devanathan-vaithiyanathan wants to merge 4 commits into
dotnet:net11.0from
devanathan-vaithiyanathan:net11-label-perf-imp
Open

[Net11]Improve label mapping performance and ensure complete coverage including ToPlatform and subsequent property changes#35892
devanathan-vaithiyanathan wants to merge 4 commits into
dotnet:net11.0from
devanathan-vaithiyanathan:net11-label-perf-imp

Conversation

@devanathan-vaithiyanathan

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

  • The iOS Label performance was improved in PR Improve iOS Label performance #30864. In that PR, the Label and Entry Feature Matrix test sample and script were modified, which caused discrepancies in the expected images due to changes which is due to test sample's default property values. In this PR, I updated the test sample and re-saved the images accordingly.

  • Windows - The Entry is now unfocused, so I re-saved the latest image.

  • Android - I modified the test sample by altering the default values and re-saved two images.

Additionally, while working on the test sample changes, I identified and fixed issues in FormattedStringExtensions.

These updates improve formatted text rendering on iOS by correctly propagating span properties (font, character spacing, and line-break settings) from the label to each span. The layout logic is also more robust, falling back to MAUI’s calculated size when iOS has not yet provided a valid label size, preventing incorrect text positioning and rendering issues.

Issues Fixed

Contributing to #30864

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35892

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35892"

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Jun 12, 2026
@kubaflo

kubaflo commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

AI code review refresh for net11.0 target

Head reviewed: aedd137875fb05f9b16dcd5f09f2e8505ce97aac (commit "Candidate failure changes added", 2026-06-12)
Target branch: net11.0 · State: OPEN, Draft (WIP)

Verdict: Needs discussion (WIP)

Solid, well-reasoned approach with a large global blast radius and some scope creep. No definite bugs found in the changed source, but several items below warrant confirmation before this leaves WIP.

What the change does (independent reading of the diff)

  • Introduces a high‑priority TextMapper sub‑mapper for Label/Entry (and reorders TextButtonMapper for Button) so Text is mapped before dependent text‑style props (Font, CharacterSpacing, LineHeight, TextDecorations, alignment, TextColor). On iOS these props mutate the AttributedText produced by MapText, so ordering matters.
  • Guards MapText/MapFormatting/MapFormattedText/MapFont with IsConnectingHandler() so the full attributed‑string is not rebuilt repeatedly during handler connection (the performance win). At runtime (non‑connect) behavior is preserved.
  • EntryHandler.iOS.MapFormatting now routes through handler.UpdateValue(nameof(...)) instead of calling UpdateMaxLength/UpdateCharacterSpacing/UpdateHorizontalTextAlignment directly — single source of truth via the mapper.
  • FormattedStringExtensions.ToNSAttributedString gains a defaultLineBreakMode optional param (+ a #if !MACOS / #else NSLineBreakMode branch); PublicAPI.Unshipped updated with proper *REMOVED*+added entries for net‑ios and net‑maccatalyst.
  • New EntryHandler.iOS.MapBackground (image/null/empty handling); new Entry.MapTextTransform.

Prior review reconciliation

No prior PR reviews, review comments, or earlier fleet markers exist (only the dogfood bot comment). Nothing to reconcile; no outstanding ❌ findings.

CI status

Build 1461094 still in progress. Most build/pack/Helix/integration jobs pass; 3 iOS jobs fail: RunOniOS_MauiRelease, RunOniOS_MauiReleaseTrimFull, RunOniOS_MauiReleaseTrimFull_CoreCLR. Root cause = HybridWebView IL2026 trim‑analysis errors → NETSDK1144 "Optimizing assemblies for size failed" while building a template app. This is a trimming/template‑infra issue unrelated to the Label/Entry/Button mapping changes and appears as pre‑existing net11 preview‑ILLink noise. iOS Debug + NativeAOT + Blazor iOS all pass.

Blast radius / failure‑mode probing

The Core handler files are cross‑platform, so the mapper reordering + connection guards affect every Label, Entry, and Button instance on all platforms, not just iOS.

  • Because MapText now skips MapFormatting during connect, correctness on Android/Windows/Tizen relies entirely on the individual property maps in TextMapper running on connect. They are present, so this should be safe — please confirm with Android/Windows device + FeatureMatrix runs.
  • Verified IsConnectingHandler() exists for both IElement and IElementHandler (internal extensions), and Paint.IsNullOrEmpty() is null‑safe, so entry.Background.IsNullOrEmpty() won't NRE.

Concise findings

  1. Scope creep (discuss/split): EntryHandler.iOS.MapBackground and Entry now overriding Background mapping is unrelated to "label mapping performance." It changes iOS Entry background behavior (previously ViewHandler.MapBackground). Justify or split into its own PR.
  2. macOS PublicAPI gap (verify): the new #else (NSLineBreakMode) branch implies a MACOS compile path, but only net‑ios/net‑maccatalyst PublicAPI files were updated. Controls.Core has no net‑macos PublicAPI baseline, so likely a no‑op — confirm no MACOS target builds this with the new default‑param signature.
  3. Snapshot churn (verify): large number of iOS/Android/Windows/Mac snapshot updates. Confirm these are intended re‑renders, not silent regressions, before un‑drafting.
  4. Nit: several changed files now lack a trailing newline (\ No newline at end of file).
  5. Tests: coverage is via FeatureMatrix UI tests + snapshots; consider a focused unit test asserting Text precedes dependent props in the mapper order to lock in the invariant.

Confidence

Medium. Source‑level reasoning is high‑confidence (changes read cleanly, key invariants verified). Runtime/visual correctness across non‑iOS platforms and snapshot validity are unverified here and depend on the in‑progress CI + device/UI tests.


Automated non‑binding review. This is not an approval and does not request changes; a human maintainer owns the merge decision.

@vishnumenon2684 vishnumenon2684 changed the title [WIP][Net11]Improve label mapping performance and ensure complete coverage including ToPlatform and subsequent property changes [Net11]Improve label mapping performance and ensure complete coverage including ToPlatform and subsequent property changes Jun 15, 2026
@devanathan-vaithiyanathan devanathan-vaithiyanathan marked this pull request as ready for review June 15, 2026 11:41

@kubaflo kubaflo 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.

PR #35892 — [Net11] Improve Label mapping performance + complete coverage (ToPlatform & subsequent property changes)

Verdict: NEEDS_DISCUSSION (confidence: medium) — HEAD aedd137. The core change is correct — the deep reviews (opus-4.8, opus-4.6) confirmed no Label/Entry mappings were dropped and runtime (non-connect) behavior is preserved. Three precise, non-blocking items remain (2 inline + an API note); CI red is the known flake set.

What it does (sound)

Consolidates the Label/Entry/Button mappers so Text is mapped first (into a dedicated TextMapper) and IsConnectingHandler() guards skip redundant re-mapping during connect — avoiding repeated AttributedText rebuilds on iOS. The ToNSAttributedString LineBreakMode plumbing is a real fix. Mapper consolidation and ordering were independently vetted as coherent by 3 of 4 models.

Findings (inline)

  • ⚠️ EntryHandler.cs:30 — the Text-ordering comment is inaccurate (HorizontalTextAlignment/VerticalTextAlignment are declared before Text) and the resulting order diverges from Label/Button. Benign at runtime, but misleading in an ordering-focused PR. (opus-4.8 + opus-4.6 consensus.)
  • 💡 EntryHandler.cs:39EntryPriorityMapper is now orphaned dead code (confirmed via git grep at HEAD); remove it.
  • 💡 FormattedStringExtensions.cs:43 — adding the optional defaultLineBreakMode is a binary-breaking change to a shipped public Platform extension; handled via *REMOVED* in PublicAPI (gate satisfied) — flagging to confirm the break is intentional vs. adding a preserving overload.

Dropped (false positive)

A model flagged Entry.Mapper.cs MapTextTransform → MapText as "bypassing UpdateValue/user customizations." Dropped: the ReplaceMapping(TextTransform, MapText) wiring is pre-existing — the PR only adds an IsConnectingHandler() guard around it (a perf optimization), and opus-4.8 confirmed runtime behavior is preserved. Not a new defect.

CI — known flakes

Red legs are the universal set seen across all PRs today: Build Analysis, AOT macOS, RunOniOS_MauiRelease/MauiReleaseTrimFull/TrimFull_CoreCLR. The Debug-passes / Release+Trim+AOT-fails pattern matches trimming-baseline noise; RunOniOS_MauiDebug, MauiRelease_CoreCLR, MauiNativeAOT pass. Not PR-caused.

[nameof(IEntry.IsPassword)] = MapIsPassword,
[nameof(IEntry.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IEntry.VerticalTextAlignment)] = MapVerticalTextAlignment,
// Ensure Text is mapped before LineHeight/Decorations/CharacterSpacing/HorizontalTextAlignment/TextColor/Font

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.

This ordering comment doesn't match the actual order, and the order diverges from Label/Button. The comment says "Ensure Text is mapped before LineHeight/Decorations/CharacterSpacing/HorizontalTextAlignment/TextColor/Font", but in this same TextMapper HorizontalTextAlignment (line 28) and VerticalTextAlignment (line 29) are declared before Text (line 32). It's benign at runtime since text alignment on UITextField is independent of the AttributedText built when mapping Text — but in a PR whose whole point is mapper ordering, the misleading comment plus the inconsistency with the Label/Button mappers is a maintenance trap. Either move Text above the alignment entries, or scope the comment to the properties that truly must follow Text (Font, CharacterSpacing, TextColor).

[nameof(IEntry.TextColor)] = MapTextColor
};

public static IPropertyMapper<IEntry, IEntryHandler> Mapper = new PropertyMapper<IEntry, IEntryHandler>(TextMapper, ViewHandler.ViewMapper)

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.

EntryPriorityMapper (line 20) is now dead code. Mapper here chains (TextMapper, ViewHandler.ViewMapper) and no longer references EntryPriorityMapper, and its only entry (MaxLength) was relocated into TextMapper (line 33). Confirmed via git grep at this commit that nothing else references it. Removing the orphaned field (lines 20-23) avoids confusion.

TextTransform defaultTextTransform = TextTransform.Default)
=> formattedString.ToNSAttributedString(fontManager, defaultLineHeight, defaultHorizontalAlignment, defaultFont, defaultColor, defaultTextTransform, LineBreakMode.WordWrap, defaultCharacterSpacing: 0d);
TextTransform defaultTextTransform = TextTransform.Default,
LineBreakMode defaultLineBreakMode = LineBreakMode.WordWrap)

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.

Adding the optional defaultLineBreakMode parameter changes the signatures of the public ToNSAttributedString(this FormattedString, ...) and (this Span, ...) extension methods. You've correctly recorded this in PublicAPI.Unshipped.txt via *REMOVED* + the new signature, so the API gate is satisfied — but note that adding an optional parameter is a binary-breaking change: already-compiled external consumers bound to the old metadata signature will fail to resolve. If preserving binary compat for these public Platform extensions matters, consider keeping the existing overload and adding a new one that takes defaultLineBreakMode. If the break is intentional (internal-use platform helper), this is fine as-is — flagging for an explicit decision.

…ing ToPlatform and subsequent property changes

Co-Authored-By: Tamilarasan-Paranthaman <93904422+Tamilarasan-Paranthaman@users.noreply.github.com>
Co-Authored-By: albyrock87 <albyrock87@gmail.com>
Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>

@kubaflo kubaflo 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.

PR #35892 - [Net11] Improve Label mapping performance + complete coverage

Re-review at HEAD 0c2e170 (prior review: NEEDS_DISCUSSION at aedd137). Consensus verdict from all 4 models: NEEDS_CHANGES (high confidence).

What changed

This PR continues the iOS Label/Entry/Button mapping-performance work from #30864. It introduces a high-priority TextMapper so Text is mapped before dependent text-style properties, guards MapText/MapFormatting with IsConnectingHandler() to avoid rebuilding the iOS AttributedText repeatedly during handler connection, routes EntryHandler.iOS.MapFormatting through handler.UpdateValue(...), fixes span-property propagation in FormattedStringExtensions, and re-saves a large set of Android/iOS/Mac/Windows FeatureMatrix snapshots (587 additions across 104 files).

Consensus verdict: NEEDS_CHANGES

The latest push introduced a build-breaking regression. EntryHandler.iOS.cs now declares MapBackground(IEntryHandler, IEntry) twice with an identical signature and body (lines 56-78 and 80-102) - a CS0111 "member already defined" error. The file compiles for both iOS and MacCatalyst, which directly explains the red Build macOS (Debug/Release) and Pack macOS legs in CI; the duplicate did not exist at the prior head aedd137. All four models flagged this independently, and it is the single blocking issue: remove one of the two copies and the build should recover.

Prior concerns (still unaddressed, not re-filed inline)

Two non-blocking items from the prior NEEDS_DISCUSSION review remain, but are already documented in the PR discussion, so they are not re-filed as fresh inline comments: (1) EntryPriorityMapper (EntryHandler.cs:20-23) is orphaned dead code - it is no longer passed to the Mapper constructor (which chains TextMapper -> ViewMapper) and its only entry, MaxLength, is already present in TextMapper; and (2) the comment at EntryHandler.cs:30-31 states Text is mapped before HorizontalTextAlignment, yet HorizontalTextAlignment/VerticalTextAlignment (lines 28-29) are declared before Text (line 32) - harmless for iOS UITextField (alignment is view-level) but misleading in an ordering-focused PR. The core mapper consolidation itself was independently vetted as correct: no mappings were dropped and runtime (non-connect) behavior is preserved.

}
}

public static void MapBackground(IEntryHandler handler, IEntry entry)

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.

MapBackground(IEntryHandler, IEntry) is declared twice in this file with an identical signature and body (lines 56-78 and 80-102) - a CS0111 "member already defined" compile error that breaks every iOS/MacCatalyst build and matches the failing Build macOS (Debug/Release) and Pack macOS legs in CI. The base branch already defined this method; the latest push re-added it. Remove one of the two copies.

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

Labels

area-controls-label Label, Span partner/syncfusion Issues / PR's with Syncfusion collaboration platform/ios platform/macos macOS / Mac Catalyst

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants