moonsharp icon indicating copy to clipboard operation
moonsharp copied to clipboard

System.IndexOutOfRangeException

Open wledfor2 opened this issue 8 years ago • 1 comments

I was writing a wrapper around NUnit's assert functions, I encountered a strange issue. When running the following code:

using System;
using MoonSharp.Interpreter;
using NUnit.Framework;

namespace Test {

	class Test {

		public class TestClass {
			
			//simple wrapper around NUnit.Framework.Assert.Catch
			public DynValue Catch(DynValue testDelegate, DynValue message) {
				Exception e = Assert.Catch(() => testDelegate.Function.Call(), message.CastToString());
				return DynValue.NewTuple(DynValue.NewString(e.GetType().Name), DynValue.NewString(e.Message));

			}

		}

		public static void Main(string[] args) {

			try {

				UserData.RegisterType<TestClass>();
				Script s = new Script();
				s.Globals["Assert"] = UserData.Create(new TestClass());
				s.DoString(@"

					-- does not throw, because function argument throws
					Assert:Catch(

						-- AssertionException bubbles up
						function()

							-- throws AssertionException, because function argument does not throw
							Assert:Catch(

								-- does not throw
								function()
								end

							)

						end

					)

				");

			} catch (InterpreterException e) {

				Console.WriteLine(e.DecoratedMessage);

			}
		}
	}
}

The following exception is produced:

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at MoonSharp.Interpreter.Execution.VM.Processor.AssignLocal(SymbolRef symref, DynValue value) in src\MoonSharp.Interpreter\Execution\VM\Processor\Processor_InstructionLoop.cs:line 358
   at MoonSharp.Interpreter.Execution.VM.Processor.ExecStoreLcl(Instruction i) in src\MoonSharp.Interpreter\Execution\VM\Processor\Processor_InstructionLoop.cs:line 370
   at MoonSharp.Interpreter.Execution.VM.Processor.Processing_Loop(Int32 instructionPtr) in src\MoonSharp.Interpreter\Execution\VM\Processor\Processor_InstructionLoop.cs:line 210
   at MoonSharp.Interpreter.Execution.VM.Processor.Call(DynValue function, DynValue[] args) in src\MoonSharp.Interpreter\Execution\VM\Processor\Processor.cs:line 67
   at MoonSharp.Interpreter.Script.Call(DynValue function, DynValue[] args) in src\MoonSharp.Interpreter\Script.cs:line 483
   at MoonSharp.Interpreter.Script.Call(DynValue function) in src\MoonSharp.Interpreter\Script.cs:line 442
   at MoonSharp.Interpreter.Script.DoString(String code, Table globalContext, String codeFriendlyName) in src\MoonSharp.Interpreter\Script.cs:line 331
   at Test.Test.Main(String[] args) in Program.cs:line 29

When changing the Lua code to this, it works as expected:

Assert:Catch(function()
	Assert:Catch(function()
	end)
end)

or

return Assert:Catch(function()
	Assert:Catch(function()
	end)
end)

and accept return values from DoString, the results are as expected.

wledfor2 avatar Oct 15 '17 13:10 wledfor2

The issue isn't just NUnit. It happens when any exception but ScriptRuntimeException is thrown.

//this works
public DynValue Catch(DynValue testDelegate, DynValue message) {

	Exception e = null;

	try {

		testDelegate.Function.Call();

	} catch(Exception ex) {

		e = ex;

	}

	if (e == null) {

		throw new ScriptRuntimeException(message.CastToString());

	}

	return DynValue.NewTuple(DynValue.NewString(e.GetType().Name), DynValue.NewString(e.Message));

}
//this does not work
public DynValue Catch(DynValue testDelegate, DynValue message) {

	Exception e = null;

	try {

		testDelegate.Function.Call();

	} catch(Exception ex) {

		e = ex;

	}

	if (e == null) {

		throw new Exception(message.CastToString());

	}

	return DynValue.NewTuple(DynValue.NewString(e.GetType().Name), DynValue.NewString(e.Message));

}

I'm not sure what's going on here.

wledfor2 avatar Oct 15 '17 19:10 wledfor2