Browse Source

Merge pull request #1214 from jkoritzinsky/FixBindingStackOverflow

Fix binding stack overflow for negation
pull/1225/head
danwalmsley 9 years ago
committed by GitHub
parent
commit
57400f9a91
  1. 16
      build/XUnit.props
  2. 19
      src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs
  3. 11
      src/Markup/Avalonia.Markup/Data/ITransformNode.cs
  4. 13
      src/Markup/Avalonia.Markup/Data/LogicalNotNode.cs
  5. 20
      tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Negation.cs

16
build/XUnit.props

@ -1,14 +1,14 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="xunit" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit" Version="2.3.0" />
<PackageReference Include="xunit.abstractions" Version="2.0.1" /> <PackageReference Include="xunit.abstractions" Version="2.0.1" />
<PackageReference Include="xunit.assert" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit.assert" Version="2.3.0" />
<PackageReference Include="xunit.core" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit.core" Version="2.3.0" />
<PackageReference Include="xunit.extensibility.core" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit.extensibility.core" Version="2.3.0" />
<PackageReference Include="xunit.extensibility.execution" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit.extensibility.execution" Version="2.3.0" />
<PackageReference Include="xunit.runner.console" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit.runner.console" Version="2.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta5-build3769" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.3.0" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0-beta5-build3769" /> <DotNetCliToolReference Include="dotnet-xunit" Version="2.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'"> <ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp2.0'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />

19
src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs

@ -154,7 +154,24 @@ namespace Avalonia.Markup.Data
/// </returns> /// </returns>
public bool SetValue(object value, BindingPriority priority = BindingPriority.LocalValue) public bool SetValue(object value, BindingPriority priority = BindingPriority.LocalValue)
{ {
return (Leaf as ISettableNode)?.SetTargetValue(value, priority) ?? false; if (Leaf is ISettableNode settable)
{
var node = _node;
while (node != null)
{
if (node is ITransformNode transform)
{
value = transform.Transform(value);
if (value is BindingNotification)
{
return false;
}
}
node = node.Next;
}
return settable.SetTargetValue(value, priority);
}
return false;
} }
/// <summary> /// <summary>

11
src/Markup/Avalonia.Markup/Data/ITransformNode.cs

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Markup.Data
{
interface ITransformNode
{
object Transform(object value);
}
}

13
src/Markup/Avalonia.Markup/Data/LogicalNotNode.cs

@ -7,7 +7,7 @@ using Avalonia.Data;
namespace Avalonia.Markup.Data namespace Avalonia.Markup.Data
{ {
internal class LogicalNotNode : ExpressionNode internal class LogicalNotNode : ExpressionNode, ITransformNode
{ {
public override string Description => "!"; public override string Description => "!";
@ -61,5 +61,16 @@ namespace Avalonia.Markup.Data
return AvaloniaProperty.UnsetValue; return AvaloniaProperty.UnsetValue;
} }
public object Transform(object value)
{
var originalType = value.GetType();
var negated = Negate(value);
if (negated is BindingNotification)
{
return negated;
}
return Convert.ChangeType(negated, originalType);
}
} }
} }

20
tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Negation.cs

@ -105,14 +105,32 @@ namespace Avalonia.Markup.UnitTests.Data
} }
[Fact] [Fact]
public void SetValue_Should_Return_False() public void SetValue_Should_Return_False_For_Invalid_Value()
{ {
var data = new { Foo = "foo" }; var data = new { Foo = "foo" };
var target = new ExpressionObserver(data, "!Foo"); var target = new ExpressionObserver(data, "!Foo");
target.Subscribe(_ => { });
Assert.False(target.SetValue("bar")); Assert.False(target.SetValue("bar"));
GC.KeepAlive(data); GC.KeepAlive(data);
} }
[Fact]
public void Can_SetValue_For_Valid_Value()
{
var data = new Test { Foo = true };
var target = new ExpressionObserver(data, "!Foo");
target.Subscribe(_ => { });
Assert.True(target.SetValue(true));
Assert.False(data.Foo);
}
private class Test
{
public bool Foo { get; set; }
}
} }
} }

Loading…
Cancel
Save