Browse Source

Don't set owner for shared value frames.

Should fix leak tests.
Steven Kirk 3 years ago
parent
commit
09d0992f74

+ 17 - 2
src/Avalonia.Base/PropertyStore/ValueFrame.cs

@@ -11,17 +11,26 @@ namespace Avalonia.PropertyStore
     {
         private readonly List<IValueEntry> _entries = new();
         private AvaloniaPropertyDictionary<IValueEntry> _index;
+        private ValueStore? _owner;
+        private bool _isShared;
 
         public int EntryCount => _entries.Count;
         public abstract bool IsActive { get; }
-        public ValueStore? Owner { get; private set; }
+        public ValueStore? Owner => !_isShared ? _owner : 
+            throw new AvaloniaInternalException("Cannot get owner for shared ValueFrame");
         public BindingPriority Priority { get; protected set; }
 
         public bool Contains(AvaloniaProperty property) => _index.ContainsKey(property);
 
         public IValueEntry GetEntry(int index) => _entries[index];
 
-        public void SetOwner(ValueStore? owner) => Owner = owner;
+        public void SetOwner(ValueStore? owner)
+        {
+            if (_owner is not null && owner is not null)
+                throw new AvaloniaInternalException("ValueFrame already has an owner.");
+            if (!_isShared)
+                _owner = owner;
+        }
 
         public bool TryGetEntry(AvaloniaProperty property, [NotNullWhen(true)] out IValueEntry? entry)
         {
@@ -40,6 +49,12 @@ namespace Avalonia.PropertyStore
                 _entries[i].Unsubscribe();
         }
 
+        protected void MakeShared()
+        {
+            _isShared = true;
+            _owner = null;
+        }
+
         protected void Add(IValueEntry value)
         {
             Debug.Assert(!value.Property.IsDirect);

+ 3 - 0
src/Avalonia.Base/Styling/StyleBase.cs

@@ -110,7 +110,10 @@ namespace Avalonia.Styling
                 }
 
                 if (canShareInstance)
+                {
+                    instance.MakeShared();
                     _sharedInstance = instance;
+                }
             }
 
             ao.GetValueStore().AddFrame(instance);

+ 2 - 0
src/Avalonia.Base/Styling/StyleInstance.cs

@@ -61,6 +61,8 @@ namespace Avalonia.Styling
             _activator?.Dispose();
         }
 
+        public new void MakeShared() => base.MakeShared();
+
         void IStyleActivatorSink.OnNext(bool value, int tag) => Owner?.OnFrameActivationChanged(this);
     }
 }