Forráskód Böngészése

Handle recursive engine invocations (#837)

Marko Lahma 4 éve
szülő
commit
f212d3fa77

+ 1 - 1
Jint.Tests.Test262/Test262Test.cs

@@ -100,7 +100,7 @@ namespace Jint.Tests.Test262
                 var parser = new JavaScriptParser(args.At(0).AsString(), options);
                 var script = parser.ParseScript(strict);
 
-                var value = engine.Execute(script, false).GetCompletionValue();
+                var value = engine.Execute(script).GetCompletionValue();
                 
                 return value;
             }), true, true, true));

+ 13 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -2934,6 +2934,19 @@ x.test = {
             Assert.Equal(1, Convert.ToInt32(engine2.GetValue("x").ToObject()));
         }
 
+        [Fact]
+        public void RecursiveCallStack()
+        {
+            var engine = new Engine();
+            Func<string, object> evaluateCode = code => engine.Execute(code).GetCompletionValue();
+            var evaluateCodeValue = JsValue.FromObject(engine, evaluateCode);
+
+            engine.SetValue("evaluateCode", evaluateCodeValue);
+            var result = (int) engine.Execute(@"evaluateCode('678 + 711')").GetCompletionValue().AsNumber();
+
+            Assert.Equal(1389, result);
+        }
+
         private class Wrapper
         {
             public Testificate Test { get; set; }

+ 16 - 13
Jint/Engine.cs

@@ -349,17 +349,8 @@ namespace Jint
 
         public Engine Execute(Script script)
         {
-            return Execute(script, true);
-        }
-
-        internal Engine Execute(Script script, bool resetState)
-        {
-            if (resetState)
-            {
-                ResetConstraints();
-                ResetLastStatement();
-                ResetCallStack();
-            }
+            ResetConstraints();
+            ResetLastStatement();
 
             using (new StrictModeScope(_isStrict || script.Strict))
             {
@@ -368,11 +359,23 @@ namespace Jint
                     GlobalEnvironment);
 
                 var list = new JintStatementList(this, null, script.Body);
-                
-                var result = list.Execute();
+
+                Completion result;
+                try
+                {
+                    result = list.Execute();
+                }
+                catch
+                {
+                    // unhandled exception
+                    ResetCallStack();
+                    throw;
+                }
+
                 if (result.Type == CompletionType.Throw)
                 {
                     var ex = new JavaScriptException(result.GetValueOrDefault()).SetCallstack(this, result.Location);
+                    ResetCallStack();
                     throw ex;
                 }
 

+ 2 - 0
Jint/Runtime/CallStack/JintCallStack.cs

@@ -60,6 +60,8 @@ namespace Jint.Runtime.CallStack
             return item;
         }
 
+        public int Count => _stack._size;
+
         public void Clear()
         {
             _stack.Clear();