XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using Mono.Cecil;
using Mono.Cecil.Cil;
using XFESystem.Collections;

namespace XFESystem.Tools.JintCleanupPatch;

public static partial class Program
{
    private const string RegexSchedulingMarker = "XFESystem.JintRegexSchedulingV1";
    private static void PatchRegexScheduling(ModuleDefinition module)
    {
        if (module.GetType(RegexSchedulingMarker) is not null) { ValidateRegexScheduling(module); return; }
        var type = module.GetType("Jint.Native.RegExp.RegExpPrototype"); int count = 0;
        foreach (var method in type.Methods.Where(method => method.HasBody))
            foreach (var instruction in method.Body.Instructions)
                if (instruction.Operand is MethodReference call && call.DeclaringType.FullName == "System.Text.RegularExpressions.Regex" && call.Name is "Match" or "IsMatch")
                {
                    var parameterTypes = new[] { typeof(System.Text.RegularExpressions.Regex) }.Concat(call.Parameters.Select(p => p.ParameterType.FullName switch
                    { "System.String" => typeof(string), "System.Int32" => typeof(int), _ => throw new InvalidOperationException("Pinned regex match overload changed.") })).ToArray();
                    var replacement = typeof(RegexPauseRecovery).GetMethod(call.Name, parameterTypes) ?? throw new InvalidOperationException("Pinned regex match recovery overload is missing.");
                    instruction.OpCode = OpCodes.Call; instruction.Operand = module.ImportReference(replacement); count++;
                }
        if (count != 6) throw new InvalidOperationException("Pinned regex match scheduling call count changed: " + count);
        module.Types.Add(new("XFESystem", "JintRegexSchedulingV1", TypeAttributes.NotPublic | TypeAttributes.Abstract | TypeAttributes.Sealed, module.TypeSystem.Object));
        ValidateRegexScheduling(module);
    }
    private static void ValidateRegexScheduling(ModuleDefinition module)
    {
        var calls = module.GetType("Jint.Native.RegExp.RegExpPrototype").Methods.Where(m => m.HasBody).SelectMany(m => m.Body.Instructions).ToArray();
        if (module.GetType(RegexSchedulingMarker) is null || calls.Count(i => i.OpCode == OpCodes.Call && i.Operand is MethodReference call && call.DeclaringType.FullName == typeof(RegexPauseRecovery).FullName) != 6 ||
            calls.Any(i => i.Operand is MethodReference call && call.DeclaringType.FullName == "System.Text.RegularExpressions.Regex" && call.Name is "Match" or "IsMatch"))
            throw new InvalidOperationException("The regex scheduling patch is incomplete.");
    }
}