jint: Stack overflow exceptions are more likely to happen in Jint than other engines

I am running into stack overflow problem in Jint. I am running React inside Jint. React can have too many nested calls which probably cause this error.

As far as I understand, there are two types of stack overflow. First one is caused by this kind of code:

var count = 0;
function recurse() {
    count++;
    if(count > 100000) return;
    recurse();
    return null; // ensure no tail recursion
}
try {
    count = 0; 
    recurse();
    console.log('Recursed times: more than ' + count);
} catch(err) {
    console.error(err);
    console.log('Recursed times: ' + count);
}

Chrome and V8 based engines (ClearScript) can handle 13955 calls with this code. Firefox can handle 26215 calls. But Jint can only handle somewhere around 730 calls. By the way, this is not a recoverable error in .NET and will immediately crash your application.

However, this is only related to the count of nested calls. I am running a pretty complex application and I haven’t run into this issue yet. Still, I believe it is something to watch out.

The other type of stack overflow is caused by the size of the call stack (I may be wrong). And this is the issue I am running into. When this issue happens, it generates a stack trace:

StackOverflowException: The requested operation caused a stack overflow.
Jint.Collections.StringDictionarySlim`1[TValue]..ctor (System.Int32 capacity) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Collections.HybridDictionary`1[TValue].SwitchToDictionary (Jint.Key key, TValue value) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Collections.HybridDictionary`1[TValue].set_Item (Jint.Key key, TValue value) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Environments.DeclarativeEnvironmentRecord.CreateMutableBindingAndInitialize (Jint.Key name, System.Boolean canBeDeleted, Jint.Native.JsValue value) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.FunctionDeclarationInstantiation (Jint.Native.Function.FunctionInstance functionInstance, Jint.Native.JsValue[] argumentsList) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.FunctionInstance.OrdinaryCallEvaluateBody (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue[] arguments, Jint.Runtime.Environments.ExecutionContext calleeContext) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.ScriptFunctionInstance.Call (Jint.Native.JsValue thisArgument, Jint.Native.JsValue[] arguments) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.Function.FunctionInstance functionInstance, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.ICallable callable, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateCall (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue func, System.Object reference, Esprima.Ast.NodeList`1[Esprima.Ast.Expression]& arguments, System.Boolean tailPosition) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.Call (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintExpression.Evaluate (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintExpressionStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintSwitchBlock.Execute (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue input) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintSwitchStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintFunctionDefinition.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.FunctionInstance.OrdinaryCallEvaluateBody (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue[] arguments, Jint.Runtime.Environments.ExecutionContext calleeContext) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.ScriptFunctionInstance.Call (Jint.Native.JsValue thisArgument, Jint.Native.JsValue[] arguments) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.Function.FunctionInstance functionInstance, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.ICallable callable, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateCall (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue func, System.Object reference, Esprima.Ast.NodeList`1[Esprima.Ast.Expression]& arguments, System.Boolean tailPosition) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.Call (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintExpression.Evaluate (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintExpressionStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintWhileStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintIfStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintFunctionDefinition.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.FunctionInstance.OrdinaryCallEvaluateBody (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue[] arguments, Jint.Runtime.Environments.ExecutionContext calleeContext) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.ScriptFunctionInstance.Call (Jint.Native.JsValue thisArgument, Jint.Native.JsValue[] arguments) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.Function.FunctionInstance functionInstance, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.ICallable callable, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateCall (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue func, System.Object reference, Esprima.Ast.NodeList`1[Esprima.Ast.Expression]& arguments, System.Boolean tailPosition) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.Call (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintExpression.Evaluate (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintExpressionStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintSwitchBlock.Execute (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue input) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintSwitchStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintFunctionDefinition.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.FunctionInstance.OrdinaryCallEvaluateBody (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue[] arguments, Jint.Runtime.Environments.ExecutionContext calleeContext) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.ScriptFunctionInstance.Call (Jint.Native.JsValue thisArgument, Jint.Native.JsValue[] arguments) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.Function.FunctionInstance functionInstance, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.ICallable callable, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateCall (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue func, System.Object reference, Esprima.Ast.NodeList`1[Esprima.Ast.Expression]& arguments, System.Boolean tailPosition) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.Call (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintExpression.Evaluate (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintExpressionStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintWhileStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintBlockStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintIfStatement.ExecuteInternal (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Statements.JintStatement.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintStatementList.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.JintFunctionDefinition.Execute (Jint.Runtime.Interpreter.EvaluationContext context) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.FunctionInstance.OrdinaryCallEvaluateBody (Jint.Runtime.Interpreter.EvaluationContext context, Jint.Native.JsValue[] arguments, Jint.Runtime.Environments.ExecutionContext calleeContext) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Native.Function.ScriptFunctionInstance.Call (Jint.Native.JsValue thisArgument, Jint.Native.JsValue[] arguments) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.Function.FunctionInstance functionInstance, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Engine.Call (Jint.Native.ICallable callable, Jint.Native.JsValue thisObject, Jint.Native.JsValue[] arguments, Jint.Runtime.Interpreter.Expressions.JintExpression expression) (at <3199913b93e24fcd8a9636916a1ace31>:0)
Jint.Runtime.Interpreter.Expressions.JintCallExpression.EvaluateCall (Jint.Runtime.Interpreter.EvaluationContext context, J<message truncated>

I guess this happens because of the objects stored in the stack. To be clear, this does not happen for me in production mode of React, but happens in development. This is because React does a lot more things in development mode. (There is also a possibility that I am making an amateur mistake somewhere.)

I don’t know what action can be taken about this issue. Reporting it here, so that we can discuss.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (9 by maintainers)

Most upvoted comments

Just a heads up here, #1566 brought a new neat feature that should allow you to push stack limits even further (disabled by default).

I think the “easy” wins have been done for this one. I’m closing and we can have a separate new issue if there’s specific real-world use case causing trouble. Thanks to all involved for testing and verifying fixes!

With the latest release I think we could probably close this issue as there’s now test coverage and improvements to recursive calls. Test case shows that plain nested calls to generated functions should now allow 1000 functions in chain.

https://github.com/sebastienros/jint/releases/tag/v3.0.0-beta-2041

What do you think?

Hey folks, you might be pleasantly surprised with latest MyGet release which should be available shortly!

On my side, I’m getting 638 for standalone C# and 266 for Unity now. 😀

If you folks would have time to test latest MyGet release at some point, that would be lovely. I’ve tried to improve stack handling to allow deeper call chains - it’s not a silver bullet though.

@lahma I was running it inside a standalone C# project. I am using Jint inside Unity as well and problem is more prominent there. But I haven’t measured the max recursion depth there.

Note that the max recursion depth was not always so low. It was low on the version I tried (main branch at the time I created the issue). So maybe it became lower after that.