From 370a04de90b8d33cb49674018a3a4ec814445659 Mon Sep 17 00:00:00 2001 From: Rebecca Muraira Date: Wed, 2 Oct 2019 12:09:32 -0700 Subject: [PATCH] [UWP] Fix circular reference in ImageOpened lambda for Auto sized image handling --- .../Renderer/lib/AdaptiveImageRenderer.cpp | 63 ++++++++++++++----- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp index da587e3452..c049a5edc2 100644 --- a/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp +++ b/source/uwp/Renderer/lib/AdaptiveImageRenderer.cpp @@ -697,17 +697,33 @@ namespace AdaptiveNamespace THROW_IF_FAILED(ellipseAsUIElement->put_Visibility(Visibility::Visibility_Collapsed)); // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent EventRegistrationToken eventToken; - ComPtr strongParentElement(parentElement); + ComPtr localParentElement(parentElement); + + // Take weak references to the ellipse and parent to avoid circular references between this lambda and + // its parents (Parent->Ellipse->ImageBrush->Lambda->(Parent and Ellipse)) + WeakRef weakParent; + THROW_IF_FAILED(localParentElement.AsWeak(&weakParent)); + + WeakRef weakEllipse; + THROW_IF_FAILED(ellipseAsUIElement.AsWeak(&weakEllipse)); THROW_IF_FAILED(brushAsImageBrush->add_ImageOpened( - Callback([ellipseAsUIElement, ellipseAsFrameworkElement, imageSourceAsBitmap, strongParentElement, isVisible]( + Callback([weakEllipse, imageSourceAsBitmap, weakParent, isVisible]( IInspectable* /*sender*/, IRoutedEventArgs * /*args*/) -> HRESULT { if (isVisible) { - RETURN_IF_FAILED(ellipseAsUIElement->put_Visibility(Visibility::Visibility_Visible)); - RETURN_IF_FAILED(XamlHelpers::SetAutoImageSize(ellipseAsFrameworkElement.Get(), - strongParentElement.Get(), - imageSourceAsBitmap.Get(), - isVisible)); + ComPtr lambdaEllipseAsFrameworkElement; + RETURN_IF_FAILED(weakEllipse.As(&lambdaEllipseAsFrameworkElement)); + + ComPtr lambdaParentElement; + RETURN_IF_FAILED(weakParent.As(&lambdaParentElement)); + + if (lambdaEllipseAsFrameworkElement && lambdaParentElement) + { + RETURN_IF_FAILED(XamlHelpers::SetAutoImageSize(lambdaEllipseAsFrameworkElement.Get(), + lambdaParentElement.Get(), + imageSourceAsBitmap.Get(), + isVisible)); + } } return S_OK; }).Get(), @@ -743,16 +759,33 @@ namespace AdaptiveNamespace THROW_IF_FAILED(imageAsUIElement->put_Visibility(Visibility::Visibility_Collapsed)); // Handle ImageOpened event so we can check the imageSource's size to determine if it fits in its parent - ComPtr strongParentElement(parentElement); + ComPtr localParentElement(parentElement); + + // Take weak references to the image and parent to avoid circular references between this lambda and + // its parents (Parent->Image->Lambda->(Parent and Image)) + WeakRef weakParent; + THROW_IF_FAILED(localParentElement.AsWeak(&weakParent)); + + WeakRef weakImage; + THROW_IF_FAILED(imageAsFrameworkElement.AsWeak(&weakImage)); EventRegistrationToken eventToken; THROW_IF_FAILED(xamlImage->add_ImageOpened( - Callback([imageAsFrameworkElement, strongParentElement, imageSourceAsBitmap, isVisible]( - IInspectable* /*sender*/, IRoutedEventArgs * - /*args*/) -> HRESULT { - return XamlHelpers::SetAutoImageSize(imageAsFrameworkElement.Get(), - strongParentElement.Get(), - imageSourceAsBitmap.Get(), - isVisible); + Callback([weakImage, weakParent, imageSourceAsBitmap, isVisible](IInspectable* /*sender*/, IRoutedEventArgs * + /*args*/) -> HRESULT { + ComPtr lambdaImageAsFrameworkElement; + RETURN_IF_FAILED(weakImage.As(&lambdaImageAsFrameworkElement)); + + ComPtr lambdaParentElement; + RETURN_IF_FAILED(weakParent.As(&lambdaParentElement)); + + if (lambdaImageAsFrameworkElement && lambdaParentElement) + { + RETURN_IF_FAILED(XamlHelpers::SetAutoImageSize(lambdaImageAsFrameworkElement.Get(), + lambdaParentElement.Get(), + imageSourceAsBitmap.Get(), + isVisible)); + } + return S_OK; }).Get(), &eventToken)); }