using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Xml; using Microsoft.Iris.Debug; using Microsoft.Iris.Debug.Data; using Microsoft.Iris.Library; using Microsoft.Iris.Markup.UIX; using Microsoft.Iris.Session; namespace Microsoft.Iris.Markup { // Token: 0x0200018B RID: 395 internal class Interpreter { // Token: 0x06000F21 RID: 3873 RVA: 0x00029E78 File Offset: 0x00028E78 public static object Run(InterpreterContext context) { object result = null; ByteCodeReader byteCodeReader = null; long num = -1L; bool isErrored = true; ErrorManager.EnterContext(context); try { byteCodeReader = context.LoadResult.ObjectSection; num = (long)(ulong)byteCodeReader.CurrentOffset; byteCodeReader.CurrentOffset = context.InitialBytecodeOffset; if (Application.DebugSettings.UseDecompiler) result = RunDecompile(context, byteCodeReader); else result = Run(context, byteCodeReader); isErrored = false; } finally { if (isErrored) ExceptionContext = context.ToString(); ErrorManager.ExitContext(); if (byteCodeReader != null && num != -1L) byteCodeReader.CurrentOffset = (uint)num; } return result; } // Token: 0x06000F22 RID: 3874 RVA: 0x00029EF8 File Offset: 0x00028EF8 private static object Run(InterpreterContext context, ByteCodeReader reader) { MarkupLoadResult loadResult = context.LoadResult; IMarkupTypeBase instance = context.Instance; MarkupImportTables importTables = loadResult.ImportTables; MarkupConstantsTable constantsTable = loadResult.ConstantsTable; SymbolReference[] symbolReferenceTable = context.MarkupType.SymbolReferenceTable; ErrorWatermark watermark = ErrorManager.Watermark; Trace.IsCategoryEnabled(TraceCategory.Markup); Stack stack = _stack; int count = stack.Count; if (instance != null) { stack.Push(instance); } bool errorsDetected = false; object result = null; bool wasInDebugState = false; bool debugging = Application.Debugger != null; context.LoadResult.LineNumberTable.DumpTable(); void OnDecode(InterpreterEntry entry) { if (!debugging) return; Application.Debugger.LogInterpreterDecode(context, entry.Instruction); // Fetch line and column numbers from the table int line = -1, column = -1; context.LoadResult.LineNumberTable.TryLookup(entry.Instruction.Offset, out line, out column); bool ShouldBreak(Breakpoint b) => b.Enabled && b.Equals(loadResult.Uri, line, column, entry.Instruction.Offset); // Check if a breakpoint has been set at this location bool shouldBreakHere = Application.DebugSettings.Breakpoints.Any(ShouldBreak); if (shouldBreakHere) Application.Debugger.DebuggerCommand = InterpreterCommand.Break; // Stop execution while the debugger is in break mode while (Application.Debugger.DebuggerCommand == InterpreterCommand.Break) ; // If the debugger requested a single step, immediately set the debugger // to break again for the next instruction if (Application.Debugger.DebuggerCommand == InterpreterCommand.Step) Application.Debugger.DebuggerCommand = InterpreterCommand.Break; } while (!errorsDetected) { OpCode opCode = (OpCode)reader.ReadByte(); InterpreterEntry entry = new(new(opCode, reader.CurrentOffset, loadResult.Uri)); switch (opCode) { case OpCode.ConstructObject: { int typeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(typeIndex); OnDecode(entry); TypeSchema typeSchema = importTables.TypeImports[typeIndex]; entry.Parameters.Add(new InterpreterObject("type", typeof(TypeSchema), typeSchema, InstructionObjectSource.TypeImports, typeIndex)); object newObj = typeSchema.ConstructDefault(); ReportErrorOnNull(newObj, "Construction", typeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { RegisterDisposable(newObj, typeSchema, instance); stack.Push(newObj); entry.ReturnValues.Add(new(newObj)); } break; } case OpCode.ConstructObjectIndirect: { int assignmentTypeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(assignmentTypeIndex); OnDecode(entry); TypeSchema assignmentTypeSchema = importTables.TypeImports[assignmentTypeIndex]; entry.Parameters.Add(new("assignmentType", typeof(TypeSchema), assignmentTypeSchema, InstructionObjectSource.TypeImports, assignmentTypeIndex)); TypeSchema targetTypeSchema = (TypeSchema)stack.Pop(); entry.Parameters.Add(new("targetType", typeof(TypeSchema), targetTypeSchema, InstructionObjectSource.Stack)); if (!assignmentTypeSchema.IsAssignableFrom(targetTypeSchema)) { ErrorManager.ReportError("Script runtime failure: Dynamic construction type override failed. Attempting to construct '{0}' in place of '{1}'", (targetTypeSchema != null) ? targetTypeSchema.Name : "null", assignmentTypeSchema.Name); if (ErrorsDetected(watermark, ref result, ref errorsDetected)) break; } object newObj = targetTypeSchema is IDynamicConstructionSchema dynamicConstructionSchema ? dynamicConstructionSchema.ConstructDefault(assignmentTypeSchema) : targetTypeSchema.ConstructDefault(); ReportErrorOnNull(newObj, "Construction", targetTypeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { RegisterDisposable(newObj, targetTypeSchema, instance); stack.Push(newObj); entry.ReturnValues.Add(new(newObj)); } break; } case OpCode.ConstructObjectParam: { int targetTypeIndex = reader.ReadUInt16(); int constructorIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(targetTypeIndex); entry.Instruction.Operands.Add(constructorIndex); OnDecode(entry); TypeSchema targetTypeSchema = importTables.TypeImports[targetTypeIndex]; ConstructorSchema constructorSchema = importTables.ConstructorImports[constructorIndex]; int parameterCount = constructorSchema.ParameterTypes.Length; object[] array = ParameterListAllocator.Alloc(parameterCount); for (parameterCount--; parameterCount >= 0; parameterCount--) array[parameterCount] = stack.Pop(); entry.Parameters.Add(new("ctorParams", typeof(object[]), array, InstructionObjectSource.Stack)); object newObj = constructorSchema.Construct(array); ReportErrorOnNull(newObj, "Construction", targetTypeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { RegisterDisposable(newObj, targetTypeSchema, instance); stack.Push(newObj); entry.ReturnValues.Add(new(newObj)); ParameterListAllocator.Free(array); } break; } case OpCode.ConstructFromString: { int typeIndex = reader.ReadUInt16(); int stringIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(typeIndex); entry.Instruction.Operands.Add(stringIndex); OnDecode(entry); TypeSchema typeSchema = importTables.TypeImports[typeIndex]; entry.Parameters.Add(new("type", typeof(TypeSchema), typeSchema, InstructionObjectSource.TypeImports, typeIndex)); string fromString = (string)constantsTable.Get(stringIndex); entry.Parameters.Add(new("fromString", typeof(string), fromString, InstructionObjectSource.Constants, stringIndex)); typeSchema.TypeConverter(fromString, StringSchema.Type, out object newObj); ReportErrorOnNull(newObj, "Construction", typeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { RegisterDisposable(newObj, typeSchema, instance); stack.Push(newObj); entry.ReturnValues.Add(new(newObj)); } break; } case OpCode.ConstructFromBinary: { int typeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(typeIndex); OnDecode(entry); TypeSchema typeSchema = importTables.TypeImports[typeIndex]; entry.Parameters.Add(new("type", typeof(TypeSchema), typeSchema, InstructionObjectSource.TypeImports, typeIndex)); uint blobStart = reader.CurrentOffset; object newObj = typeSchema.DecodeBinary(reader); if (debugging) { // Potentially expensive operation, only do this if a debugger is attached uint blobEnd = reader.CurrentOffset; uint blobLength = blobEnd - blobStart; byte[] blob = new byte[blobLength]; reader.CurrentOffset = blobStart; while (reader.CurrentOffset < blobEnd) blob[reader.CurrentOffset - blobStart] = reader.ReadByte(); entry.Parameters.Add(new("blob", typeof(byte[]), blob, InstructionObjectSource.Inline, 0)); } ReportErrorOnNull(newObj, "Construction", typeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { RegisterDisposable(newObj, typeSchema, instance); stack.Push(newObj); entry.ReturnValues.Add(new(newObj)); } break; } case OpCode.InitializeInstance: { int typeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(typeIndex); OnDecode(entry); TypeSchema typeSchema = importTables.TypeImports[typeIndex]; entry.Parameters.Add(new("type", typeof(TypeSchema), typeSchema, InstructionObjectSource.TypeImports, typeIndex)); object objToInit = stack.Pop(); entry.Parameters.Add(new("objToInit", typeof(object), objToInit, InstructionObjectSource.Stack)); typeSchema.InitializeInstance(ref objToInit); ReportErrorOnNull(objToInit, "Initialize", typeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { stack.Push(objToInit); entry.ReturnValues.Add(new(objToInit)); } break; } case OpCode.InitializeInstanceIndirect: { OnDecode(entry); TypeSchema typeSchema = (TypeSchema)stack.Pop(); entry.Parameters.Add(new("type", typeof(TypeSchema), typeSchema, InstructionObjectSource.Stack)); object objToInit = stack.Pop(); entry.Parameters.Add(new("objToInit", typeof(object), objToInit, InstructionObjectSource.Stack)); typeSchema.InitializeInstance(ref objToInit); ReportErrorOnNull(objToInit, "Initialize", typeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { stack.Push(objToInit); entry.ReturnValues.Add(new(objToInit)); } break; } case OpCode.LookupSymbol: { int symbolRefIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(symbolRefIndex); OnDecode(entry); SymbolReference symbolRef = symbolReferenceTable[symbolRefIndex]; entry.Parameters.Add(new("symbolRef", typeof(SymbolReference), symbolRef, InstructionObjectSource.SymbolReference, symbolRefIndex)); object symbol = context.ReadSymbol(symbolRef); stack.Push(symbol); entry.ReturnValues.Add(new(symbol)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.WriteSymbol: case OpCode.WriteSymbolPeek: { int symbolRefIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(symbolRefIndex); OnDecode(entry); object symbol = (opCode == OpCode.WriteSymbolPeek) ? stack.Peek() : stack.Pop(); entry.Parameters.Add(new("symbol", typeof(object), symbol, InstructionObjectSource.Stack)); SymbolReference symbolRef = symbolReferenceTable[symbolRefIndex]; entry.Parameters.Add(new("symbolRef", typeof(SymbolReference), symbolRef, InstructionObjectSource.SymbolReference, symbolRefIndex)); context.WriteSymbol(symbolRef, symbol); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.ClearSymbol: { int symbolRefIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(symbolRefIndex); OnDecode(entry); SymbolReference symbolRef = symbolReferenceTable[symbolRefIndex]; entry.Parameters.Add(new("symbolRef", typeof(SymbolReference), symbolRef, InstructionObjectSource.SymbolReference, symbolRefIndex)); context.ClearSymbol(symbolRef); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.PropertyInitialize: case OpCode.PropertyInitializeIndirect: { int propertyIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(propertyIndex); OnDecode(entry); bool isIndirect = opCode == OpCode.PropertyInitializeIndirect; TypeSchema parentTypeSchema = null; if (isIndirect) { parentTypeSchema = (TypeSchema)stack.Pop(); entry.Parameters.Add(new("parentType", typeof(TypeSchema), parentTypeSchema, InstructionObjectSource.Stack)); } PropertySchema propertySchema = importTables.PropertyImports[propertyIndex]; entry.Parameters.Add(new("property", typeof(PropertySchema), propertySchema, InstructionObjectSource.PropertyImports, propertyIndex)); object propertyValue = stack.Pop(); entry.Parameters.Add(new("value", typeof(object), propertyValue, InstructionObjectSource.Stack)); object parentObj = stack.Pop(); entry.Parameters.Add(new("parent", typeof(object), parentObj, InstructionObjectSource.Stack)); ReportErrorOnNull(parentObj, "Property Set", propertySchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { if (isIndirect) { PropertySchema inheritedPropertySchema = parentTypeSchema.FindPropertyDeep(propertySchema.Name); if (inheritedPropertySchema != propertySchema) { TypeSchema propertyType = inheritedPropertySchema.PropertyType; if (!propertyType.IsAssignableFrom(propertyValue)) { string param = TypeSchema.NameFromInstance(propertyValue); ErrorManager.ReportError("Script runtime failure: Incompatible value for property '{0}' supplied (expecting values of type '{1}' but got '{2}') while constructing runtime replacement type '{3}' (original type '{4}')", propertySchema.Name, propertyType.Name, param, parentTypeSchema.Name, propertySchema.Owner.Name); result = ScriptError; } if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { break; } } } propertySchema.SetValue(ref parentObj, propertyValue); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { stack.Push(parentObj); entry.ReturnValues.Add(new(parentObj)); } } break; } case OpCode.PropertyListAdd: { int propertyIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(propertyIndex); OnDecode(entry); object objToAdd = stack.Pop(); entry.Parameters.Add(new("objToAdd", typeof(object), objToAdd, InstructionObjectSource.Stack)); object collection = GetCollection(stack.Peek(), importTables, propertyIndex, out var propertySchema); entry.Parameters.Add(new("collection", typeof(IList), collection, InstructionObjectSource.Dynamic)); if (propertySchema != null) entry.Parameters.Add(new("collectionProperty", typeof(PropertySchema), propertySchema, InstructionObjectSource.TypeImports, propertyIndex)); ReportErrorOnNull(collection, "List Add"); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { ((IList)collection).Add(objToAdd); if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { } } break; } case OpCode.PropertyDictionaryAdd: { int propertyIndex = reader.ReadUInt16(); int keyIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(propertyIndex); entry.Instruction.Operands.Add(keyIndex); OnDecode(entry); string key = (string)constantsTable.Get(keyIndex); entry.Parameters.Add(new("key", typeof(string), key, InstructionObjectSource.Constants, keyIndex)); object objToAdd = stack.Pop(); entry.Parameters.Add(new("objToAdd", typeof(object), objToAdd, InstructionObjectSource.Stack)); object dictionary = GetCollection(stack.Peek(), importTables, propertyIndex, out var propertySchema); entry.Parameters.Add(new("dictionary", typeof(IDictionary), dictionary, InstructionObjectSource.Dynamic)); if (propertySchema != null) entry.Parameters.Add(new("dictionaryProperty", typeof(PropertySchema), propertySchema, InstructionObjectSource.TypeImports, propertyIndex)); ReportErrorOnNull(dictionary, "Dictionary Add"); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { ((IDictionary)dictionary)[key] = objToAdd; if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { } } break; } case OpCode.PropertyAssign: case OpCode.PropertyAssignStatic: { int propertyIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(propertyIndex); OnDecode(entry); PropertySchema propertySchema = importTables.PropertyImports[propertyIndex]; entry.Parameters.Add(new("property", typeof(PropertySchema), propertySchema, InstructionObjectSource.PropertyImports, propertyIndex)); object parentObj = null; if (opCode == OpCode.PropertyAssign) { parentObj = stack.Pop(); entry.Parameters.Add(new("parent", typeof(object), parentObj, InstructionObjectSource.Stack)); ReportErrorOnNullOrDisposed(parentObj, "Property Set", propertySchema.Name, propertySchema.Owner); if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { break; } } object propertyValue = stack.Peek(); entry.Parameters.Add(new("value", typeof(object), propertyValue, InstructionObjectSource.Stack, 1)); propertySchema.SetValue(ref parentObj, propertyValue); if (!ErrorsDetected(watermark, ref result, ref errorsDetected) && Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.PropertyGet: case OpCode.PropertyGetPeek: case OpCode.PropertyGetStatic: { int propertyIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(propertyIndex); OnDecode(entry); PropertySchema propertySchema = importTables.PropertyImports[propertyIndex]; entry.Parameters.Add(new("property", typeof(PropertySchema), propertySchema, InstructionObjectSource.PropertyImports, propertyIndex)); object parentObj = null; if (opCode != OpCode.PropertyGetStatic) { parentObj = opCode == OpCode.PropertyGet ? stack.Pop() : stack.Peek(); entry.Parameters.Add(new("parent", typeof(object), parentObj, InstructionObjectSource.Stack)); ReportErrorOnNullOrDisposed(parentObj, "Property Get", propertySchema.Name, propertySchema.Owner); if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { break; } } object propertyValue = propertySchema.GetValue(parentObj); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { stack.Push(propertyValue); entry.ReturnValues.Add(new(propertyValue)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.MethodInvoke: case OpCode.MethodInvokePeek: case OpCode.MethodInvokeStatic: case OpCode.MethodInvokePushLastParam: case OpCode.MethodInvokeStaticPushLastParam: { int methodIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(methodIndex); OnDecode(entry); MethodSchema methodSchema = importTables.MethodImports[methodIndex]; int parameterCount = methodSchema.ParameterTypes.Length; object[] parameters = ParameterListAllocator.Alloc(parameterCount); for (parameterCount--; parameterCount >= 0; parameterCount--) parameters[parameterCount] = stack.Pop(); entry.Parameters.Add(new("parameters", typeof(object[]), parameters, InstructionObjectSource.Stack)); object parentObj = null; bool isStatic = opCode == OpCode.MethodInvokeStatic || opCode == OpCode.MethodInvokeStaticPushLastParam; bool peek = opCode == OpCode.MethodInvokePeek; bool pushLastParam = opCode == OpCode.MethodInvokePushLastParam || opCode == OpCode.MethodInvokeStaticPushLastParam; if (!isStatic) { parentObj = !peek ? stack.Pop() : stack.Peek(); entry.Parameters.Add(new("parent", typeof(object), parentObj, InstructionObjectSource.Stack)); ReportErrorOnNullOrDisposed(parentObj, "Method Invoke", methodSchema.Name, methodSchema.Owner); if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { break; } } object methodResult = methodSchema.Invoke(parentObj, parameters); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { if (!pushLastParam) { if (methodSchema.ReturnType != VoidSchema.Type) { stack.Push(methodResult); entry.ReturnValues.Add(new(methodResult)); } } else { stack.Push(parameters[parameters.Length - 1]); } ParameterListAllocator.Free(parameters); } break; } case OpCode.VerifyTypeCast: { int typeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(typeIndex); OnDecode(entry); TypeSchema typeSchema = importTables.TypeImports[typeIndex]; entry.Parameters.Add(new("type", typeof(TypeSchema), typeSchema, InstructionObjectSource.TypeImports, typeIndex)); object objToCheck = stack.Peek(); entry.Parameters.Add(new("objToCheck", typeof(object), objToCheck, InstructionObjectSource.Stack, 1)); if (objToCheck != null) { if (!typeSchema.IsAssignableFrom(objToCheck)) { string runtimeTypeName = TypeSchema.NameFromInstance(objToCheck); string name = typeSchema.Name; ErrorManager.ReportError("Script runtime failure: Invalid type cast while attempting to cast an instance with a runtime type of '{0}' to '{1}'", runtimeTypeName, name); result = ScriptError; } if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { } } else if (!typeSchema.IsNullAssignable) { ReportErrorOnNull(objToCheck, "Verify Type Cast", typeSchema.Name); if (ErrorsDetected(watermark, ref result, ref errorsDetected)) { } } break; } case OpCode.ConvertType: { int toTypeIndex = reader.ReadUInt16(); int fromTypeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(toTypeIndex); entry.Instruction.Operands.Add(fromTypeIndex); OnDecode(entry); TypeSchema toTypeSchema = importTables.TypeImports[toTypeIndex]; entry.Parameters.Add(new("toType", typeof(TypeSchema), toTypeSchema, InstructionObjectSource.TypeImports, toTypeIndex)); TypeSchema fromTypeSchema = importTables.TypeImports[fromTypeIndex]; entry.Parameters.Add(new("fromType", typeof(TypeSchema), fromTypeSchema, InstructionObjectSource.TypeImports, fromTypeIndex)); object objToConvert = stack.Pop(); entry.Parameters.Add(new("objToConvert", typeof(object), objToConvert, InstructionObjectSource.Stack)); ReportErrorOnNull(objToConvert, "Type Conversion", toTypeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { Result castResult = toTypeSchema.TypeConverter(objToConvert, fromTypeSchema, out object obj14); if (castResult.Failed) ErrorManager.ReportError("Script runtime failure: Type conversion failed while attempting to convert to '{0}' ({1})", toTypeSchema.Name, castResult.Error); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { stack.Push(obj14); entry.ReturnValues.Add(new(obj14)); } } break; } case OpCode.Operation: { int opHostIndex = reader.ReadUInt16(); OperationType op = (OperationType)reader.ReadByte(); entry.Instruction.Operands.Add(opHostIndex); entry.Instruction.Operands.Add(op); OnDecode(entry); TypeSchema opHost = importTables.TypeImports[opHostIndex]; entry.Parameters.Add(new("opHost", typeof(TypeSchema), opHost, InstructionObjectSource.TypeImports, opHostIndex)); entry.Parameters.Add(new("op", typeof(OperationType), op, InstructionObjectSource.Inline)); object right = null; if (!TypeSchema.IsUnaryOperation(op)) { right = stack.Pop(); entry.Parameters.Add(new("right", typeof(object), right, InstructionObjectSource.Stack)); } object left = stack.Pop(); entry.Parameters.Add(new("left", typeof(object), left, InstructionObjectSource.Stack)); object opResult = opHost.PerformOperationDeep(left, right, op); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { stack.Push(opResult); entry.ReturnValues.Add(new(opResult)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.IsCheck: { int targetTypeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(targetTypeIndex); OnDecode(entry); TypeSchema targetTypeSchema = importTables.TypeImports[targetTypeIndex]; entry.Parameters.Add(new("targetType", typeof(TypeSchema), targetTypeSchema, InstructionObjectSource.TypeImports, targetTypeIndex)); object objToCheck = stack.Pop(); entry.Parameters.Add(new("objToCheck", typeof(object), objToCheck, InstructionObjectSource.Stack)); bool checkResult = false; if (objToCheck != null) checkResult = targetTypeSchema.IsAssignableFrom(objToCheck); stack.Push(BooleanBoxes.Box(checkResult)); entry.ReturnValues.Add(new(checkResult)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.As: { int targetTypeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(targetTypeIndex); OnDecode(entry); TypeSchema targetTypeSchema = importTables.TypeImports[targetTypeIndex]; entry.Parameters.Add(new("targetType", typeof(TypeSchema), targetTypeSchema, InstructionObjectSource.TypeImports, targetTypeIndex)); object objToCheck = stack.Peek(); entry.Parameters.Add(new("objToCheck", typeof(object), objToCheck, InstructionObjectSource.Stack, 1)); if (objToCheck != null && !targetTypeSchema.IsAssignableFrom(objToCheck)) { stack.Pop(); stack.Push(null); } else if (debugging) { // The opcode isn't implemented like this, // but technically As returns a value. entry.ReturnValues.Add(new(objToCheck)); } if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.TypeOf: { int typeIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(typeIndex); OnDecode(entry); entry.Parameters.Add(new("typeIndex", typeof(ushort), typeIndex, InstructionObjectSource.Inline)); TypeSchema typeSchema = importTables.TypeImports[typeIndex]; stack.Push(typeSchema); entry.ReturnValues.Add(new(typeSchema)); break; } case OpCode.PushNull: OnDecode(entry); stack.Push(null); entry.ReturnValues.Add(new(null)); break; case OpCode.PushConstant: { int constantIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(constantIndex); OnDecode(entry); entry.Parameters.Add(new("constantIndex", typeof(ushort), constantIndex, InstructionObjectSource.Inline)); object constant = constantsTable.Get(constantIndex); stack.Push(constant); entry.ReturnValues.Add(new(constant)); break; } case OpCode.PushThis: OnDecode(entry); stack.Push(instance); entry.ReturnValues.Add(new(instance)); break; case OpCode.DiscardValue: OnDecode(entry); stack.Pop(); break; case OpCode.ReturnValue: { OnDecode(entry); object thisResult = stack.Pop(); entry.ReturnValues.Add(new(thisResult)); result = thisResult; errorsDetected = true; break; } case OpCode.ReturnVoid: OnDecode(entry); result = VoidReturnValue; errorsDetected = true; break; case OpCode.JumpIfFalse: case OpCode.JumpIfFalsePeek: case OpCode.JumpIfTruePeek: { uint jumpTo = reader.ReadUInt32(); entry.Instruction.Operands.Add(jumpTo); OnDecode(entry); entry.Parameters.Add(new("jumpTo", typeof(uint), jumpTo, InstructionObjectSource.Inline)); bool value = (bool)((opCode == OpCode.JumpIfFalse) ? stack.Pop() : stack.Peek()); entry.Parameters.Add(new("value", typeof(bool), value, InstructionObjectSource.Stack)); bool jumpIfTrue = opCode == OpCode.JumpIfTruePeek; if (jumpIfTrue == value) { reader.CurrentOffset = jumpTo; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.JumpIfDictionaryContains: { ushort propertyIndex = reader.ReadUInt16(); ushort keyIndex = reader.ReadUInt16(); uint jumpTo = reader.ReadUInt32(); entry.Instruction.Operands.Add(propertyIndex); entry.Instruction.Operands.Add(keyIndex); entry.Instruction.Operands.Add(jumpTo); OnDecode(entry); entry.Parameters.Add(new("jumpTo", typeof(uint), jumpTo, InstructionObjectSource.Inline)); string key = (string)constantsTable.Get(keyIndex); entry.Parameters.Add(new("key", typeof(string), key, InstructionObjectSource.Constants, keyIndex)); object dictionary = GetCollection(stack.Peek(), importTables, propertyIndex, out var propertySchema); entry.Parameters.Add(new("dictionary", typeof(IDictionary), dictionary, InstructionObjectSource.Dynamic)); if (propertySchema != null) entry.Parameters.Add(new("dictionaryProperty", typeof(PropertySchema), propertySchema, InstructionObjectSource.TypeImports, propertyIndex)); ReportErrorOnNull(dictionary, "Dictionary Contains"); if (!ErrorsDetected(watermark, ref result, ref errorsDetected)) { bool dictionaryContains = ((IDictionary)dictionary).Contains(key); Trace.IsCategoryEnabled(TraceCategory.Markup); if (dictionaryContains) { reader.CurrentOffset = jumpTo; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } } break; } case OpCode.JumpIfNullPeek: { uint jumpTo = reader.ReadUInt32(); entry.Instruction.Operands.Add(jumpTo); OnDecode(entry); entry.Parameters.Add(new("jumpTo", typeof(uint), jumpTo, InstructionObjectSource.Inline)); object objToCheck = stack.Peek(); entry.Parameters.Add(new("objToCheck", typeof(object), objToCheck, InstructionObjectSource.Stack)); Trace.IsCategoryEnabled(TraceCategory.Markup); if (objToCheck == null) { reader.CurrentOffset = jumpTo; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.Jump: { uint jumpTo = reader.ReadUInt32(); entry.Instruction.Operands.Add(jumpTo); OnDecode(entry); entry.Parameters.Add(new("jumpTo", typeof(uint), jumpTo, InstructionObjectSource.Inline)); reader.CurrentOffset = jumpTo; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.ConstructListenerStorage: { int listenerCount = reader.ReadUInt16(); entry.Instruction.Operands.Add(listenerCount); OnDecode(entry); entry.Parameters.Add(new("listenerCount", typeof(int), listenerCount, InstructionObjectSource.Inline)); if (instance.Listeners == null) { MarkupListeners markupListeners = new(listenerCount); markupListeners.DeclareOwner(instance); instance.Listeners = markupListeners; } else { instance.Listeners.AddEntries(listenerCount); } if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.Listen: case OpCode.DestructiveListen: { int listenerIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(listenerIndex); entry.Parameters.Add(new("listenerIndex", typeof(int), listenerIndex, InstructionObjectSource.Inline)); ListenerType listenerType = (ListenerType)reader.ReadByte(); entry.Instruction.Operands.Add(listenerType); entry.Parameters.Add(new("listenerType", typeof(ListenerType), listenerType, InstructionObjectSource.Inline)); int watchIndex = reader.ReadUInt16(); entry.Instruction.Operands.Add(watchIndex); uint handlerOffset = reader.ReadUInt32(); entry.Instruction.Operands.Add(handlerOffset); entry.Parameters.Add(new("handlerOffset", typeof(uint), handlerOffset, InstructionObjectSource.Inline)); uint refreshOffset = uint.MaxValue; if (opCode == OpCode.DestructiveListen) { refreshOffset = reader.ReadUInt32(); entry.Instruction.Operands.Add(refreshOffset); entry.Parameters.Add(new("refreshOffset", typeof(uint), refreshOffset, InstructionObjectSource.Inline)); } OnDecode(entry); string watch = null; InstructionObjectSource watchSource = InstructionObjectSource.Dynamic; switch (listenerType) { case ListenerType.Property: watch = importTables.PropertyImports[watchIndex].Name; watchSource = InstructionObjectSource.PropertyImports; break; case ListenerType.Event: watch = importTables.EventImports[watchIndex].Name; watchSource = InstructionObjectSource.EventImports; break; case ListenerType.Symbol: watch = symbolReferenceTable[watchIndex].Symbol; watchSource = InstructionObjectSource.SymbolReference; break; } entry.Parameters.Add(new("watch", typeof(string), watch, watchSource, watchIndex)); object handlerObj = stack.Peek(); entry.Parameters.Add(new("handlerObj", typeof(object), handlerObj, InstructionObjectSource.Stack, 1)); if (handlerObj is INotifyObject notifier) { MarkupListeners listeners = instance.Listeners; listeners.RefreshListener(listenerIndex, notifier, watch, instance, handlerOffset, refreshOffset); } else { Trace.IsCategoryEnabled(TraceCategory.Markup); } break; } case OpCode.EnterDebugState: { int breakpointIndex = reader.ReadInt32(); entry.Instruction.Operands.Add(breakpointIndex); OnDecode(entry); entry.Parameters.Add(new("breakpointIndex", typeof(int), breakpointIndex, InstructionObjectSource.Inline)); if (MarkupSystem.IsDebuggingEnabled(2)) { wasInDebugState = MarkupDebugHelper.EnterDebugState(wasInDebugState, loadResult, breakpointIndex, instance.Storage); } break; } } Application.Debugger?.LogInterpreterExecute(context, entry); } while (stack.Count > count) { stack.Pop(); } return result; } // Token: 0x06000F23 RID: 3875 RVA: 0x0002ADA7 File Offset: 0x00029DA7 private static bool ErrorsDetected(ErrorWatermark watermark, ref object result, ref bool done) { if (watermark.ErrorsDetected) { result = ScriptError; done = true; return true; } return false; } // Token: 0x06000F24 RID: 3876 RVA: 0x0002ADC0 File Offset: 0x00029DC0 private static void RegisterDisposable(object instance, TypeSchema type, IMarkupTypeBase root) { if (type.Disposable && root != null) { IDisposableObject disposableObject = (IDisposableObject)instance; root.RegisterDisposable(disposableObject); disposableObject.DeclareOwner(root); } } // Token: 0x06000F25 RID: 3877 RVA: 0x0002ADF0 File Offset: 0x00029DF0 private static object GetCollection(object stackInstance, MarkupImportTables importTables, int propertyIndex, out PropertySchema propertySchema) { object result = null; if (propertyIndex == 0xFFFF) { result = stackInstance; propertySchema = null; } else { propertySchema = importTables.PropertyImports[propertyIndex]; ReportErrorOnNull(stackInstance, "Property Get", propertySchema.Name); if (stackInstance != null) result = propertySchema.GetValue(stackInstance); } return result; } // Token: 0x06000F26 RID: 3878 RVA: 0x0002AE31 File Offset: 0x00029E31 private static void ReportErrorOnNull(object instance, string operation, string member) { if (instance == null) { ErrorManager.ReportError("Script runtime failure: Null-reference while attempting a '{0}' of '{1}' on a null instance", operation, member); } } // Token: 0x06000F27 RID: 3879 RVA: 0x0002AE42 File Offset: 0x00029E42 private static void ReportErrorOnNull(object instance, string operation) { if (instance == null) { ErrorManager.ReportError("Script runtime failure: Null-reference while attempting a '{0}'", operation); } } // Token: 0x06000F28 RID: 3880 RVA: 0x0002AE54 File Offset: 0x00029E54 private static void ReportErrorOnNullOrDisposed(object instance, string operation, string member, TypeSchema typeSchema) { if (instance == null) { ErrorManager.ReportError("Script runtime failure: Null-reference while attempting a '{0}' of '{1}' on a null instance", operation, member); return; } if (typeSchema.Disposable) { IDisposableObject disposableObject = (IDisposableObject)instance; if (disposableObject.IsDisposed) { ErrorManager.ReportError("Script runtime failure: Attempting a '{0}' of '{1}' on an object '{2}' that has already been disposed", operation, member, TypeSchema.NameFromInstance(instance)); } } } // Token: 0x04000947 RID: 2375 public const uint InvalidOffset = 4294967295U; // Token: 0x04000948 RID: 2376 private static object VoidReturnValue = new object(); // Token: 0x04000949 RID: 2377 private static Stack _stack = new Stack(); private static Stack _xmlStack = new Stack(); // Token: 0x0400094A RID: 2378 public static object ScriptError = new Interpreter.ScriptErrorObject(); // Token: 0x0400094B RID: 2379 public static string ExceptionContext; // Token: 0x0200018C RID: 396 private class ScriptErrorObject { } // Token: 0x0200018D RID: 397 private struct ParameterListAllocator { // Token: 0x06000F2C RID: 3884 RVA: 0x0002AECC File Offset: 0x00029ECC public static object[] Alloc(int count) { object[] array; if (count == 0) { array = s_params0; } else if (count < MAX_CACHED_LIST_SIZE) { array = s_cachedLists[count]; if (array != null) { s_cachedLists[count] = null; } else { array = new object[count]; } } else { array = new object[count]; } return array; } // Token: 0x06000F2D RID: 3885 RVA: 0x0002AF10 File Offset: 0x00029F10 public static void Free(object[] paramList) { int num = paramList.Length; if (num != 0 && num < MAX_CACHED_LIST_SIZE && s_cachedLists[num] == null) { Array.Clear(paramList, 0, paramList.Length); s_cachedLists[num] = paramList; } } // Token: 0x0400094C RID: 2380 private const int MAX_CACHED_LIST_SIZE = 20; // Token: 0x0400094D RID: 2381 private static object[] s_params0 = new object[0]; // Token: 0x0400094E RID: 2382 private static object[][] s_cachedLists = new object[MAX_CACHED_LIST_SIZE][]; } private static XmlElement UIXElem; private static XmlDocument _xmlDoc; public static XmlDocument XmlDoc { get { if (_xmlDoc == null) { _xmlDoc = new XmlDocument(); UIXElem = _xmlDoc.CreateElement("UIX"); UIXElem.SetAttribute("xmlns", "http://schemas.microsoft.com/2007/uix"); _xmlDoc.AppendChild(UIXElem); } return _xmlDoc; } } /// /// Attempts to generate source UIX from a compiled result /// private static object RunDecompile(InterpreterContext context, ByteCodeReader reader) { MarkupLoadResult loadResult = context.LoadResult; IMarkupTypeBase instance = context.Instance; MarkupImportTables importTables = loadResult.ImportTables; MarkupConstantsTable constantsTable = loadResult.ConstantsTable; SymbolReference[] symbolReferenceTable = context.MarkupType.SymbolReferenceTable; Trace.IsCategoryEnabled(TraceCategory.Markup); bool decompile = Application.DebugSettings.UseDecompiler; Stack stack = _stack; Stack xmlStack = _xmlStack; int count = stack.Count; if (instance != null) { stack.Push(instance); // Make sure XmlDoc has been initialized _ = XmlDoc; // Add UI container to root string key = instance.TypeSchema.Name; XmlElement instanceXml = UIXElem.ChildNodes.OfType() .FirstOrDefault(elem => elem?.GetAttribute("Name") == key); if (instanceXml == null) { instanceXml = XmlDoc.CreateElement("UI"); instanceXml.SetAttribute("Name", key); UIXElem.AppendChild(instanceXml); } xmlStack.Push(instanceXml); } ErrorWatermark watermark = ErrorManager.Watermark; bool flag = false; object result = null; bool wasInDebugState = false; while (!flag) { OpCode opCode = (OpCode)reader.ReadByte(); switch (opCode) { case OpCode.ConstructObject: { int num = reader.ReadUInt16(); TypeSchema typeSchema = importTables.TypeImports[num]; object obj = typeSchema.ConstructDefault(); string typeName = obj.GetType().Name; int idxTilde = typeName.IndexOf('`'); if (idxTilde >= 0) typeName = typeName.Substring(0, idxTilde); var objXml = XmlDoc.CreateElement(typeName); ReportErrorOnNull(obj, "Construction", typeSchema.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { RegisterDisposable(obj, typeSchema, instance); stack.Push(obj); xmlStack.Push(objXml); } break; } case OpCode.ConstructObjectIndirect: { int num2 = reader.ReadUInt16(); TypeSchema typeSchema2 = importTables.TypeImports[num2]; TypeSchema typeSchema3 = (TypeSchema)stack.Pop(); xmlStack.Pop(); if (!typeSchema2.IsAssignableFrom(typeSchema3)) { ErrorManager.ReportError("Script runtime failure: Dynamic construction type override failed. Attempting to construct '{0}' in place of '{1}'", (typeSchema3 != null) ? typeSchema3.Name : "null", typeSchema2.Name); if (ErrorsDetected(watermark, ref result, ref flag)) { break; } } IDynamicConstructionSchema dynamicConstructionSchema = typeSchema3 as IDynamicConstructionSchema; object obj2; if (dynamicConstructionSchema != null) { obj2 = dynamicConstructionSchema.ConstructDefault(typeSchema2); } else { obj2 = typeSchema3.ConstructDefault(); } var objXml2 = XmlDoc.CreateElement(obj2.GetType().Name); ReportErrorOnNull(obj2, "Construction", typeSchema3.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { RegisterDisposable(obj2, typeSchema3, instance); stack.Push(obj2); xmlStack.Push(objXml2); } break; } case OpCode.ConstructObjectParam: { int num3 = reader.ReadUInt16(); TypeSchema typeSchema4 = importTables.TypeImports[num3]; int num4 = reader.ReadUInt16(); ConstructorSchema constructorSchema = importTables.ConstructorImports[num4]; int i = constructorSchema.ParameterTypes.Length; object[] array = ParameterListAllocator.Alloc(i); for (i--; i >= 0; i--) { array[i] = stack.Pop(); xmlStack.Pop(); // TODO } object obj3 = constructorSchema.Construct(array); var objXml3 = XmlDoc.CreateElement(obj3.GetType().Name); ReportErrorOnNull(obj3, "Construction", typeSchema4.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { RegisterDisposable(obj3, typeSchema4, instance); stack.Push(obj3); xmlStack.Push(objXml3); ParameterListAllocator.Free(array); } break; } case OpCode.ConstructFromString: { int num5 = reader.ReadUInt16(); TypeSchema typeSchema5 = importTables.TypeImports[num5]; int index = reader.ReadUInt16(); string from = (string)constantsTable.Get(index); object obj4; typeSchema5.TypeConverter(from, StringSchema.Type, out obj4); var objXml4 = XmlDoc.CreateElement(obj4.GetType().Name); ReportErrorOnNull(obj4, "Construction", typeSchema5.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { RegisterDisposable(obj4, typeSchema5, instance); stack.Push(obj4); xmlStack.Push(objXml4); } break; } case OpCode.ConstructFromBinary: { int num6 = reader.ReadUInt16(); TypeSchema typeSchema6 = importTables.TypeImports[num6]; object obj5 = typeSchema6.DecodeBinary(reader); var objXml5 = XmlDoc.CreateElement(obj5.GetType().Name); ReportErrorOnNull(obj5, "Construction", typeSchema6.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { RegisterDisposable(obj5, typeSchema6, instance); stack.Push(obj5); xmlStack.Push(objXml5); } break; } case OpCode.InitializeInstance: { int num7 = reader.ReadUInt16(); TypeSchema typeSchema7 = importTables.TypeImports[num7]; object obj6 = stack.Pop(); var objXml6 = (XmlElement)xmlStack.Pop(); typeSchema7.InitializeInstance(ref obj6); objXml6.SetAttribute("Name", typeSchema7.Name); ReportErrorOnNull(obj6, "Initialize", typeSchema7.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { stack.Push(obj6); xmlStack.Push(objXml6); } break; } case OpCode.InitializeInstanceIndirect: { TypeSchema typeSchema8 = (TypeSchema)stack.Pop(); object obj7 = stack.Pop(); typeSchema8.InitializeInstance(ref obj7); xmlStack.Pop(); var objXml7 = (XmlElement)xmlStack.Pop(); objXml7.SetAttribute("Name", typeSchema8.Name); ReportErrorOnNull(obj7, "Initialize", typeSchema8.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { stack.Push(obj7); xmlStack.Push(objXml7); } break; } case OpCode.LookupSymbol: { int num8 = reader.ReadUInt16(); SymbolReference symbolRef = symbolReferenceTable[num8]; object obj8 = context.ReadSymbol(symbolRef); var objXml8 = GenerateXmlRepresentation(obj8); stack.Push(obj8); xmlStack.Push(objXml8); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.WriteSymbol: case OpCode.WriteSymbolPeek: { object value = (opCode == OpCode.WriteSymbolPeek) ? stack.Peek() : stack.Pop(); if (opCode == OpCode.WriteSymbol) xmlStack.Pop(); int num9 = reader.ReadUInt16(); SymbolReference symbolRef2 = symbolReferenceTable[num9]; context.WriteSymbol(symbolRef2, value); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.ClearSymbol: { int num10 = reader.ReadUInt16(); SymbolReference symbolRef3 = symbolReferenceTable[num10]; context.ClearSymbol(symbolRef3); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.PropertyInitialize: case OpCode.PropertyInitializeIndirect: { bool isPropInitIndirect = opCode == OpCode.PropertyInitializeIndirect; TypeSchema typeSchema9 = null; if (isPropInitIndirect) { typeSchema9 = (TypeSchema)stack.Pop(); xmlStack.Pop(); } int num11 = reader.ReadUInt16(); PropertySchema propertySchema = importTables.PropertyImports[num11]; object propValue = stack.Pop(); object destObj = stack.Pop(); XmlNode propValueXml = xmlStack.Pop(); var destObjXml = (XmlElement)xmlStack.Pop(); ReportErrorOnNull(destObj, "Property Set", propertySchema.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { if (isPropInitIndirect) { PropertySchema propertySchema2 = typeSchema9.FindPropertyDeep(propertySchema.Name); if (propertySchema2 != propertySchema) { TypeSchema propertyType = propertySchema2.PropertyType; if (!propertyType.IsAssignableFrom(propValue)) { string param = TypeSchema.NameFromInstance(propValue); ErrorManager.ReportError("Script runtime failure: Incompatible value for property '{0}' supplied (expecting values of type '{1}' but got '{2}') while constructing runtime replacement type '{3}' (original type '{4}')", propertySchema.Name, propertyType.Name, param, typeSchema9.Name, propertySchema.Owner.Name); result = ScriptError; } if (ErrorsDetected(watermark, ref result, ref flag)) { break; } } } propertySchema.SetValue(ref destObj, propValue); if (!IsDefaultValue(propValue)) SetXmlPropValue(destObjXml, propertySchema.Name, propValueXml); if (!ErrorsDetected(watermark, ref result, ref flag)) { stack.Push(destObj); xmlStack.Push(destObjXml); } } break; } case OpCode.PropertyListAdd: { int propertyIndex = reader.ReadUInt16(); object value2 = stack.Pop(); XmlNode valueXml2 = xmlStack.Pop(); object collection = GetCollectionDecompile(stack.Peek(), importTables, propertyIndex, out var propertySchema); ReportErrorOnNull(collection, "List Add"); if (!ErrorsDetected(watermark, ref result, ref flag)) { ((IList)collection).Add(value2); if (ErrorsDetected(watermark, ref result, ref flag)) { } // Add value to list var destObjXml = xmlStack.Peek(); if (!IsDefaultValue(value2) && valueXml2 != null) { if (propertySchema != null) { // Create element if needed if (destObjXml.SelectSingleNode(propertySchema.Name) is not XmlElement propXmlElem2) { propXmlElem2 = XmlDoc.CreateElement(propertySchema.Name); destObjXml.AppendChild(propXmlElem2); } propXmlElem2.AppendChild(valueXml2); } else { // Add straight to parent element var valueXmlElem2 = XmlDoc.CreateElement("String"); valueXmlElem2.AppendChild(valueXml2); destObjXml.AppendChild(valueXmlElem2); } } } break; } case OpCode.PropertyDictionaryAdd: { int propertyIndex2 = reader.ReadUInt16(); int index2 = reader.ReadUInt16(); string key = (string)constantsTable.Get(index2); object value3 = stack.Pop(); XmlNode valueXml3 = xmlStack.Pop(); object collection2 = GetCollectionDecompile(stack.Peek(), importTables, propertyIndex2, out var propertySchema2); ReportErrorOnNull(collection2, "Dictionary Add"); if (!ErrorsDetected(watermark, ref result, ref flag)) { ((IDictionary)collection2)[key] = value3; if (ErrorsDetected(watermark, ref result, ref flag)) { } if (!IsDefaultValue(value3) && valueXml3 != null) { // Prepare value XML element if (valueXml3 is not XmlElement valueXmlElem3) { // Need to create an XML element from the node valueXmlElem3 = XmlDoc.CreateElement(value3.GetType().Name); valueXmlElem3.AppendChild(valueXml3); } // Add value to dictionary var destObjXml2 = xmlStack.Peek(); // Create element if needed if (propertySchema2 != null) { if (destObjXml2.SelectSingleNode(propertySchema2.Name) is not XmlElement propXmlElem2) { propXmlElem2 = XmlDoc.CreateElement(propertySchema2.Name); destObjXml2.AppendChild(propXmlElem2); } propXmlElem2.AppendChild(valueXmlElem3); } valueXmlElem3.SetAttribute("Name", key); } } break; } case OpCode.PropertyAssign: case OpCode.PropertyAssignStatic: { int num12 = reader.ReadUInt16(); PropertySchema propertySchema3 = importTables.PropertyImports[num12]; object instance2 = null; if (opCode == OpCode.PropertyAssign) { instance2 = stack.Pop(); ReportErrorOnNullOrDisposed(instance2, "Property Set", propertySchema3.Name, propertySchema3.Owner); if (ErrorsDetected(watermark, ref result, ref flag)) { break; } } object value4 = stack.Peek(); propertySchema3.SetValue(ref instance2, value4); if (opCode == OpCode.PropertyAssign) { var xmlInstance2 = (XmlElement)xmlStack.Pop(); SetXmlPropValue(xmlInstance2, propertySchema3.Name, value4); } if (!ErrorsDetected(watermark, ref result, ref flag) && Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.PropertyGet: case OpCode.PropertyGetPeek: case OpCode.PropertyGetStatic: { int num13 = reader.ReadUInt16(); PropertySchema propertySchema4 = importTables.PropertyImports[num13]; object instance3 = null; if (opCode != OpCode.PropertyGetStatic) { bool pop = opCode == OpCode.PropertyGet; instance3 = pop ? stack.Pop() : stack.Peek(); if (pop) xmlStack.Pop(); ReportErrorOnNullOrDisposed(instance3, "Property Get", propertySchema4.Name, propertySchema4.Owner); if (ErrorsDetected(watermark, ref result, ref flag)) { break; } } object value5 = propertySchema4.GetValue(instance3); if (!ErrorsDetected(watermark, ref result, ref flag)) { stack.Push(value5); xmlStack.Push(GenerateXmlRepresentation(value5)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.MethodInvoke: case OpCode.MethodInvokePeek: case OpCode.MethodInvokeStatic: case OpCode.MethodInvokePushLastParam: case OpCode.MethodInvokeStaticPushLastParam: { int num14 = reader.ReadUInt16(); MethodSchema methodSchema = importTables.MethodImports[num14]; int j = methodSchema.ParameterTypes.Length; object[] array2 = ParameterListAllocator.Alloc(j); for (j--; j >= 0; j--) { array2[j] = stack.Pop(); xmlStack.Pop(); } object instance4 = null; bool flag3 = opCode != OpCode.MethodInvokeStatic && opCode != OpCode.MethodInvokeStaticPushLastParam; bool flag4 = opCode == OpCode.MethodInvokePeek; bool flag5 = opCode == OpCode.MethodInvokePushLastParam || opCode == OpCode.MethodInvokeStaticPushLastParam; if (flag3) { if (!flag4) { instance4 = stack.Pop(); xmlStack.Pop(); } else { instance4 = stack.Peek(); } ReportErrorOnNullOrDisposed(instance4, "Method Invoke", methodSchema.Name, methodSchema.Owner); if (ErrorsDetected(watermark, ref result, ref flag)) { break; } } if (methodSchema.Name == "PlayOrPreview") System.Diagnostics.Debugger.Break(); object obj11 = methodSchema.Invoke(instance4, array2); if (!ErrorsDetected(watermark, ref result, ref flag)) { if (!flag5) { if (methodSchema.ReturnType != VoidSchema.Type) { stack.Push(obj11); xmlStack.Push(GenerateXmlRepresentation(obj11)); } } else { var lastParam = array2[array2.Length - 1]; stack.Push(lastParam); xmlStack.Push(GenerateXmlRepresentation(lastParam)); } ParameterListAllocator.Free(array2); } break; } case OpCode.VerifyTypeCast: { int num15 = reader.ReadUInt16(); TypeSchema typeSchema10 = importTables.TypeImports[num15]; object obj12 = stack.Peek(); if (obj12 != null) { if (!typeSchema10.IsAssignableFrom(obj12)) { string param2 = TypeSchema.NameFromInstance(obj12); string name = typeSchema10.Name; ErrorManager.ReportError("Script runtime failure: Invalid type cast while attempting to cast an instance with a runtime type of '{0}' to '{1}'", param2, name); result = ScriptError; } if (ErrorsDetected(watermark, ref result, ref flag)) { } } else if (!typeSchema10.IsNullAssignable) { ReportErrorOnNull(obj12, "Verify Type Cast", typeSchema10.Name); if (ErrorsDetected(watermark, ref result, ref flag)) { } } break; } case OpCode.ConvertType: { int num16 = reader.ReadUInt16(); TypeSchema typeSchema11 = importTables.TypeImports[num16]; int num17 = reader.ReadUInt16(); TypeSchema fromType = importTables.TypeImports[num17]; object obj13 = stack.Pop(); var xmlObj13 = xmlStack.Pop(); ReportErrorOnNull(obj13, "Type Conversion", typeSchema11.Name); if (!ErrorsDetected(watermark, ref result, ref flag)) { object obj14; Result result2 = typeSchema11.TypeConverter(obj13, fromType, out obj14); if (result2.Failed) { ErrorManager.ReportError("Script runtime failure: Type conversion failed while attempting to convert to '{0}' ({1})", typeSchema11.Name, result2.Error); } if (!ErrorsDetected(watermark, ref result, ref flag)) { stack.Push(obj14); xmlStack.Push(GenerateXmlRepresentation(obj14)); } } break; } case OpCode.Operation: { int num18 = reader.ReadUInt16(); TypeSchema typeSchema12 = importTables.TypeImports[num18]; OperationType op = (OperationType)reader.ReadByte(); object right = null; if (!TypeSchema.IsUnaryOperation(op)) { right = stack.Pop(); xmlStack.Pop(); } object left = stack.Pop(); xmlStack.Pop(); object obj15 = typeSchema12.PerformOperationDeep(left, right, op); if (!ErrorsDetected(watermark, ref result, ref flag)) { stack.Push(obj15); xmlStack.Push(GenerateXmlRepresentation(obj15)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.IsCheck: { int num19 = reader.ReadUInt16(); TypeSchema typeSchema13 = importTables.TypeImports[num19]; object obj16 = stack.Pop(); var xmlObj16 = xmlStack.Pop(); bool value6 = false; if (obj16 != null) { value6 = typeSchema13.IsAssignableFrom(obj16); } stack.Push(BooleanBoxes.Box(value6)); xmlStack.Push(GenerateXmlRepresentation(value6)); if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.As: { int num20 = reader.ReadUInt16(); TypeSchema typeSchema14 = importTables.TypeImports[num20]; object obj17 = stack.Peek(); if (obj17 != null && !typeSchema14.IsAssignableFrom(obj17)) { stack.Pop(); stack.Push(null); xmlStack.Pop(); xmlStack.Push(GenerateXmlRepresentation(null)); } if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.TypeOf: { int num21 = reader.ReadUInt16(); TypeSchema obj18 = importTables.TypeImports[num21]; stack.Push(obj18); xmlStack.Push(GenerateXmlRepresentation(obj18)); break; } case OpCode.PushNull: stack.Push(null); xmlStack.Push(GenerateXmlRepresentation(null)); break; case OpCode.PushConstant: { int index3 = reader.ReadUInt16(); object obj19 = constantsTable.Get(index3); stack.Push(obj19); xmlStack.Push(GenerateXmlRepresentation(obj19)); break; } case OpCode.PushThis: stack.Push(instance); xmlStack.Push(GenerateXmlRepresentation(instance)); break; case OpCode.DiscardValue: stack.Pop(); xmlStack.Pop(); break; case OpCode.ReturnValue: { object obj20 = stack.Pop(); xmlStack.Pop(); result = obj20; flag = true; break; } case OpCode.ReturnVoid: result = VoidReturnValue; flag = true; break; case OpCode.JumpIfFalse: case OpCode.JumpIfFalsePeek: case OpCode.JumpIfTruePeek: { uint currentOffset = reader.ReadUInt32(); object obj21 = (opCode == OpCode.JumpIfFalse) ? stack.Pop() : stack.Peek(); if (opCode == OpCode.JumpIfFalse) xmlStack.Pop(); bool flag6 = (bool)obj21; bool flag7 = opCode == OpCode.JumpIfTruePeek; Trace.IsCategoryEnabled(TraceCategory.Markup); if (flag7 == flag6) { reader.CurrentOffset = currentOffset; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.JumpIfDictionaryContains: { ushort propertyIndex3 = reader.ReadUInt16(); ushort index4 = reader.ReadUInt16(); uint currentOffset2 = reader.ReadUInt32(); string key2 = (string)constantsTable.Get(index4); object collection3 = GetCollection(stack.Peek(), importTables, propertyIndex3, out _); ReportErrorOnNull(collection3, "Dictionary Contains"); if (!ErrorsDetected(watermark, ref result, ref flag)) { bool flag8 = ((IDictionary)collection3).Contains(key2); Trace.IsCategoryEnabled(TraceCategory.Markup); if (flag8) { reader.CurrentOffset = currentOffset2; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } } break; } case OpCode.JumpIfNullPeek: { uint currentOffset3 = reader.ReadUInt32(); object obj22 = stack.Peek(); Trace.IsCategoryEnabled(TraceCategory.Markup); if (obj22 == null) { reader.CurrentOffset = currentOffset3; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } } break; } case OpCode.Jump: { uint currentOffset4 = reader.ReadUInt32(); reader.CurrentOffset = currentOffset4; if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.ConstructListenerStorage: { int listenerCount = reader.ReadUInt16(); if (instance.Listeners == null) { MarkupListeners markupListeners = new MarkupListeners(listenerCount); markupListeners.DeclareOwner(instance); instance.Listeners = markupListeners; } else { instance.Listeners.AddEntries(listenerCount); } if (Trace.IsCategoryEnabled(TraceCategory.Markup)) { } break; } case OpCode.Listen: case OpCode.DestructiveListen: { int index5 = reader.ReadUInt16(); ListenerType listenerType = (ListenerType)reader.ReadByte(); int num22 = reader.ReadUInt16(); uint scriptOffset = reader.ReadUInt32(); uint refreshOffset = uint.MaxValue; if (opCode == OpCode.DestructiveListen) { refreshOffset = reader.ReadUInt32(); } string watch = null; switch (listenerType) { case ListenerType.Property: watch = importTables.PropertyImports[num22].Name; break; case ListenerType.Event: watch = importTables.EventImports[num22].Name; break; case ListenerType.Symbol: watch = symbolReferenceTable[num22].Symbol; break; } object obj23 = stack.Peek(); if (obj23 != null) { INotifyObject notifier = (INotifyObject)obj23; Trace.IsCategoryEnabled(TraceCategory.Markup); MarkupListeners listeners = instance.Listeners; listeners.RefreshListener(index5, notifier, watch, instance, scriptOffset, refreshOffset); } else { Trace.IsCategoryEnabled(TraceCategory.Markup); } break; } case OpCode.EnterDebugState: { int breakpointIndex = reader.ReadInt32(); if (MarkupSystem.IsDebuggingEnabled(2)) { wasInDebugState = MarkupDebugHelper.EnterDebugState(wasInDebugState, loadResult, breakpointIndex, instance.Storage); } break; } } if (stack.Count != xmlStack.Count) throw new InvalidOperationException( $"Invalid stacks, stack:{stack.Count} != xmlStack{xmlStack.Count}! " + $"Check implementations for {opCode}"); } while (stack.Count > count) { stack.Pop(); xmlStack.Pop(); } CleanUpXmlDoc(); Application.DebugSettings.DecompileResults.Add(new(loadResult.Uri, XmlDoc)); return result; } // Token: 0x06000F25 RID: 3877 RVA: 0x0002ADF0 File Offset: 0x00029DF0 private static object GetCollectionDecompile(object stackInstance, MarkupImportTables importTables, int propertyIndex, out PropertySchema prop) { object result = null; prop = null; if (propertyIndex == 65535) { result = stackInstance; } else { PropertySchema propertySchema = importTables.PropertyImports[propertyIndex]; ReportErrorOnNull(stackInstance, "Property Get", propertySchema.Name); if (stackInstance != null) { result = propertySchema.GetValue(stackInstance); prop = propertySchema; } } return result; } private static XmlNode GenerateXmlRepresentation(object obj, int recursionLevel = 5) { if (obj == null || recursionLevel < 0) { return null; } var objType = obj.GetType(); if (objType.IsPrimitive || objType.IsEnum || objType == typeof(string)) { return XmlDoc.CreateTextNode(obj.ToString()); } else if (obj is AssemblyObjectProxyHelper.IAssemblyProxyObject objProxy && obj != objProxy.AssemblyObject) { // This is a proxy object, meaning it doesn't actually hold any values itself. return GenerateXmlRepresentation(objProxy.AssemblyObject, recursionLevel); } else if (typeof(IEnumerable).IsAssignableFrom(objType)) { // This is a list or array var objXml = XmlDoc.CreateElement("List"); foreach (object item in obj as IEnumerable) { var itemXml = GenerateXmlRepresentation(item, recursionLevel); if (itemXml != null) objXml.AppendChild(itemXml); } return objXml; } else { var objXml = XmlDoc.CreateElement(objType.Name); // Use reflection to recursively generate XML representations for each property foreach (System.Reflection.PropertyInfo prop in objType.GetProperties()) { if (!prop.CanWrite || !prop.CanRead) continue; try { object value = prop.GetValue(obj, null); if (IsDefaultValue(value)) continue; SetXmlPropValue(objXml, prop.Name, value, recursionLevel - 1); } catch { // Ignore errors, sometimes things aren't initialized yet continue; } } return objXml; } } private static void SetXmlPropValue(XmlElement objXml, string propName, object value, int recursionLevel = 10) { var valueXml = GenerateXmlRepresentation(value, recursionLevel); SetXmlPropValue(objXml, propName, valueXml); } private static void SetXmlPropValue(XmlElement objXml, string propName, XmlNode valueXml) { if (valueXml is XmlElement propValueXml) { var propXml = XmlDoc.CreateElement(propName); propXml.AppendChild(propValueXml); objXml.AppendChild(propXml); } else if (valueXml != null) { // Primitive type, set as attribute objXml.SetAttribute(propName, valueXml.InnerText); } } private static bool IsDefaultValue(object value) { if (value == null) return true; var type = value.GetType(); object defaultValue = type.IsValueType ? Activator.CreateInstance(type) : null; return value?.Equals(defaultValue) ?? true; } private static void CleanUpXmlDoc() { XmlNamespaceManager nsManager = new XmlNamespaceManager(XmlDoc.NameTable); var hosts = XmlDoc.DocumentElement.SelectNodes("*//Host", nsManager); foreach (XmlNode node in hosts) { if (!(node is XmlElement host)) continue; if (host.Attributes.Count == 1 && host.HasAttribute("Name")) { string uiElemName = host.GetAttribute("Name"); nsManager.AddNamespace("me", "Me"); XmlDoc.DocumentElement.SetAttribute("xmlns:me", "Me"); XmlElement uiElem = XmlDoc.CreateElement("me", uiElemName, "Me"); host.ParentNode.ReplaceChild(uiElem, host); } } } } }