Browse Source

Removed memory leak

Krzysztof Krysiński 1 year ago
parent
commit
f81aa4557c

+ 1 - 4
src/PixiEditor.Extensions.WasmRuntime/WasmExtensionInstance.cs

@@ -23,8 +23,6 @@ public class WasmExtensionInstance : Extension
     private LayoutBuilder LayoutBuilder { get; }
     private WasmMemoryUtility WasmMemoryUtility { get; set; }
 
-    private Action<int, int> raiseElementEvent;
-
     public WasmExtensionInstance(Linker linker, Store store, Module module)
     {
         Linker = linker;
@@ -46,7 +44,6 @@ public class WasmExtensionInstance : Extension
 
     protected override void OnInitialized()
     {
-        raiseElementEvent = Instance.GetAction<int, int>("raise_element_event");
         Instance.GetAction("initialize").Invoke();
         base.OnInitialized();
     }
@@ -94,7 +91,7 @@ public class WasmExtensionInstance : Extension
             Span<byte> arr = memory.GetSpan<byte>(bodyOffset, bodyLength);
 
             var element = managedElements[controlId];
-            var body = LayoutBuilder.Deserialize(arr, DuplicateResolutionTactic.Replace);
+            var body = LayoutBuilder.Deserialize(arr, DuplicateResolutionTactic.ReplaceRemoveChildren);
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {

+ 1 - 1
src/PixiEditor.Extensions/LayoutBuilding/Elements/IChildrenDeserializable.cs

@@ -3,7 +3,7 @@ using PixiEditor.Extensions.CommonApi.LayoutBuilding;
 
 namespace PixiEditor.Extensions.LayoutBuilding.Elements;
 
-public interface IChildrenDeserializable
+public interface IChildrenDeserializable : IEnumerable<ILayoutElement<Control>>
 {
     public void DeserializeChildren(List<ILayoutElement<Control>> children);
 }

+ 20 - 2
src/PixiEditor.Extensions/LayoutBuilding/Elements/LayoutBuilder.cs

@@ -105,18 +105,36 @@ public class LayoutBuilder
             {
                 throw new DuplicateIdElementException(uniqueId);
             }
-            else if (duplicatedIdTactic == DuplicateResolutionTactic.Replace)
+
+            if (duplicatedIdTactic == DuplicateResolutionTactic.ReplaceRemoveChildren)
             {
+                if (managedElements[uniqueId] is IChildrenDeserializable childrenDeserializable)
+                {
+                    RemoveChildren(childrenDeserializable);
+                }
+
                 managedElements[uniqueId] = layoutElement;
             }
         }
 
         return layoutElement;
     }
+
+    private void RemoveChildren(IChildrenDeserializable childrenDeserializable)
+    {
+        foreach (var child in childrenDeserializable)
+        {
+            managedElements.Remove(child.UniqueId);
+            if (child is IChildrenDeserializable childChildrenDeserializable)
+            {
+                RemoveChildren(childChildrenDeserializable);
+            }
+        }
+    }
 }
 
 public enum DuplicateResolutionTactic
 {
     ThrowException,
-    Replace,
+    ReplaceRemoveChildren,
 }

+ 15 - 1
src/PixiEditor.Extensions/LayoutBuilding/Elements/SingleChildLayoutElement.cs

@@ -1,4 +1,5 @@
-using Avalonia.Controls;
+using System.Collections;
+using Avalonia.Controls;
 using PixiEditor.Extensions.CommonApi.LayoutBuilding;
 
 namespace PixiEditor.Extensions.LayoutBuilding.Elements;
@@ -12,4 +13,17 @@ public abstract class SingleChildLayoutElement : LayoutElement, ISingleChildLayo
     {
         Child = children.FirstOrDefault();
     }
+
+    public IEnumerator<ILayoutElement<Control>> GetEnumerator()
+    {
+        if (Child != null)
+        {
+            yield return Child;
+        }
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
 }

+ 12 - 1
src/PixiEditor.Extensions/LayoutBuilding/Elements/StatefulContainer.cs

@@ -1,4 +1,5 @@
-using Avalonia.Controls;
+using System.Collections;
+using Avalonia.Controls;
 using PixiEditor.Extensions.CommonApi.LayoutBuilding;
 
 namespace PixiEditor.Extensions.LayoutBuilding.Elements;
@@ -14,4 +15,14 @@ public class StatefulContainer : StatefulElement<ContainerState>, IChildrenDeser
     {
         State.Content = children.FirstOrDefault();
     }
+
+    public IEnumerator<ILayoutElement<Control>> GetEnumerator()
+    {
+        yield return State.Content;
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
 }