Browse Source

Add `Options.Constraints.PromiseTimeout` to control timeout for `DisposeHint.Async` and `JintAwaitExpression` (#2150)

---------

Co-authored-by: liuyan <[email protected]>
Rocky LIU Yan 4 days ago
parent
commit
f58fc1f128

+ 27 - 3
Jint.Tests/Runtime/AsyncTests.cs

@@ -42,6 +42,30 @@ public class AsyncTests
         Assert.Equal(AsyncTestClass.TestString, result);
         Assert.Equal(AsyncTestClass.TestString, result);
     }
     }
 
 
+    [Fact]
+    public void ShouldUnwrapPromiseWithCustomTimeout()
+    {
+        Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop);
+        engine.SetValue("asyncTestClass", new AsyncTestClass());
+        var result = engine.Evaluate("asyncTestClass.ReturnDelayedTaskAsync().then(x=>x)");
+        result = result.UnwrapIfPromise(TimeSpan.FromMilliseconds(200));
+        Assert.Equal(AsyncTestClass.TestString, result);
+    }
+
+    [Fact]
+    public void ShouldAwaitUnwrapPromiseWithCustomTimeout()
+    {
+        Engine engine = new(options => { options.ExperimentalFeatures = ExperimentalFeature.TaskInterop; options.Constraints.PromiseTimeout = TimeSpan.FromMilliseconds(500); });
+        engine.SetValue("asyncTestClass", new AsyncTestClass());
+        engine.Execute(""" 
+        async function test() {
+            return await asyncTestClass.ReturnDelayedTaskAsync();
+        }
+        """);
+        var result = engine.Invoke("test").UnwrapIfPromise();
+        Assert.Equal(AsyncTestClass.TestString, result);
+    }
+
     [Fact]
     [Fact]
     public void ShouldReturnedCompletedTaskConvertedToPromiseInJS()
     public void ShouldReturnedCompletedTaskConvertedToPromiseInJS()
     {
     {
@@ -230,7 +254,7 @@ public class AsyncTests
 
 
         Assert.Equal(expected, log.Select(x => x.AsString()).ToArray());
         Assert.Equal(expected, log.Select(x => x.AsString()).ToArray());
     }
     }
-    
+
     [Fact]
     [Fact]
     public void ShouldPromiseBeResolved()
     public void ShouldPromiseBeResolved()
     {
     {
@@ -240,7 +264,7 @@ public class AsyncTests
         {
         {
             log.Add(str);
             log.Add(str);
         });
         });
-        
+
         const string Script = """
         const string Script = """
           async function main() {
           async function main() {
             return new Promise(function (resolve) {
             return new Promise(function (resolve) {
@@ -268,7 +292,7 @@ public class AsyncTests
             {
             {
                 Task.Delay(ms).ContinueWith(_ => action());
                 Task.Delay(ms).ContinueWith(_ => action());
             });
             });
-        
+
         const string Script = """
         const string Script = """
           var delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
           var delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
           async function main() {
           async function main() {

+ 1 - 1
Jint/Native/Disposable/DisposeCapability.cs

@@ -87,7 +87,7 @@ internal sealed class DisposeCapability
                         hasAwaited = true;
                         hasAwaited = true;
                         try
                         try
                         {
                         {
-                            result = result.UnwrapIfPromise();
+                            result = result.UnwrapIfPromise(_engine.Options.Constraints.PromiseTimeout);
                         }
                         }
                         catch (JavaScriptException e)
                         catch (JavaScriptException e)
                         {
                         {

+ 6 - 0
Jint/Options.cs

@@ -431,6 +431,12 @@ public class Options
         /// </summary>
         /// </summary>
         public TimeSpan RegexTimeout { get; set; } = TimeSpan.FromSeconds(10);
         public TimeSpan RegexTimeout { get; set; } = TimeSpan.FromSeconds(10);
 
 
+        /// <summary>
+        /// Maximum time allowed for unwrapping a Promise and getting its resolved/rejected value.
+        /// Defaults to 10 seconds.
+        /// </summary>
+        public TimeSpan PromiseTimeout { get; set; } = TimeSpan.FromSeconds(10);
+
         /// <summary>
         /// <summary>
         /// The maximum size for JavaScript array, defaults to <see cref="uint.MaxValue"/>.
         /// The maximum size for JavaScript array, defaults to <see cref="uint.MaxValue"/>.
         /// </summary>
         /// </summary>

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintAwaitExpression.cs

@@ -34,7 +34,7 @@ internal sealed class JintAwaitExpression : JintExpression
                 value = promiseInstance;
                 value = promiseInstance;
             }
             }
 
 
-            return value.UnwrapIfPromise();
+            return value.UnwrapIfPromise(engine.Options.Constraints.PromiseTimeout);
         }
         }
         catch (PromiseRejectedException e)
         catch (PromiseRejectedException e)
         {
         {