You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was working on catching recursion exceptions in case my users input endless recursion code and I think the engine is behaving a little odd. It could be that my understanding of how it should work is wrong but I was expecting invoking a function would reset the recursion limit per call and not carry over. This wasn't really the case. I I call function foo using invoke and it reaches the limit of recursion it will stop as expected. If I call foo again however it will throw out immediately as it recurses and not after limit is reached. This does not happen with Execute. I also noticed that you get an even weirder interaction if you call Execute after Invoke. Then you throw immediately. I also noticed that invoke apparently takes one more recursion to reach limit than Execute.
I believe my example code illustrate everything best. I've made a bunch of different combinations of scenarios mixing Execute and Invoke when it comes to recursion error handling.
Code example
Sorry if the code is a little bit messy but I hope this will show more clearly what I mean! <3
privatestaticvoidTestRecursion(){voidExecuteAction(Engineengine)=>engine.Execute("recursion()");voidInvokeAction(Engineengine)=>engine.Invoke("recursion");List<int>test1=RunLoop(CreateEngine(),ExecuteAction);// [6, 6, 6, 6, 6]List<int>test2=RunLoop(CreateEngine(),InvokeAction);// [7, 1, 1, 1, 1]Enginee1=CreateEngine();List<int>test3_1=RunLoop(e1,ExecuteAction);// list = [6, 6, 6, 6, 6]List<int>test3_2=RunLoop(e1,InvokeAction);// list = [7, 1, 1, 1, 1]Enginee2=CreateEngine();List<int>test4_1=RunLoop(e2,InvokeAction);// list = [7, 1, 1, 1, 1]List<int>test4_2=RunLoop(e2,ExecuteAction);// list = [0, 6, 6, 6, 6]Enginee3=CreateEngine();List<int>test5_1=RunLoop(e3,InvokeAction);// list = [7, 1, 1, 1, 1]List<int>test5_2=RunLoop(e3,ExecuteAction);// list = [0, 6, 6, 6, 6]List<int>test5_3=RunLoop(e3,InvokeAction);// list = [7, 1, 1, 1, 1]Enginee4=CreateEngine();List<int>test6_1=RunLoop(e4,InvokeAction);// list = [7, 1, 1, 1, 1]List<int>test6_2=RunLoop(e4,InvokeAction);// list = [1, 1, 1, 1, 1]}privatestaticEngineCreateEngine(){Engineengine=new(options =>options.LimitRecursion(5));returnengine.Execute(@" var num = 0; function recursion() { num++; recursion(num); } ");}privatestaticList<int>RunLoop(Engineengine,Action<Engine>engineAction){List<int>results=new();for(inti=0;i<5;i++){try{engine.SetValue("num",0);engineAction.Invoke(engine);}catch(RecursionDepthOverflowException){results.Add((int)engine.GetValue("num").AsNumber());}}returnresults;}
Expected behavior
I'm not entirely sure what the underlying intention is regarding invoke and execute in relation to recursion but my own expectation was that I would be able to invoke the same function multiple times and the recursion limit would be reset for each call. My expectation could be wrong of course :3 For my own purposes I can just use Execute in favor of Invoke to call my function and have the recursion be reset for each call but I'm curious as to why they would differ!
I'm see quite constant behavior of always having [6, 6, 6, 6, 6] for Execute and [7, 7, 7, 7, 7] for Invoke, there's a stack frame difference because direct invoke is skipping one layer. With #1714 test suite passes.
Version: 3.0.0-beta
Description
I was working on catching recursion exceptions in case my users input endless recursion code and I think the engine is behaving a little odd. It could be that my understanding of how it should work is wrong but I was expecting invoking a function would reset the recursion limit per call and not carry over. This wasn't really the case. I I call function foo using invoke and it reaches the limit of recursion it will stop as expected. If I call foo again however it will throw out immediately as it recurses and not after limit is reached. This does not happen with Execute. I also noticed that you get an even weirder interaction if you call Execute after Invoke. Then you throw immediately. I also noticed that invoke apparently takes one more recursion to reach limit than Execute.
I believe my example code illustrate everything best. I've made a bunch of different combinations of scenarios mixing Execute and Invoke when it comes to recursion error handling.
Code example
Sorry if the code is a little bit messy but I hope this will show more clearly what I mean! <3
Expected behavior
I'm not entirely sure what the underlying intention is regarding invoke and execute in relation to recursion but my own expectation was that I would be able to invoke the same function multiple times and the recursion limit would be reset for each call. My expectation could be wrong of course :3 For my own purposes I can just use Execute in favor of Invoke to call my function and have the recursion be reset for each call but I'm curious as to why they would differ!
Result
The text was updated successfully, but these errors were encountered: