Browse Source

Fix call stack pop to account for stack being reset (#1243)

Marko Lahma 3 years ago
parent
commit
e9567b980b
2 changed files with 48 additions and 1 deletions
  1. 43 0
      Jint.Tests/Runtime/ErrorTests.cs
  2. 5 1
      Jint/Engine.cs

+ 43 - 0
Jint.Tests/Runtime/ErrorTests.cs

@@ -379,6 +379,49 @@ try {
             Assert.Equal(type, engine.Evaluate("o.constructor.name").AsString());
             Assert.Equal(type, engine.Evaluate("o.constructor.name").AsString());
         }
         }
 
 
+        [Fact]
+        public void CallStackWorksWithRecursiveCalls()
+        {
+            static ParserOptions CreateParserOptions(string filePath)
+            {
+                return new ParserOptions(filePath)
+                {
+                    AdaptRegexp = true,
+                    Tolerant = true
+                };
+            }
+
+            var e = Assert.Throws<JavaScriptException>(() =>
+            {
+                var engine = new Engine();
+
+                engine.SetValue("executeFile", (Action<string>) (path =>
+                {
+                    var content = path switch
+                    {
+                        "first-file.js" => @"num = num * 3;
+executeFile(""second-file.js"");",
+                        "second-file.js" => @"// Intentionally making a mistake in the variable name
+nuм -= 3;",
+                        _ => throw new FileNotFoundException($"File '{path}' not exist.", path)
+                    };
+                    engine.Execute(content, CreateParserOptions(path));
+                }));
+                engine.Execute(
+                    @"var num = 5;
+executeFile(""first-file.js"");",
+                    CreateParserOptions("main-file.js")
+                );
+            });
+
+            Assert.Equal("nuм is not defined", e.Message);
+
+            const string Expected = @"   at delegate second-file.js:2:1
+   at delegate first-file.js:2:1
+   at main-file.js:2:1";
+            EqualIgnoringNewLineDifferences(Expected, e.JavaScriptStackTrace);
+        }
+
         private static void EqualIgnoringNewLineDifferences(string expected, string actual)
         private static void EqualIgnoringNewLineDifferences(string expected, string actual)
         {
         {
             expected = expected.Replace("\r\n", "\n");
             expected = expected.Replace("\r\n", "\n");

+ 5 - 1
Jint/Engine.cs

@@ -1371,7 +1371,11 @@ namespace Jint
             }
             }
             finally
             finally
             {
             {
-                CallStack.Pop();
+                // if call stack was reset due to recursive call to engine or similar, we might not have it anymore
+                if (CallStack.Count > 0)
+                {
+                    CallStack.Pop();
+                }
             }
             }
 
 
             return result;
             return result;