From bf5cb019f75a47dc625513dba3ada99f4c66097c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 20 Mar 2023 11:07:31 +0100 Subject: [PATCH] Move exit-early priority check. Priority may not be cleared to `UnsetValue` in the presence of `SetCurrentValue` so do the check upfront and compare against the priority of the next frame instead of `Unset`. --- src/Avalonia.Base/PropertyStore/ValueStore.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Base/PropertyStore/ValueStore.cs b/src/Avalonia.Base/PropertyStore/ValueStore.cs index 9fbe456ea1..af31459a98 100644 --- a/src/Avalonia.Base/PropertyStore/ValueStore.cs +++ b/src/Avalonia.Base/PropertyStore/ValueStore.cs @@ -797,6 +797,12 @@ namespace Avalonia.PropertyStore { var frame = _frames[i]; var priority = frame.Priority; + + // Exit early if the current EffectiveValue has higher priority than this frame. + if (current?.Priority < priority && current?.BasePriority < priority) + break; + + // Try to get an entry from the frame for the property we're reevaluating. var foundEntry = frame.TryGetEntryIfActive(property, out var entry, out var activeChanged); // If the active state of the frame has changed since the last read, and @@ -808,9 +814,13 @@ namespace Avalonia.PropertyStore return; } - var isRelevantPriority = HasHigherPriority(entry!, priority, current, changedValueEntry); - - if (foundEntry && isRelevantPriority && entry!.HasValue) + // If the frame has an entry for this property with a higher priority than the + // current effective value (and that entry has a value), then we have a new + // value for the property. Note that the check for entry.HasValue must be + // evaluated last as it can cause bindings to be subscribed. + if (foundEntry && + HasHigherPriority(entry!, priority, current, changedValueEntry) && + entry!.HasValue) { if (current is not null) { @@ -826,10 +836,6 @@ namespace Avalonia.PropertyStore if (generation != _frameGeneration) goto restart; - - if (current?.Priority < BindingPriority.Unset && - current?.BasePriority < BindingPriority.Unset) - break; } if (current?.Priority == BindingPriority.Unset)