Fix Path.Data and Path.RenderTransform visual tree leaks with shared resources - #36097
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36097Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36097" |
This comment has been minimized.
This comment has been minimized.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 1 findings
See inline comments for details.
| { | ||
| } | ||
|
|
||
| ~Path() |
There was a problem hiding this comment.
[major] Public API Surface / Build — Adding a destructor to public Path introduces a new finalizer API entry, but the PR does not update the Controls PublicAPI.Unshipped.txt baselines. The shipped API files already track destructors for Shape, Border, and other public types, so API validation is likely to fail for Microsoft.Maui.Controls.Shapes.Path.~Path() -> void on each target. Either add the new destructor entries to the appropriate src/Controls/src/Core/PublicAPI/*/PublicAPI.Unshipped.txt files, or avoid introducing a Path finalizer by moving the cleanup to an already-finalized base/type-level cleanup pattern.
MauiBot
left a comment
There was a problem hiding this comment.
AI Review Summary
@devanathan-vaithiyanathan — new AI review results are available based on this last commit:
c94dcd9. To request a fresh review after new comments or commits, comment/review rerun.
🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix
Gate Result: ✅ PASSED
Platform: IOS · Base: main · Merge base: 19abc43e
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🧪 PathSharedResourcesMemoryLeakTests PathSharedResourcesMemoryLeakTests |
✅ FAIL — 35s | ✅ PASS — 18s |
🔴 Without fix — 🧪 PathSharedResourcesMemoryLeakTests: FAIL ✅ · 35s
Determining projects to restore...
Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 754 ms).
Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/TestUtils/TestUtils.csproj (in 5.6 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 6.14 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/Core.UnitTests/Controls.Core.UnitTests.csproj (in 6.14 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 6.65 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 6.65 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 6.65 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 6.65 sec).
Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 6.66 sec).
1 of 10 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0/Microsoft.Maui.Maps.dll
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0/Microsoft.Maui.Controls.Maps.dll
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0/Microsoft.Maui.Controls.Xaml.dll
TestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
Controls.Core.UnitTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.07] Discovering: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.55] Discovered: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.55] Starting: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.61] SharedGeometryAndTransform_DoNotKeepPathAlive [FAIL]
[xUnit.net 00:00:00.61] Path was not collected. Shared PathGeometry and/or ScaleTransform are holding strong references to Path via event subscriptions. Use weak proxies to fix.
[xUnit.net 00:00:00.61] Stack Trace:
[xUnit.net 00:00:00.61] /_/src/Controls/tests/Core.UnitTests/Shapes/PathSharedResourcesMemoryLeakTests.cs(108,0): at Microsoft.Maui.Controls.Core.UnitTests.Shapes.PathSharedResourcesMemoryLeakTests.SharedGeometryAndTransform_DoNotKeepPathAlive()
[xUnit.net 00:00:00.61] at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
[xUnit.net 00:00:00.61] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[xUnit.net 00:00:00.61] SharedRenderTransform_DoesNotKeepPathAlive [FAIL]
[xUnit.net 00:00:00.61] Path was not collected. The shared ScaleTransform is holding a strong reference to Path via its PropertyChanged event handler. Use WeakNotifyPropertyChangedProxy to fix.
[xUnit.net 00:00:00.61] Stack Trace:
[xUnit.net 00:00:00.61] /_/src/Controls/tests/Core.UnitTests/Shapes/PathSharedResourcesMemoryLeakTests.cs(76,0): at Microsoft.Maui.Controls.Core.UnitTests.Shapes.PathSharedResourcesMemoryLeakTests.SharedRenderTransform_DoesNotKeepPathAlive()
[xUnit.net 00:00:00.61] at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
[xUnit.net 00:00:00.61] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[xUnit.net 00:00:00.61] SharedPathGeometry_DoesNotKeepPathAlive [FAIL]
[xUnit.net 00:00:00.61] Path was not collected. The shared PathGeometry is holding a strong reference to Path via its PropertyChanged event handler. Use WeakGeometryChangedProxy to fix.
[xUnit.net 00:00:00.61] Stack Trace:
[xUnit.net 00:00:00.61] /_/src/Controls/tests/Core.UnitTests/Shapes/PathSharedResourcesMemoryLeakTests.cs(57,0): at Microsoft.Maui.Controls.Core.UnitTests.Shapes.PathSharedResourcesMemoryLeakTests.SharedPathGeometry_DoesNotKeepPathAlive()
[xUnit.net 00:00:00.61] at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
[xUnit.net 00:00:00.61] at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
[xUnit.net 00:00:00.61] Finished: Microsoft.Maui.Controls.Core.UnitTests
Failed SharedGeometryAndTransform_DoNotKeepPathAlive [19 ms]
Error Message:
Path was not collected. Shared PathGeometry and/or ScaleTransform are holding strong references to Path via event subscriptions. Use weak proxies to fix.
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.Shapes.PathSharedResourcesMemoryLeakTests.SharedGeometryAndTransform_DoNotKeepPathAlive() in /_/src/Controls/tests/Core.UnitTests/Shapes/PathSharedResourcesMemoryLeakTests.cs:line 108
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Failed SharedRenderTransform_DoesNotKeepPathAlive [7 ms]
Error Message:
Path was not collected. The shared ScaleTransform is holding a strong reference to Path via its PropertyChanged event handler. Use WeakNotifyPropertyChangedProxy to fix.
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.Shapes.PathSharedResourcesMemoryLeakTests.SharedRenderTransform_DoesNotKeepPathAlive() in /_/src/Controls/tests/Core.UnitTests/Shapes/PathSharedResourcesMemoryLeakTests.cs:line 76
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Failed SharedPathGeometry_DoesNotKeepPathAlive [5 ms]
Error Message:
Path was not collected. The shared PathGeometry is holding a strong reference to Path via its PropertyChanged event handler. Use WeakGeometryChangedProxy to fix.
Stack Trace:
at Microsoft.Maui.Controls.Core.UnitTests.Shapes.PathSharedResourcesMemoryLeakTests.SharedPathGeometry_DoesNotKeepPathAlive() in /_/src/Controls/tests/Core.UnitTests/Shapes/PathSharedResourcesMemoryLeakTests.cs:line 57
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Test Run Failed.
Total tests: 3
Failed: 3
Total time: 0.8880 Seconds
🟢 With fix — 🧪 PathSharedResourcesMemoryLeakTests: PASS ✅ · 18s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
##vso[build.updatebuildnumber]10.0.90-ci+azdo.14473038
Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0/Microsoft.Maui.Controls.Xaml.dll
Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0/Microsoft.Maui.Controls.Maps.dll
TestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/TestUtils/Debug/netstandard2.0/Microsoft.Maui.TestUtils.dll
Controls.Core.UnitTests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core.UnitTests/Debug/net10.0/Microsoft.Maui.Controls.Core.UnitTests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.07] Discovering: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.61] Discovered: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.62] Starting: Microsoft.Maui.Controls.Core.UnitTests
[xUnit.net 00:00:00.66] Finished: Microsoft.Maui.Controls.Core.UnitTests
Passed SharedGeometryAndTransform_DoNotKeepPathAlive [14 ms]
Passed SharedRenderTransform_DoesNotKeepPathAlive [4 ms]
Passed SharedPathGeometry_DoesNotKeepPathAlive [4 ms]
Test Run Successful.
Total tests: 3
Passed: 3
Total time: 0.9303 Seconds
📁 Fix files reverted (2 files)
src/Controls/src/Core/Internals/WeakEventProxy.cssrc/Controls/src/Core/Shapes/Path.cs
📋 Pre-Flight — Context & Validation
Issue: #35860 - Path.Data / Path.RenderTransform leaks Path visual trees when using shared app-level PathGeometry or ScaleTransform
PR: #36097 - Fix Path.Data and Path.RenderTransform visual tree leaks with shared resources
Platforms Affected: iOS, Android; managed Controls fix is cross-platform
Files Changed: 2 implementation, 1 test
Key Findings
- Root cause: long-lived shared
PathGeometry/ScaleTransformresources strongly retained transientPathinstances through event subscriptions. - PR fix: weak-event subscription handling for
Path.DataandPath.RenderTransform, plus unit tests for shared geometry/transform GC collection. - Public issue reproduction reports 1200 retained
Pathinstances and 200 MB retained payload after 50 iOS navigation cycles; validation comments also reproduce on iOS and Android. - GitHub CLI was unauthenticated, so context gathering used local branch diff and public GitHub API; authenticated CI/AzDO details were unavailable.
Code Review Summary
Verdict: NEEDS_DISCUSSION
Confidence: low
Errors: 0 | Warnings: 2 | Suggestions: 1
Key code review findings:
⚠️ WeakGeometryChangedProxyinWeakEventProxy.cscouples shared weak-event infrastructure to Shapes; a nestedPathproxy would match existing scoping precedent.⚠️ OneEventHandlercallback handles bothPropertyChangedandInvalidatePathGeometryRequested; valid but less obvious for maintainers.- 💡 Existing tests do not explicitly cover
Datareassignment from one shared geometry to another.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #36097 | Adds WeakGeometryChangedProxy to shared WeakEventProxy.cs and uses weak proxies from Path.cs |
✅ PASSED (Gate) | WeakEventProxy.cs, Path.cs, unit tests |
Original PR |
🔬 Code Review — Deep Analysis
Code Review — PR #36097
Independent Assessment
What this changes: Path.cs replaces direct strong-reference event subscriptions on Geometry.PropertyChanged, PathGeometry.InvalidatePathGeometryRequested, and Transform.PropertyChanged with weak-reference proxy subscriptions. WeakEventProxy.cs gains WeakGeometryChangedProxy. Unit tests verify that shared PathGeometry and ScaleTransform resources do not keep transient Path instances alive.
Inferred motivation: Shared app-level geometry/transform resources can live for the application lifetime. When they store instance event handlers from transient Path controls, the shared resource strongly roots the old Path, its page graph, and binding-context payload after navigation.
Reconciliation with PR Narrative
Author claims: Shared PathGeometry / ScaleTransform resources keep Path alive via strong event subscriptions; the fix uses weak-event subscription handling; tested on Android, Windows, iOS, and Mac.
Agreement/disagreement: The code matches the described root cause and fix. Platform testing claims could not be independently verified because GitHub CLI/AzDO auth was unavailable.
Prior Review Reconciliation
| Prior ❌ Error Finding | Source | Status | Evidence |
|---|---|---|---|
| — | — | — | — |
No prior ❌ Error findings found from public PR comments or inline review comments.
Blast Radius Assessment
- Runs for all instances: no; subscriptions are created only when
Path.DataorPath.RenderTransformis non-null. - Startup impact: no static startup path is introduced.
- Static/shared state: none; proxy fields are per-
Pathinstance.
CI Status
- Required-check result: undetermined locally;
ghwas unauthenticated. - Classification: undetermined.
- Action taken: confidence capped because required checks could not be queried through authenticated tooling.
Findings
⚠️ Warning — WeakGeometryChangedProxy placement couples shared weak-event infrastructure to Shapes
WeakEventProxy.cs is general Controls infrastructure, but the PR adds using Microsoft.Maui.Controls.Shapes and a geometry-specific proxy there. The analogous brush proxy is scoped near its consumer (Shape.WeakBrushChangedProxy), so a nested Path proxy would reduce blast radius.
⚠️ Warning — Shared callback signature obscures PropertyChangedEventArgs
WeakGeometryChangedProxy.OnGeometryChanged(object?, EventArgs) is subscribed to both PropertyChanged and InvalidatePathGeometryRequested. This is valid method-group variance and behaviorally correct, but less obvious to maintainers than a typed property-changed proxy plus a separate invalidate proxy or an explanatory scoped implementation.
💡 Suggestion — Add reassignment regression coverage
The existing tests cover collection after assigning shared geometry, transform, and both. A reassignment test would explicitly cover unsubscribe-from-old/subscribe-to-new behavior.
Failure-Mode Probing
- Shared resource outlives
Path: weak proxy prevents the resource from strongly rooting thePathdelegate. DataorRenderTransformset to null:propertyChangingunsubscribes before the new null value is applied.- Same resource assigned twice: proxy
Subscribeunsubscribes from the previous source before re-subscribing. - Multiple paths share one geometry: each path has an independent proxy and dead proxies self-unsubscribe on finalizer/event callback.
Verdict: NEEDS_DISCUSSION
Confidence: low
Summary: The PR's functional fix appears mechanically correct and the gate result supplied by the caller passed. The main review concern is maintainability/layering: the geometry-specific proxy can be scoped to Path.cs without changing behavior.
🛠️ Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix | Nested WeakGeometryChangedProxy inside Path.cs; no Shapes dependency in WeakEventProxy.cs |
✅ PASS | 1 implementation file (+ tests retained) | Behavior-equivalent to PR, better layering/lower blast radius |
| PR | PR #36097 | Top-level WeakGeometryChangedProxy in WeakEventProxy.cs plus Path.cs weak proxy usage |
✅ PASSED (Gate) | 2 implementation files + tests | Original PR |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| maui-expert-reviewer | 1 | Yes | Candidate A nested proxy, Candidate B split proxies, Candidate C handler lifecycle, Candidate D CWT relay, Candidate E Window hook |
| orchestrator | 1 | Stop | Candidate 1 passed all targeted tests and is demonstrably better than the PR fix because it removes the shared-infrastructure layer violation while preserving behavior |
Exhausted: No — stopped by pass-and-better criterion.
Selected Fix: Candidate #1 — It passes the targeted regression tests and improves the PR's maintainability by scoping geometry-specific weak-event behavior to Path.cs instead of WeakEventProxy.cs.
🏁 Report — Final Recommendation
Comparative Candidate Report — PR #36097
Candidates compared
| Candidate | Approach | Regression result | Review/build risk | Rank |
|---|---|---|---|---|
pr-plus-reviewer |
Keeps the PR weak-event implementation and adds missing Path finalizer PublicAPI unshipped entries in all Controls API baselines. |
✅ Passed supplied gate by inheritance from PR fix. | ✅ Addresses the expert reviewer's major API baseline finding. | 1 |
try-fix-1 |
Moves WeakGeometryChangedProxy into Path.cs, keeping geometry-specific weak-event logic scoped to its only consumer while using WeakNotifyPropertyChangedProxy for transforms. |
✅ Passed targeted regression tests. | Path.~Path() PublicAPI entries; its recorded diff also contains unrelated HybridWebView.js noise, making it less merge-ready as submitted. |
2 |
pr |
Adds top-level WeakGeometryChangedProxy in shared weak-event infrastructure and uses weak proxies from Path.cs. |
✅ Passed supplied gate. | ❌ Missing finalizer PublicAPI unshipped entries flagged by expert review; also has a lower-severity layering concern because shared weak-event infrastructure imports Shapes. | 3 |
Analysis
All behaviorally relevant candidates fix the root leak mechanism: shared long-lived PathGeometry and ScaleTransform resources no longer strongly retain transient Path instances through event subscriptions. None of the candidates failed the supplied regression tests, so ranking is determined by completeness and merge risk.
try-fix-1 has the cleanest layering because it scopes geometry-specific event proxy logic inside Path.cs instead of coupling WeakEventProxy.cs to Shapes. However, as a STEP 5a candidate it lacks the required PublicAPI baseline entries for the newly introduced Path finalizer, and its recorded candidate diff includes unrelated generated HybridWebView.js changes. Those issues make it less safe to select as the single winning candidate.
pr passes the leak gate but is incomplete after expert review because API validation is likely to fail for Microsoft.Maui.Controls.Shapes.Path.~Path() -> void.
pr-plus-reviewer keeps the PR's tested behavior and applies the expert reviewer's actionable API baseline fix. Although it preserves the PR's lower-severity layering tradeoff, it is the most complete and lowest-risk candidate among the actual candidate set.
Winner
pr-plus-reviewer
It is the only candidate that both preserves the passing regression fix and incorporates the expert reviewer's required API baseline correction.
🧭 Next Steps — review latest findings
No alternative fix was selected for this run. Review the session findings and CI results before merging.
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
…resources (#36097) <!-- Please keep the note below for people who find this PR --> > [!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](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment whether this change resolves your issue. Thank you!<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform). The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped. Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms. ### Description of Change <!-- Enter description of the fix in this section --> Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35860 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/5bbfab0e-1978-46f9-91e2-a93b5b037ced" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/98c362a0-a10e-411b-91b6-d612105958a2" width="300" height="600"> |
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 whether this change resolves your issue. Thank you!
Issue Details
Path.Data and Path.RenderTransform can cause memory leaks when they use shared long-lived resources (PathGeometry / ScaleTransform).
The shared resource stays alive for app lifetime, and its event subscriptions can keep old Path controls alive after a page is popped.
Because those Path controls stay alive, related page objects and binding context data may also be retained.This is reproducible across platforms.
Description of Change
Added weak-event subscription handling so Path no longer holds strong references through shared geometry/transform change events.
Issues Fixed
Fixes #35860
Tested the behavior in the following platforms.
Before.mov
After.mov