Skip to content

Commit

Permalink
adds tests for CodeInstruction.CallClosure
Browse files Browse the repository at this point in the history
  • Loading branch information
pardeike committed Dec 29, 2024
1 parent 22959ce commit c26e8f0
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 5 deletions.
9 changes: 4 additions & 5 deletions Harmony/Public/CodeInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public class CodeInstruction
{
internal static class State
{
internal static readonly Dictionary<int, Delegate> closureCache = [];
internal static readonly List<Delegate> closureCache = [];
}

/// <summary>The opcode</summary>
Expand Down Expand Up @@ -166,11 +166,10 @@ public static CodeInstruction CallClosure<T>(T closure) where T : Delegate
var preserveContext = closure.Target != null && targetType.GetFields().Any(x => !x.IsStatic);
if (preserveContext)
{
var n = State.closureCache.Count;
State.closureCache[n] = closure;
State.closureCache.Add(closure);
il.Emit(OpCodes.Ldsfld, AccessTools.Field(typeof(State), nameof(State.closureCache)));
il.Emit(OpCodes.Ldc_I4, n);
il.Emit(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(Dictionary<int, Delegate>), "Item"));
il.Emit(OpCodes.Ldc_I4, State.closureCache.Count - 1);
il.Emit(OpCodes.Callvirt, AccessTools.PropertyGetter(typeof(List<Delegate>), "Item"));
}
else
{
Expand Down
9 changes: 9 additions & 0 deletions HarmonyTests/Patching/Assets/Specials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -397,4 +397,13 @@ static void Prefix()
{
}
}

public class ClassTestingCallClosure
{
public string field1 = "";
public string field2 = "";

public CodeInstruction WIthoutContext() => CodeInstruction.CallClosure<Func<string, string>>(input => { return $"[{input}]"; });
public CodeInstruction WithContext() => CodeInstruction.CallClosure(() => { field2 = field1; });
}
}
33 changes: 33 additions & 0 deletions HarmonyTests/Patching/Specials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
using System;
#if NET6_0_OR_GREATER
using System.Net.Http;
using System.Reflection.Emit;
#else
using System.Net;
using System.Reflection.Emit;
#endif

namespace HarmonyLibTests.Patching
Expand Down Expand Up @@ -470,5 +472,36 @@ public void Test_MarshalledWithEventHandler2()
new MarshalledWithEventHandlerTest2Class().Run();
Console.WriteLine($"### MarshalledWithEventHandlerTest2 AFTER");
}

[Test]
public void Test_CallClosure()
{
CodeInstruction.State.closureCache.Clear();
var instance = new ClassTestingCallClosure
{
field1 = "test",
field2 = "tobereplaced"
};

var code1 = instance.WIthoutContext();
var action1 = code1.operand as DynamicMethod;
Assert.NotNull(action1);
var result = action1.Invoke(null, ["TEST"]);
Assert.AreEqual(result, "[TEST]");
Assert.AreEqual(CodeInstruction.State.closureCache.Count, 0);

var code2 = instance.WithContext();
Assert.AreEqual(instance.field1, "test");
Assert.AreEqual(instance.field2, "tobereplaced");
var action2 = code2.operand as DynamicMethod;
Assert.NotNull(action2);
_ = action2.Invoke(null, []);
Assert.AreEqual(instance.field1, "test");
Assert.AreEqual(instance.field2, "test");
Assert.AreEqual(CodeInstruction.State.closureCache.Count, 1);

_ = instance.WithContext();
Assert.AreEqual(CodeInstruction.State.closureCache.Count, 2);
}
}
}

0 comments on commit c26e8f0

Please sign in to comment.