diff --git a/Jint.Tests/Runtime/AsyncTests.cs b/Jint.Tests/Runtime/AsyncTests.cs index da31e21332..fe350fb7a6 100644 --- a/Jint.Tests/Runtime/AsyncTests.cs +++ b/Jint.Tests/Runtime/AsyncTests.cs @@ -42,6 +42,30 @@ public void ShouldReturnedTaskConvertedToPromiseInJS() 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] public void ShouldReturnedCompletedTaskConvertedToPromiseInJS() { @@ -230,7 +254,7 @@ async function foo(name) { Assert.Equal(expected, log.Select(x => x.AsString()).ToArray()); } - + [Fact] public void ShouldPromiseBeResolved() { @@ -240,7 +264,7 @@ public void ShouldPromiseBeResolved() { log.Add(str); }); - + const string Script = """ async function main() { return new Promise(function (resolve) { @@ -268,7 +292,7 @@ public void ShouldPromiseBeResolved2() { Task.Delay(ms).ContinueWith(_ => action()); }); - + const string Script = """ var delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); async function main() { diff --git a/Jint/Native/Disposable/DisposeCapability.cs b/Jint/Native/Disposable/DisposeCapability.cs index e358e70daf..66984b1c0f 100644 --- a/Jint/Native/Disposable/DisposeCapability.cs +++ b/Jint/Native/Disposable/DisposeCapability.cs @@ -87,7 +87,7 @@ public Completion DisposeResources(Completion c) hasAwaited = true; try { - result = result.UnwrapIfPromise(); + result = result.UnwrapIfPromise(_engine.Options.Constraints.PromiseTimeout); } catch (JavaScriptException e) { diff --git a/Jint/Options.cs b/Jint/Options.cs index 5e30581841..2d69eb57eb 100644 --- a/Jint/Options.cs +++ b/Jint/Options.cs @@ -431,6 +431,12 @@ public class ConstraintOptions /// public TimeSpan RegexTimeout { get; set; } = TimeSpan.FromSeconds(10); + /// + /// Maximum time allowed for unwrapping a Promise and getting its resolved/rejected value. + /// Defaults to 10 seconds. + /// + public TimeSpan PromiseTimeout { get; set; } = TimeSpan.FromSeconds(10); + /// /// The maximum size for JavaScript array, defaults to . /// diff --git a/Jint/Runtime/Interpreter/Expressions/JintAwaitExpression.cs b/Jint/Runtime/Interpreter/Expressions/JintAwaitExpression.cs index 22f5c047c8..1562873e01 100644 --- a/Jint/Runtime/Interpreter/Expressions/JintAwaitExpression.cs +++ b/Jint/Runtime/Interpreter/Expressions/JintAwaitExpression.cs @@ -34,7 +34,7 @@ protected override object EvaluateInternal(EvaluationContext context) value = promiseInstance; } - return value.UnwrapIfPromise(); + return value.UnwrapIfPromise(engine.Options.Constraints.PromiseTimeout); } catch (PromiseRejectedException e) {