|
@@ -1,11 +1,19 @@
|
|
|
#if !NETFRAMEWORK
|
|
|
|
|
|
using System.Text;
|
|
|
+using Jint.Runtime;
|
|
|
|
|
|
namespace Jint.Tests.Runtime;
|
|
|
|
|
|
public class EngineLimitTests
|
|
|
{
|
|
|
+
|
|
|
+#if RELEASE
|
|
|
+ const int FunctionNestingCount = 960;
|
|
|
+#else
|
|
|
+ const int FunctionNestingCount = 520;
|
|
|
+#endif
|
|
|
+
|
|
|
[Fact]
|
|
|
public void ShouldAllowReasonableCallStackDepth()
|
|
|
{
|
|
@@ -15,24 +23,61 @@ public class EngineLimitTests
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
-#if RELEASE
|
|
|
- const int FunctionNestingCount = 960;
|
|
|
-#else
|
|
|
- const int FunctionNestingCount = 520;
|
|
|
-#endif
|
|
|
+ var script = GenerateCallTree(FunctionNestingCount);
|
|
|
|
|
|
- // generate call tree
|
|
|
+ var engine = new Engine();
|
|
|
+ engine.Execute(script);
|
|
|
+ Assert.Equal(123, engine.Evaluate("func1(123);").AsNumber());
|
|
|
+ Assert.Equal(FunctionNestingCount, engine.Evaluate("x").AsNumber());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ShouldNotStackoverflowWhenStackGuardEnable()
|
|
|
+ {
|
|
|
+ // Can be more than actual dotnet stacktrace count, It does not hit stackoverflow anymore.
|
|
|
+ int functionNestingCount = FunctionNestingCount * 2;
|
|
|
+
|
|
|
+ var script = GenerateCallTree(functionNestingCount);
|
|
|
+
|
|
|
+ var engine = new Engine(option => option.Constraints.MaxExecutionStackCount = functionNestingCount);
|
|
|
+ engine.Execute(script);
|
|
|
+ Assert.Equal(123, engine.Evaluate("func1(123);").AsNumber());
|
|
|
+ Assert.Equal(functionNestingCount, engine.Evaluate("x").AsNumber());
|
|
|
+ }
|
|
|
+
|
|
|
+ [Fact]
|
|
|
+ public void ShouldThrowJavascriptExceptionWhenStackGuardExceed()
|
|
|
+ {
|
|
|
+ // Can be more than actual dotnet stacktrace count, It does not hit stackoverflow anymore.
|
|
|
+ int functionNestingCount = FunctionNestingCount * 2;
|
|
|
+
|
|
|
+ var script = GenerateCallTree(functionNestingCount);
|
|
|
+
|
|
|
+ var engine = new Engine(option => option.Constraints.MaxExecutionStackCount = 500);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ engine.Execute(script);
|
|
|
+ engine.Evaluate("func1(123);");
|
|
|
+ }
|
|
|
+ catch (JavaScriptException jsException)
|
|
|
+ {
|
|
|
+ Assert.Equal("Maximum call stack size exceeded", jsException.Message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private string GenerateCallTree(int functionNestingCount)
|
|
|
+ {
|
|
|
var sb = new StringBuilder();
|
|
|
- sb.AppendLine("var x = 10;");
|
|
|
+ sb.AppendLine("var x = 1;");
|
|
|
sb.AppendLine();
|
|
|
- for (var i = 1; i <= FunctionNestingCount; ++i)
|
|
|
+ for (var i = 1; i <= functionNestingCount; ++i)
|
|
|
{
|
|
|
sb.Append("function func").Append(i).Append("(func").Append(i).AppendLine("Param) {");
|
|
|
sb.Append(" ");
|
|
|
- if (i != FunctionNestingCount)
|
|
|
+ if (i != functionNestingCount)
|
|
|
{
|
|
|
// just to create a bit more nesting add some constructs
|
|
|
- sb.Append("return x++ > 1 ? func").Append(i + 1).Append("(func").Append(i).AppendLine("Param): undefined;");
|
|
|
+ sb.Append("return x++ >= 1 ? func").Append(i + 1).Append("(func").Append(i).AppendLine("Param): undefined;");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -43,10 +88,7 @@ public class EngineLimitTests
|
|
|
sb.AppendLine("}");
|
|
|
sb.AppendLine();
|
|
|
}
|
|
|
-
|
|
|
- var engine = new Engine();
|
|
|
- engine.Execute(sb.ToString());
|
|
|
- Assert.Equal(123, engine.Evaluate("func1(123);").AsNumber());
|
|
|
+ return sb.ToString();
|
|
|
}
|
|
|
}
|
|
|
|