2022-03-03 08:14:05 -06:00
using System ;
using System.Collections ;
2022-06-24 20:41:00 -05:00
using System.Collections.Generic ;
2022-03-03 08:14:05 -06:00
using System.Linq ;
using System.Xml ;
using Microsoft.Iris.Debug ;
2023-05-25 01:04:30 -05:00
using Microsoft.Iris.Debug.Data ;
2022-03-03 08:14:05 -06:00
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 ;
2023-05-22 18:04:22 -05:00
bool isErrored = true ;
2022-03-03 08:14:05 -06:00
ErrorManager . EnterContext ( context );
try
{
byteCodeReader = context . LoadResult . ObjectSection ;
2023-05-22 18:04:22 -05:00
num = ( long )( ulong ) byteCodeReader . CurrentOffset ;
2022-03-03 08:14:05 -06:00
byteCodeReader . CurrentOffset = context . InitialBytecodeOffset ;
2023-05-23 20:28:19 -05:00
if ( Application . DebugSettings . UseDecompiler )
2022-03-03 08:14:05 -06:00
result = RunDecompile ( context , byteCodeReader );
else
result = Run ( context , byteCodeReader );
2023-05-22 18:04:22 -05:00
isErrored = false ;
2022-03-03 08:14:05 -06:00
}
finally
{
2023-05-22 18:04:22 -05:00
if ( isErrored )
2022-03-03 08:14:05 -06:00
ExceptionContext = context . ToString ();
ErrorManager . ExitContext ();
2023-05-22 18:04:22 -05:00
2022-03-03 08:14:05 -06:00
if ( byteCodeReader != null && num != - 1L )
byteCodeReader . CurrentOffset = ( uint ) num ;
}
return result ;
}
2023-10-09 14:46:51 -05:00
2022-03-03 08:14:05 -06:00
// 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 ;
2023-05-22 18:04:22 -05:00
ErrorWatermark watermark = ErrorManager . Watermark ;
2022-03-03 08:14:05 -06:00
Trace . IsCategoryEnabled ( TraceCategory . Markup );
2023-05-22 18:04:22 -05:00
2022-03-03 08:14:05 -06:00
Stack stack = _stack ;
int count = stack . Count ;
if ( instance != null )
{
stack . Push ( instance );
}
2023-05-22 18:04:22 -05:00
bool errorsDetected = false ;
2022-03-03 08:14:05 -06:00
object result = null ;
bool wasInDebugState = false ;
2023-05-22 21:44:05 -05:00
bool debugging = Application . Debugger != null ;
2023-10-11 13:23:33 -05:00
context . LoadResult . LineNumberTable . DumpTable ();
2023-10-09 14:46:51 -05:00
void OnDecode ( InterpreterEntry entry )
{
if (! debugging ) return ;
Application . Debugger . LogInterpreterDecode ( context , entry . Instruction );
2023-10-09 22:58:28 -05:00
// 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 ;
2023-10-09 14:46:51 -05:00
// 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 ;
}
2023-05-22 18:04:22 -05:00
while (! errorsDetected )
2022-03-03 08:14:05 -06:00
{
OpCode opCode = ( OpCode ) reader . ReadByte ();
2023-10-08 23:54:26 -05:00
InterpreterEntry entry = new ( new ( opCode , reader . CurrentOffset , loadResult . Uri ));
2023-05-22 18:04:22 -05:00
2022-03-03 08:14:05 -06:00
switch ( opCode )
{
case OpCode . ConstructObject :
{
2023-05-25 01:04:30 -05:00
int typeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( typeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
TypeSchema typeSchema = importTables . TypeImports [ typeIndex ];
entry . Parameters . Add ( new InterpreterObject ( "type" , typeof ( TypeSchema ),
2023-08-22 02:04:19 -05:00
typeSchema , InstructionObjectSource . TypeImports , typeIndex ));
2023-05-25 01:04:30 -05:00
object newObj = typeSchema . ConstructDefault ();
2023-10-08 23:54:26 -05:00
2023-05-25 01:04:30 -05:00
ReportErrorOnNull ( newObj , "Construction" , typeSchema . Name );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
RegisterDisposable ( newObj , typeSchema , instance );
stack . Push ( newObj );
entry . ReturnValues . Add ( new ( newObj ));
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . ConstructObjectIndirect :
{
2023-05-25 01:04:30 -05:00
int assignmentTypeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( assignmentTypeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
break ;
}
2023-05-25 01:04:30 -05:00
object newObj = targetTypeSchema is IDynamicConstructionSchema dynamicConstructionSchema
? dynamicConstructionSchema . ConstructDefault ( assignmentTypeSchema )
: targetTypeSchema . ConstructDefault ();
ReportErrorOnNull ( newObj , "Construction" , targetTypeSchema . Name );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
RegisterDisposable ( newObj , targetTypeSchema , instance );
stack . Push ( newObj );
entry . ReturnValues . Add ( new ( newObj ));
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . ConstructObjectParam :
{
2023-05-25 01:04:30 -05:00
int targetTypeIndex = reader . ReadUInt16 ();
int constructorIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( targetTypeIndex );
entry . Instruction . Operands . Add ( constructorIndex );
OnDecode ( entry );
TypeSchema targetTypeSchema = importTables . TypeImports [ targetTypeIndex ];
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
RegisterDisposable ( newObj , targetTypeSchema , instance );
stack . Push ( newObj );
entry . ReturnValues . Add ( new ( newObj ));
2022-03-03 08:14:05 -06:00
ParameterListAllocator . Free ( array );
}
break ;
}
case OpCode . ConstructFromString :
{
2023-05-25 01:04:30 -05:00
int typeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
int stringIndex = reader . ReadUInt16 ();
entry . Instruction . Operands . Add ( typeIndex );
entry . Instruction . Operands . Add ( stringIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
RegisterDisposable ( newObj , typeSchema , instance );
stack . Push ( newObj );
entry . ReturnValues . Add ( new ( newObj ));
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . ConstructFromBinary :
{
2023-05-25 01:04:30 -05:00
int typeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( typeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
RegisterDisposable ( newObj , typeSchema , instance );
stack . Push ( newObj );
entry . ReturnValues . Add ( new ( newObj ));
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . InitializeInstance :
{
2023-05-25 01:04:30 -05:00
int typeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( typeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
stack . Push ( objToInit );
entry . ReturnValues . Add ( new ( objToInit ));
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . InitializeInstanceIndirect :
{
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
stack . Push ( objToInit );
entry . ReturnValues . Add ( new ( objToInit ));
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . LookupSymbol :
{
2023-05-25 01:04:30 -05:00
int symbolRefIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( symbolRefIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
SymbolReference symbolRef = symbolReferenceTable [ symbolRefIndex ];
entry . Parameters . Add ( new ( "symbolRef" , typeof ( SymbolReference ),
symbolRef , InstructionObjectSource . SymbolReference , symbolRefIndex ));
2023-05-24 10:14:07 -05:00
2023-05-25 01:04:30 -05:00
object symbol = context . ReadSymbol ( symbolRef );
2023-05-24 10:14:07 -05:00
2023-05-25 01:04:30 -05:00
stack . Push ( symbol );
entry . ReturnValues . Add ( new ( symbol ));
2023-05-24 10:14:07 -05:00
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . WriteSymbol :
case OpCode . WriteSymbolPeek :
{
2023-10-09 14:46:51 -05:00
int symbolRefIndex = reader . ReadUInt16 ();
entry . Instruction . Operands . Add ( symbolRefIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
object symbol = ( opCode == OpCode . WriteSymbolPeek ) ? stack . Peek () : stack . Pop ();
entry . Parameters . Add ( new ( "symbol" , typeof ( object ),
symbol , InstructionObjectSource . Stack ));
2023-05-24 10:14:07 -05:00
2023-05-25 01:04:30 -05:00
SymbolReference symbolRef = symbolReferenceTable [ symbolRefIndex ];
entry . Parameters . Add ( new ( "symbolRef" , typeof ( SymbolReference ),
symbolRef , InstructionObjectSource . SymbolReference , symbolRefIndex ));
2023-05-24 10:14:07 -05:00
2023-05-25 01:04:30 -05:00
context . WriteSymbol ( symbolRef , symbol );
2023-05-24 10:14:07 -05:00
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . ClearSymbol :
{
2023-05-25 01:04:30 -05:00
int symbolRefIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( symbolRefIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
SymbolReference symbolRef = symbolReferenceTable [ symbolRefIndex ];
entry . Parameters . Add ( new ( "symbolRef" , typeof ( SymbolReference ),
symbolRef , InstructionObjectSource . SymbolReference , symbolRefIndex ));
context . ClearSymbol ( symbolRef );
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . PropertyInitialize :
case OpCode . PropertyInitializeIndirect :
{
2023-10-09 14:46:51 -05:00
int propertyIndex = reader . ReadUInt16 ();
entry . Instruction . Operands . Add ( propertyIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
bool isIndirect = opCode == OpCode . PropertyInitializeIndirect ;
TypeSchema parentTypeSchema = null ;
if ( isIndirect )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
parentTypeSchema = ( TypeSchema ) stack . Pop ();
entry . Parameters . Add ( new ( "parentType" , typeof ( TypeSchema ),
parentTypeSchema , InstructionObjectSource . Stack ));
2022-03-03 08:14:05 -06:00
}
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
if ( isIndirect )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
PropertySchema inheritedPropertySchema = parentTypeSchema . FindPropertyDeep ( propertySchema . Name );
if ( inheritedPropertySchema != propertySchema )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
TypeSchema propertyType = inheritedPropertySchema . PropertyType ;
if (! propertyType . IsAssignableFrom ( propertyValue ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
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 );
2022-03-03 08:14:05 -06:00
result = ScriptError ;
}
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
break ;
}
}
}
2023-05-25 01:04:30 -05:00
propertySchema . SetValue ( ref parentObj , propertyValue );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
stack . Push ( parentObj );
entry . ReturnValues . Add ( new ( parentObj ));
2022-03-03 08:14:05 -06:00
}
}
break ;
}
case OpCode . PropertyListAdd :
{
2023-10-09 14:46:51 -05:00
int propertyIndex = reader . ReadUInt16 ();
entry . Instruction . Operands . Add ( propertyIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 ));
2022-03-03 08:14:05 -06:00
ReportErrorOnNull ( collection , "List Add" );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
(( IList ) collection ). Add ( objToAdd );
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
}
}
break ;
}
case OpCode . PropertyDictionaryAdd :
{
2023-05-25 01:04:30 -05:00
int propertyIndex = reader . ReadUInt16 ();
int keyIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( propertyIndex );
entry . Instruction . Operands . Add ( keyIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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" );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
(( IDictionary ) dictionary )[ key ] = objToAdd ;
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
}
}
break ;
}
case OpCode . PropertyAssign :
case OpCode . PropertyAssignStatic :
{
2023-05-25 01:04:30 -05:00
int propertyIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( propertyIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
PropertySchema propertySchema = importTables . PropertyImports [ propertyIndex ];
entry . Parameters . Add ( new ( "property" , typeof ( PropertySchema ),
propertySchema , InstructionObjectSource . PropertyImports , propertyIndex ));
object parentObj = null ;
2022-03-03 08:14:05 -06:00
if ( opCode == OpCode . PropertyAssign )
{
2023-05-25 01:04:30 -05:00
parentObj = stack . Pop ();
entry . Parameters . Add ( new ( "parent" , typeof ( object ),
parentObj , InstructionObjectSource . Stack ));
ReportErrorOnNullOrDisposed ( parentObj , "Property Set" , propertySchema . Name , propertySchema . Owner );
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
break ;
}
}
2023-05-25 01:04:30 -05:00
object propertyValue = stack . Peek ();
entry . Parameters . Add ( new ( "value" , typeof ( object ),
propertyValue , InstructionObjectSource . Stack , 1 ));
propertySchema . SetValue ( ref parentObj , propertyValue );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ) && Trace . IsCategoryEnabled ( TraceCategory . Markup ))
2022-03-03 08:14:05 -06:00
{
}
break ;
}
case OpCode . PropertyGet :
case OpCode . PropertyGetPeek :
case OpCode . PropertyGetStatic :
{
2023-05-25 01:04:30 -05:00
int propertyIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( propertyIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
PropertySchema propertySchema = importTables . PropertyImports [ propertyIndex ];
entry . Parameters . Add ( new ( "property" , typeof ( PropertySchema ),
propertySchema , InstructionObjectSource . PropertyImports , propertyIndex ));
object parentObj = null ;
2022-03-03 08:14:05 -06:00
if ( opCode != OpCode . PropertyGetStatic )
{
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
break ;
}
}
2023-05-25 01:04:30 -05:00
object propertyValue = propertySchema . GetValue ( parentObj );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
stack . Push ( propertyValue );
entry . ReturnValues . Add ( new ( propertyValue ));
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
}
break ;
}
case OpCode . MethodInvoke :
case OpCode . MethodInvokePeek :
case OpCode . MethodInvokeStatic :
case OpCode . MethodInvokePushLastParam :
case OpCode . MethodInvokeStaticPushLastParam :
{
2023-05-25 01:04:30 -05:00
int methodIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( methodIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
parentObj = ! peek ? stack . Pop () : stack . Peek ();
entry . Parameters . Add ( new ( "parent" , typeof ( object ),
parentObj , InstructionObjectSource . Stack ));
ReportErrorOnNullOrDisposed ( parentObj , "Method Invoke" , methodSchema . Name , methodSchema . Owner );
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
break ;
}
}
2023-04-28 18:46:37 -05:00
2023-05-25 01:04:30 -05:00
object methodResult = methodSchema . Invoke ( parentObj , parameters );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
if (! pushLastParam )
2022-03-03 08:14:05 -06:00
{
if ( methodSchema . ReturnType != VoidSchema . Type )
{
2023-05-25 01:04:30 -05:00
stack . Push ( methodResult );
entry . ReturnValues . Add ( new ( methodResult ));
2022-03-03 08:14:05 -06:00
}
}
else
{
2023-05-25 01:04:30 -05:00
stack . Push ( parameters [ parameters . Length - 1 ]);
2022-03-03 08:14:05 -06:00
}
2023-05-25 01:04:30 -05:00
ParameterListAllocator . Free ( parameters );
2022-03-03 08:14:05 -06:00
}
break ;
}
case OpCode . VerifyTypeCast :
{
2023-05-25 01:04:30 -05:00
int typeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( typeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
if (! typeSchema . IsAssignableFrom ( objToCheck ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
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 );
2022-03-03 08:14:05 -06:00
result = ScriptError ;
}
2023-05-25 01:04:30 -05:00
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
}
}
2023-05-25 01:04:30 -05:00
else if (! typeSchema . IsNullAssignable )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
ReportErrorOnNull ( objToCheck , "Verify Type Cast" , typeSchema . Name );
2023-05-22 18:04:22 -05:00
if ( ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
}
}
break ;
}
case OpCode . ConvertType :
{
2023-05-25 01:04:30 -05:00
int toTypeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
int fromTypeIndex = reader . ReadUInt16 ();
entry . Instruction . Operands . Add ( toTypeIndex );
entry . Instruction . Operands . Add ( fromTypeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
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 );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
stack . Push ( obj14 );
2023-05-25 01:04:30 -05:00
entry . ReturnValues . Add ( new ( obj14 ));
2022-03-03 08:14:05 -06:00
}
}
break ;
}
case OpCode . Operation :
{
2023-05-25 01:04:30 -05:00
int opHostIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
OperationType op = ( OperationType ) reader . ReadByte ();
entry . Instruction . Operands . Add ( opHostIndex );
entry . Instruction . Operands . Add ( op );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 ));
2022-03-03 08:14:05 -06:00
object right = null ;
if (! TypeSchema . IsUnaryOperation ( op ))
{
right = stack . Pop ();
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "right" , typeof ( object ),
right , InstructionObjectSource . Stack ));
2022-03-03 08:14:05 -06:00
}
2023-05-25 01:04:30 -05:00
2022-03-03 08:14:05 -06:00
object left = stack . Pop ();
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "left" , typeof ( object ),
left , InstructionObjectSource . Stack ));
object opResult = opHost . PerformOperationDeep ( left , right , op );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
stack . Push ( opResult );
entry . ReturnValues . Add ( new ( opResult ));
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
}
break ;
}
case OpCode . IsCheck :
{
2023-05-25 01:04:30 -05:00
int targetTypeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( targetTypeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 ));
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . As :
{
2023-05-25 01:04:30 -05:00
int targetTypeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( targetTypeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 ))
2022-03-03 08:14:05 -06:00
{
stack . Pop ();
stack . Push ( null );
}
2023-05-25 01:04:30 -05:00
else if ( debugging )
{
// The opcode isn't implemented like this,
// but technically As returns a value.
entry . ReturnValues . Add ( new ( objToCheck ));
}
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . TypeOf :
{
2023-05-25 01:04:30 -05:00
int typeIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( typeIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "typeIndex" , typeof ( ushort ),
typeIndex , InstructionObjectSource . Inline ));
TypeSchema typeSchema = importTables . TypeImports [ typeIndex ];
stack . Push ( typeSchema );
entry . ReturnValues . Add ( new ( typeSchema ));
2022-03-03 08:14:05 -06:00
break ;
}
case OpCode . PushNull :
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2022-03-03 08:14:05 -06:00
stack . Push ( null );
2023-05-25 01:04:30 -05:00
entry . ReturnValues . Add ( new ( null ));
2022-03-03 08:14:05 -06:00
break ;
case OpCode . PushConstant :
{
2023-05-25 01:04:30 -05:00
int constantIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( constantIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "constantIndex" , typeof ( ushort ),
constantIndex , InstructionObjectSource . Inline ));
object constant = constantsTable . Get ( constantIndex );
stack . Push ( constant );
entry . ReturnValues . Add ( new ( constant ));
2022-03-03 08:14:05 -06:00
break ;
}
case OpCode . PushThis :
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2022-03-03 08:14:05 -06:00
stack . Push ( instance );
2023-05-25 01:04:30 -05:00
entry . ReturnValues . Add ( new ( instance ));
2022-03-03 08:14:05 -06:00
break ;
case OpCode . DiscardValue :
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2022-03-03 08:14:05 -06:00
stack . Pop ();
break ;
case OpCode . ReturnValue :
{
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
object thisResult = stack . Pop ();
entry . ReturnValues . Add ( new ( thisResult ));
result = thisResult ;
2023-05-22 18:04:22 -05:00
errorsDetected = true ;
2022-03-03 08:14:05 -06:00
break ;
}
case OpCode . ReturnVoid :
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2022-03-03 08:14:05 -06:00
result = VoidReturnValue ;
2023-05-22 18:04:22 -05:00
errorsDetected = true ;
2022-03-03 08:14:05 -06:00
break ;
case OpCode . JumpIfFalse :
case OpCode . JumpIfFalsePeek :
case OpCode . JumpIfTruePeek :
{
2023-05-25 01:04:30 -05:00
uint jumpTo = reader . ReadUInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( jumpTo );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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 )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
reader . CurrentOffset = jumpTo ;
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
}
break ;
}
case OpCode . JumpIfDictionaryContains :
{
2023-05-25 01:04:30 -05:00
ushort propertyIndex = reader . ReadUInt16 ();
ushort keyIndex = reader . ReadUInt16 ();
uint jumpTo = reader . ReadUInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( propertyIndex );
entry . Instruction . Operands . Add ( keyIndex );
entry . Instruction . Operands . Add ( jumpTo );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
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" );
2023-05-22 18:04:22 -05:00
if (! ErrorsDetected ( watermark , ref result , ref errorsDetected ))
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
bool dictionaryContains = (( IDictionary ) dictionary ). Contains ( key );
2022-03-03 08:14:05 -06:00
Trace . IsCategoryEnabled ( TraceCategory . Markup );
2023-05-25 01:04:30 -05:00
if ( dictionaryContains )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
reader . CurrentOffset = jumpTo ;
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
}
}
break ;
}
case OpCode . JumpIfNullPeek :
{
2023-05-25 01:04:30 -05:00
uint jumpTo = reader . ReadUInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( jumpTo );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "jumpTo" , typeof ( uint ),
jumpTo , InstructionObjectSource . Inline ));
object objToCheck = stack . Peek ();
entry . Parameters . Add ( new ( "objToCheck" , typeof ( object ),
objToCheck , InstructionObjectSource . Stack ));
2022-03-03 08:14:05 -06:00
Trace . IsCategoryEnabled ( TraceCategory . Markup );
2023-05-25 01:04:30 -05:00
if ( objToCheck == null )
2022-03-03 08:14:05 -06:00
{
2023-05-25 01:04:30 -05:00
reader . CurrentOffset = jumpTo ;
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
}
break ;
}
case OpCode . Jump :
{
2023-05-25 01:04:30 -05:00
uint jumpTo = reader . ReadUInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( jumpTo );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "jumpTo" , typeof ( uint ),
jumpTo , InstructionObjectSource . Inline ));
reader . CurrentOffset = jumpTo ;
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . ConstructListenerStorage :
{
int listenerCount = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( listenerCount );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "listenerCount" , typeof ( int ),
listenerCount , InstructionObjectSource . Inline ));
2022-03-03 08:14:05 -06:00
if ( instance . Listeners == null )
{
2023-05-25 01:04:30 -05:00
MarkupListeners markupListeners = new ( listenerCount );
2022-03-03 08:14:05 -06:00
markupListeners . DeclareOwner ( instance );
instance . Listeners = markupListeners ;
}
else
{
instance . Listeners . AddEntries ( listenerCount );
}
2023-05-25 01:04:30 -05:00
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . Listen :
case OpCode . DestructiveListen :
{
2023-05-25 01:04:30 -05:00
int listenerIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( listenerIndex );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "listenerIndex" , typeof ( int ),
listenerIndex , InstructionObjectSource . Inline ));
2022-03-03 08:14:05 -06:00
ListenerType listenerType = ( ListenerType ) reader . ReadByte ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( listenerType );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "listenerType" , typeof ( ListenerType ),
listenerType , InstructionObjectSource . Inline ));
int watchIndex = reader . ReadUInt16 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( watchIndex );
2023-05-25 01:04:30 -05:00
uint handlerOffset = reader . ReadUInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( handlerOffset );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "handlerOffset" , typeof ( uint ),
handlerOffset , InstructionObjectSource . Inline ));
2022-03-03 08:14:05 -06:00
uint refreshOffset = uint . MaxValue ;
if ( opCode == OpCode . DestructiveListen )
{
refreshOffset = reader . ReadUInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( refreshOffset );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "refreshOffset" , typeof ( uint ),
refreshOffset , InstructionObjectSource . Inline ));
2022-03-03 08:14:05 -06:00
}
2023-05-25 01:04:30 -05:00
2023-10-09 14:46:51 -05:00
OnDecode ( entry );
2022-03-03 08:14:05 -06:00
string watch = null ;
2023-05-25 01:04:30 -05:00
InstructionObjectSource watchSource = InstructionObjectSource . Dynamic ;
2022-03-03 08:14:05 -06:00
switch ( listenerType )
{
case ListenerType . Property :
2023-05-25 01:04:30 -05:00
watch = importTables . PropertyImports [ watchIndex ]. Name ;
watchSource = InstructionObjectSource . PropertyImports ;
2022-03-03 08:14:05 -06:00
break ;
case ListenerType . Event :
2023-05-25 01:04:30 -05:00
watch = importTables . EventImports [ watchIndex ]. Name ;
watchSource = InstructionObjectSource . EventImports ;
2022-03-03 08:14:05 -06:00
break ;
case ListenerType . Symbol :
2023-05-25 01:04:30 -05:00
watch = symbolReferenceTable [ watchIndex ]. Symbol ;
watchSource = InstructionObjectSource . SymbolReference ;
2022-03-03 08:14:05 -06:00
break ;
}
2023-05-25 01:04:30 -05:00
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 )
2022-03-03 08:14:05 -06:00
{
MarkupListeners listeners = instance . Listeners ;
2023-05-25 01:04:30 -05:00
listeners . RefreshListener ( listenerIndex , notifier , watch , instance , handlerOffset , refreshOffset );
2022-03-03 08:14:05 -06:00
}
else
{
Trace . IsCategoryEnabled ( TraceCategory . Markup );
}
break ;
}
case OpCode . EnterDebugState :
{
int breakpointIndex = reader . ReadInt32 ();
2023-10-09 14:46:51 -05:00
entry . Instruction . Operands . Add ( breakpointIndex );
OnDecode ( entry );
2023-05-25 01:04:30 -05:00
entry . Parameters . Add ( new ( "breakpointIndex" , typeof ( int ),
breakpointIndex , InstructionObjectSource . Inline ));
2022-03-03 08:14:05 -06:00
if ( MarkupSystem . IsDebuggingEnabled ( 2 ))
{
wasInDebugState = MarkupDebugHelper . EnterDebugState ( wasInDebugState , loadResult , breakpointIndex , instance . Storage );
}
break ;
}
}
2023-05-22 18:04:22 -05:00
2023-10-09 14:46:51 -05:00
Application . Debugger ?. LogInterpreterExecute ( context , entry );
2022-03-03 08:14:05 -06:00
}
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
2023-05-25 01:04:30 -05:00
private static object GetCollection ( object stackInstance , MarkupImportTables importTables , int propertyIndex , out PropertySchema propertySchema )
2022-03-03 08:14:05 -06:00
{
object result = null ;
2023-05-25 01:04:30 -05:00
if ( propertyIndex == 0xFFFF )
2022-03-03 08:14:05 -06:00
{
result = stackInstance ;
2023-05-25 01:04:30 -05:00
propertySchema = null ;
2022-03-03 08:14:05 -06:00
}
else
{
2023-05-25 01:04:30 -05:00
propertySchema = importTables . PropertyImports [ propertyIndex ];
2022-03-03 08:14:05 -06:00
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 = 4294967295 U ;
// Token: 0x04000948 RID: 2376
private static object VoidReturnValue = new object ();
// Token: 0x04000949 RID: 2377
private static Stack _stack = new Stack ();
2022-06-24 20:41:00 -05:00
private static Stack < XmlNode > _xmlStack = new Stack < XmlNode >();
2022-03-03 08:14:05 -06:00
// 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 ;
}
2023-05-22 18:04:22 -05:00
else if ( count < MAX_CACHED_LIST_SIZE )
2022-03-03 08:14:05 -06:00
{
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 ;
2023-05-22 18:04:22 -05:00
if ( num != 0 && num < MAX_CACHED_LIST_SIZE && s_cachedLists [ num ] == null )
2022-03-03 08:14:05 -06:00
{
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
2023-05-22 18:04:22 -05:00
private static object [][] s_cachedLists = new object [ MAX_CACHED_LIST_SIZE ][];
2022-03-03 08:14:05 -06:00
}
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 ;
}
}
/// <summary>
/// Attempts to generate source UIX from a compiled result
/// </summary>
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 ;
2023-05-22 18:04:22 -05:00
2022-03-03 08:14:05 -06:00
Trace . IsCategoryEnabled ( TraceCategory . Markup );
2023-05-22 18:04:22 -05:00
bool decompile = Application . DebugSettings . UseDecompiler ;
2022-03-03 08:14:05 -06:00
Stack stack = _stack ;
2022-06-24 20:41:00 -05:00
Stack < XmlNode > xmlStack = _xmlStack ;
2022-03-03 08:14:05 -06:00
int count = stack . Count ;
2023-05-22 18:04:22 -05:00
2022-03-03 08:14:05 -06:00
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 < XmlElement >()
. 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 ();
2022-06-07 14:30:29 -05:00
2022-03-03 08:14:05 -06:00
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 ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 );
2022-07-05 12:00:18 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 ];
2022-06-07 14:30:29 -05:00
2022-03-03 08:14:05 -06:00
object obj8 = context . ReadSymbol ( symbolRef );
2022-06-24 20:41:00 -05:00
var objXml8 = GenerateXmlRepresentation ( obj8 );
2022-06-07 14:30:29 -05:00
2022-03-03 08:14:05 -06:00
stack . Push ( obj8 );
xmlStack . Push ( objXml8 );
2022-06-07 14:30:29 -05:00
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . WriteSymbol :
case OpCode . WriteSymbolPeek :
{
object value = ( opCode == OpCode . WriteSymbolPeek ) ? stack . Peek () : stack . Pop ();
2022-07-05 12:00:18 -05:00
if ( opCode == OpCode . WriteSymbol ) xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
int num9 = reader . ReadUInt16 ();
SymbolReference symbolRef2 = symbolReferenceTable [ num9 ];
2022-06-07 14:30:29 -05:00
2022-03-03 08:14:05 -06:00
context . WriteSymbol ( symbolRef2 , value );
2022-06-07 14:30:29 -05:00
2022-03-03 08:14:05 -06:00
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 ();
2022-07-05 12:00:18 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
}
int num11 = reader . ReadUInt16 ();
PropertySchema propertySchema = importTables . PropertyImports [ num11 ];
object propValue = stack . Pop ();
object destObj = stack . Pop ();
2022-06-24 20:41:00 -05:00
XmlNode propValueXml = xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 ;
}
}
}
2022-06-24 20:41:00 -05:00
2022-03-03 08:14:05 -06:00
propertySchema . SetValue ( ref destObj , propValue );
2022-06-24 20:41:00 -05:00
if (! IsDefaultValue ( propValue ))
SetXmlPropValue ( destObjXml , propertySchema . Name , propValueXml );
2022-03-03 08:14:05 -06:00
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 ();
2022-06-24 20:41:00 -05:00
XmlNode valueXml2 = xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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
2022-06-24 20:41:00 -05:00
var destObjXml = xmlStack . Peek ();
if (! IsDefaultValue ( value2 ) && valueXml2 != null )
2022-03-03 08:14:05 -06:00
{
2022-07-05 12:00:18 -05:00
if ( propertySchema != null )
2022-06-24 20:41:00 -05:00
{
2022-07-05 12:00:18 -05:00
// 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 );
2022-06-24 20:41:00 -05:00
}
2022-03-03 08:14:05 -06:00
}
}
break ;
}
case OpCode . PropertyDictionaryAdd :
{
int propertyIndex2 = reader . ReadUInt16 ();
int index2 = reader . ReadUInt16 ();
string key = ( string ) constantsTable . Get ( index2 );
object value3 = stack . Pop ();
2022-06-24 20:41:00 -05:00
XmlNode valueXml3 = xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 ))
{
}
2022-06-24 20:41:00 -05:00
if (! IsDefaultValue ( value3 ) && valueXml3 != null )
2022-03-03 08:14:05 -06:00
{
2022-06-24 20:41:00 -05:00
// Prepare value XML element
if ( valueXml3 is not XmlElement valueXmlElem3 )
2022-03-03 08:14:05 -06:00
{
2022-06-24 20:41:00 -05:00
// Need to create an XML element from the node
valueXmlElem3 = XmlDoc . CreateElement ( value3 . GetType (). Name );
valueXmlElem3 . AppendChild ( valueXml3 );
2022-03-03 08:14:05 -06:00
}
2022-06-24 20:41:00 -05:00
// 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 );
2022-03-03 08:14:05 -06:00
}
}
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 );
2022-06-24 20:41:00 -05:00
if ( opCode == OpCode . PropertyAssign )
{
var xmlInstance2 = ( XmlElement ) xmlStack . Pop ();
SetXmlPropValue ( xmlInstance2 , propertySchema3 . Name , value4 );
}
2022-03-03 08:14:05 -06:00
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 ];
2022-06-24 20:41:00 -05:00
2022-03-03 08:14:05 -06:00
object instance3 = null ;
2022-06-24 20:41:00 -05:00
2022-03-03 08:14:05 -06:00
if ( opCode != OpCode . PropertyGetStatic )
{
2022-06-24 20:41:00 -05:00
bool pop = opCode == OpCode . PropertyGet ;
instance3 = pop ? stack . Pop () : stack . Peek ();
2022-07-05 12:00:18 -05:00
if ( pop ) xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
}
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 ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
}
else
{
instance4 = stack . Peek ();
}
ReportErrorOnNullOrDisposed ( instance4 , "Method Invoke" , methodSchema . Name , methodSchema . Owner );
if ( ErrorsDetected ( watermark , ref result , ref flag ))
{
break ;
}
}
2023-04-28 18:46:37 -05:00
if ( methodSchema . Name == "PlayOrPreview" )
System . Diagnostics . Debugger . Break ();
2022-03-03 08:14:05 -06:00
object obj11 = methodSchema . Invoke ( instance4 , array2 );
if (! ErrorsDetected ( watermark , ref result , ref flag ))
{
if (! flag5 )
{
if ( methodSchema . ReturnType != VoidSchema . Type )
{
stack . Push ( obj11 );
2022-06-24 20:41:00 -05:00
xmlStack . Push ( GenerateXmlRepresentation ( obj11 ));
2022-03-03 08:14:05 -06:00
}
}
else
{
2022-06-24 20:41:00 -05:00
var lastParam = array2 [ array2 . Length - 1 ];
stack . Push ( lastParam );
xmlStack . Push ( GenerateXmlRepresentation ( lastParam ));
2022-03-03 08:14:05 -06:00
}
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 ();
2022-06-24 20:41:00 -05:00
var xmlObj13 = xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 );
2022-06-24 20:41:00 -05:00
xmlStack . Push ( GenerateXmlRepresentation ( obj14 ));
2022-03-03 08:14:05 -06:00
}
}
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 ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
}
object left = stack . Pop ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
object obj15 = typeSchema12 . PerformOperationDeep ( left , right , op );
if (! ErrorsDetected ( watermark , ref result , ref flag ))
{
stack . Push ( obj15 );
2022-06-24 20:41:00 -05:00
xmlStack . Push ( GenerateXmlRepresentation ( obj15 ));
2022-03-03 08:14:05 -06:00
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
}
break ;
}
case OpCode . IsCheck :
{
int num19 = reader . ReadUInt16 ();
TypeSchema typeSchema13 = importTables . TypeImports [ num19 ];
object obj16 = stack . Pop ();
2022-06-24 20:41:00 -05:00
var xmlObj16 = xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
bool value6 = false ;
if ( obj16 != null )
{
value6 = typeSchema13 . IsAssignableFrom ( obj16 );
}
stack . Push ( BooleanBoxes . Box ( value6 ));
2022-06-24 20:41:00 -05:00
xmlStack . Push ( GenerateXmlRepresentation ( value6 ));
2022-03-03 08:14:05 -06:00
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 );
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
xmlStack . Push ( GenerateXmlRepresentation ( null ));
2022-03-03 08:14:05 -06:00
}
if ( Trace . IsCategoryEnabled ( TraceCategory . Markup ))
{
}
break ;
}
case OpCode . TypeOf :
{
int num21 = reader . ReadUInt16 ();
TypeSchema obj18 = importTables . TypeImports [ num21 ];
stack . Push ( obj18 );
2022-06-24 20:41:00 -05:00
xmlStack . Push ( GenerateXmlRepresentation ( obj18 ));
2022-03-03 08:14:05 -06:00
break ;
}
case OpCode . PushNull :
stack . Push ( null );
2022-06-24 20:41:00 -05:00
xmlStack . Push ( GenerateXmlRepresentation ( null ));
2022-03-03 08:14:05 -06:00
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 ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
break ;
case OpCode . ReturnValue :
{
object obj20 = stack . Pop ();
2022-06-24 20:41:00 -05:00
xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 ();
2022-06-24 20:41:00 -05:00
if ( opCode == OpCode . JumpIfFalse ) xmlStack . Pop ();
2022-03-03 08:14:05 -06:00
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 );
2023-05-25 01:04:30 -05:00
object collection3 = GetCollection ( stack . Peek (), importTables , propertyIndex3 , out _ );
2022-03-03 08:14:05 -06:00
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}! " +
2022-06-07 14:30:29 -05:00
$"Check implementations for {opCode}" );
2022-03-03 08:14:05 -06:00
}
while ( stack . Count > count )
{
stack . Pop ();
xmlStack . Pop ();
}
CleanUpXmlDoc ();
2022-06-24 20:41:00 -05:00
Application . DebugSettings . DecompileResults . Add ( new ( loadResult . Uri , XmlDoc ));
2022-03-03 08:14:05 -06:00
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 ;
}
2022-06-24 20:41:00 -05:00
private static XmlNode GenerateXmlRepresentation ( object obj , int recursionLevel = 5 )
2022-03-03 08:14:05 -06:00
{
2022-06-24 20:41:00 -05:00
if ( obj == null || recursionLevel < 0 )
2022-03-03 08:14:05 -06:00
{
2022-06-24 20:41:00 -05:00
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 )
2022-03-03 08:14:05 -06:00
{
2022-06-24 20:41:00 -05:00
var itemXml = GenerateXmlRepresentation ( item , recursionLevel );
if ( itemXml != null )
objXml . AppendChild ( itemXml );
2022-03-03 08:14:05 -06:00
}
return objXml ;
}
2022-06-24 20:41:00 -05:00
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 ;
2022-07-05 12:00:18 -05:00
try
{
object value = prop . GetValue ( obj , null );
if ( IsDefaultValue ( value ))
continue ;
2022-06-24 20:41:00 -05:00
2022-07-05 12:00:18 -05:00
SetXmlPropValue ( objXml , prop . Name , value , recursionLevel - 1 );
}
catch
{
// Ignore errors, sometimes things aren't initialized yet
continue ;
}
2022-06-24 20:41:00 -05:00
}
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 ;
2022-03-03 08:14:05 -06:00
}
private static void CleanUpXmlDoc ()
{
XmlNamespaceManager nsManager = new XmlNamespaceManager ( XmlDoc . NameTable );
2022-06-24 20:41:00 -05:00
var hosts = XmlDoc . DocumentElement . SelectNodes ( "*//Host" , nsManager );
2022-03-03 08:14:05 -06:00
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 );
}
}
}
}
}