Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@Xiaoy312
Copy link
Contributor

@Xiaoy312 Xiaoy312 commented Dec 17, 2025

GitHub Issue: closes unoplatform/uno-private#1670

PR Type:

  • 🐞 Bugfix
  • πŸ”„ Refactoring (no functional changes, no api changes)

What is the current behavior? πŸ€”

  1. FrameworkTemplate can leak if its view-factory method isn't static
  2. FrameworkTemplatePool still creates an entry for every data-template even if it is disabled

What is the new behavior? πŸš€

  1. FrameworkTemplate nows holds its view-factory with the new weak-delegate
  2. FrameworkTemplatePool wont create any entry when disabled

PR Checklist βœ…

Please check if your PR fulfills the following requirements:

Other information ℹ️

view-factory method are usually generated with static modifier, except when hot-reload is enable (which implies in DEBUG only)

Copilot AI review requested due to automatic review settings December 17, 2025 03:14
@Xiaoy312
Copy link
Contributor Author

todo: tests

Copy link
Contributor

Copilot AI left a comment

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 addresses memory leaks in the Uno Platform's template system by introducing weak references for delegate storage and optimizing template pooling. The changes prevent FrameworkTemplate instances from keeping view factories alive unnecessarily and avoid creating unnecessary pool entries when pooling is disabled.

Key Changes:

  • Introduces a new WeakDelegate<TDelegate> wrapper class to hold delegates with weak references to their targets
  • Updates FrameworkTemplate to store its view factory using WeakDelegate instead of direct delegate references
  • Optimizes FrameworkTemplatePool to skip creating pool entries when pooling is disabled

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
src/Uno.UI/Helpers/WeakDelegate.cs New helper class implementing weak delegate pattern to prevent memory leaks by holding delegate targets weakly
src/Uno.UI/UI/Xaml/FrameworkTemplate.cs Updates view factory storage to use WeakDelegate wrapper and fixes typo in XAML scope comment
src/Uno.UI/UI/Xaml/FrameworkTemplatePool.cs Refactors pool management to use TryGetTemplatePool and skip pool entry creation when pooling is disabled, plus fixes error message typo

Critical Issues Found:

  1. Inverted logic in TryGetTemplatePool at line 320 - returns null when pooling IS enabled instead of when disabled
  2. Non-existent API - HasSingleTarget doesn't exist on the Delegate class; should use GetInvocationList().Length == 1
  3. Missing issue reference in PR description - the PR must link to a GitHub issue per repository guidelines

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 188627 has failed on Uno.UI - CI.

@Xiaoy312 Xiaoy312 force-pushed the dev/xygu/20251216/hotreload-fwktemplate-leak branch from 32fa54f to c158701 Compare December 17, 2025 16:38
@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 188789 has failed on Uno.UI - CI.

@Xiaoy312 Xiaoy312 added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 17, 2025
Copilot AI review requested due to automatic review settings December 19, 2025 00:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.

Comment on lines 1 to 103
ο»Ώ#nullable enable

using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace Uno.UI.Helpers;

internal interface IDelegate<TDelegate> where TDelegate : Delegate
{
public object? Target { get; }
public MethodInfo Method { get; }
public TDelegate? Delegate { get; }
}

/// <summary>
/// Represents a plain wrapper over a normal delegate instance.
/// </summary>
/// <remarks>
/// Solely used to conform to the <see cref="IDelegate{TDelegate}"/> interface,
/// so <see cref="WeakDelegate{TDelegate}"/> and literal delegate can be used interchangeably.
/// </remarks>
/// <typeparam name="TDelegate">The type of delegate encapsulated by this instance. Must derive from <see cref="Delegate"/>.</typeparam>
internal class LiteralDelegate<TDelegate> : IDelegate<TDelegate>
where TDelegate : Delegate
{
public object? Target => Delegate!.Target;
public MethodInfo Method => Delegate!.Method;
public TDelegate? Delegate { get; }

public LiteralDelegate(TDelegate d)
{
Delegate = d;
}
}

/// <summary>
/// Represents a delegate that references its <see cref="Delegate.Target"/> weakly, allowing the target to be eventually garbage collected.
/// </summary>
/// <remarks>Use <see cref="WeakDelegate{TDelegate}"/> to hold a reference to a delegate without preventing its
/// target object from being collected by the garbage collector. This is useful for scenarios where you want to
/// avoid memory leaks caused by strong references. Only delegates with a single target are supported;
/// multicast delegates are not allowed.</remarks>
/// <typeparam name="TDelegate">The type of delegate to be referenced. Must derive from <see cref="Delegate"/>.</typeparam>
internal class WeakDelegate<TDelegate> : IDelegate<TDelegate>
where TDelegate : Delegate
{
public WeakReference? Instance { get; init; }
public MethodInfo Method { get; init; }

// static method delegate doesn't capture any target instance, so we can just reuse it
private TDelegate? _staticDelegate;

public WeakDelegate(TDelegate d)
{
if (!d.HasSingleTarget)
{
throw new NotImplementedException("Multi-cast delegate not supported");
}

if (d.Target is { } t)
{
Instance = new WeakReference(t);
Method = d.Method;
}
else
{
_staticDelegate = d;
Method = d.Method; // still used outside of this class for logging
}
}

public object? Target => Instance?.Target;

/// <summary>
/// Gets the delegate instance that targets the referenced object and method,
/// may be null if the target is no longer available.
/// </summary>
/// <remarks>
/// DO NOT store/cache the returned delegate, as it keeps a strong reference to the target just like the original delegate.
/// </remarks>
public TDelegate? Delegate =>
_staticDelegate ??
// for instanced method delegate, only try to create if the instance reference is still alive
(Instance!.Target is { } t
? System.Delegate.CreateDelegate(typeof(TDelegate), t, Method) as TDelegate
: null);
}

internal class DelegateHelper
{
public static LiteralDelegate<TDelegate> CreateLiteral<TDelegate>(TDelegate d)
where TDelegate : Delegate
{
return new(d);
}

public static WeakDelegate<TDelegate> CreateWeak<TDelegate>(TDelegate d)
where TDelegate : Delegate
{
return new(d);
}
}
Copy link

Copilot AI Dec 19, 2025

Choose a reason for hiding this comment

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

The new WeakDelegate class lacks test coverage. Given that this is a critical component for preventing memory leaks and involves complex logic around weak references, delegate recreation, and handling both static and instance methods, consider adding unit tests to verify its behavior, especially edge cases like delegate recreation after garbage collection and proper handling of static vs instance delegates.

Copilot uses AI. Check for mistakes.
@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 189150 has failed on Uno.UI - CI.

Copilot AI review requested due to automatic review settings December 19, 2025 08:33
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 189168 has failed on Uno.UI - CI.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

@unodevops
Copy link
Contributor

⚠️⚠️ The build 189309 has failed on Uno.UI - docs.

@unodevops
Copy link
Contributor

⚠️⚠️ The build 189310 has failed on Uno.UI - CI.

@Xiaoy312 Xiaoy312 force-pushed the dev/xygu/20251216/hotreload-fwktemplate-leak branch from 4f3c464 to 87e15a2 Compare December 20, 2025 10:55
@Xiaoy312 Xiaoy312 added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 20, 2025
@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@Xiaoy312 Xiaoy312 force-pushed the dev/xygu/20251216/hotreload-fwktemplate-leak branch from 87e15a2 to b9b8204 Compare December 20, 2025 11:50
Copilot AI review requested due to automatic review settings December 20, 2025 11:50
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 189318 has failed on Uno.UI - CI.

@Xiaoy312 Xiaoy312 force-pushed the dev/xygu/20251216/hotreload-fwktemplate-leak branch from b9b8204 to 9d17969 Compare January 5, 2026 17:58
@Xiaoy312 Xiaoy312 removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 5, 2026
@Xiaoy312 Xiaoy312 requested a review from ebariche January 5, 2026 17:58
@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 189941 has failed on Uno.UI - CI.

@Xiaoy312
Copy link
Contributor Author

Xiaoy312 commented Jan 6, 2026

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 2 pipeline(s).

@unodevops
Copy link
Contributor

πŸ€– Your WebAssembly Skia Sample App stage site is ready! Visit it here: https://unowasmprstaging.z20.web.core.windows.net/pr-22161/wasm-skia-net9/index.html

@unodevops
Copy link
Contributor

πŸ€– Your Docs stage site is ready! Visit it here: https://unodocsprstaging.z13.web.core.windows.net/pr-22161/docs/index.html

@unodevops
Copy link
Contributor

⚠️⚠️ The build 190078 has failed on Uno.UI - CI.

@Xiaoy312 Xiaoy312 enabled auto-merge January 9, 2026 16:11
@Xiaoy312 Xiaoy312 requested a review from ajpinedam January 9, 2026 22:32
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.

4 participants