From 00d6a6e8b6ab6ffe65b66b4c7296dbb14eebe5f6 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Fri, 5 Apr 2024 17:17:10 +0300 Subject: [PATCH] Make task to promise wrapping an opt-in experimental feature (#1830) --- Jint.Tests/Runtime/AsyncTests.cs | 14 ++++++------- Jint/Options.cs | 7 ++++++- .../Runtime/Interop/DefaultObjectConverter.cs | 21 +++++++++++-------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Jint.Tests/Runtime/AsyncTests.cs b/Jint.Tests/Runtime/AsyncTests.cs index 4d98c8e280..4599961345 100644 --- a/Jint.Tests/Runtime/AsyncTests.cs +++ b/Jint.Tests/Runtime/AsyncTests.cs @@ -33,7 +33,7 @@ static async Task Callable() [Fact] public void ShouldReturnedTaskConvertedToPromiseInJS() { - Engine engine = new(); + 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(); @@ -43,7 +43,7 @@ public void ShouldReturnedTaskConvertedToPromiseInJS() [Fact] public void ShouldReturnedCompletedTaskConvertedToPromiseInJS() { - Engine engine = new(); + Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop); engine.SetValue("asyncTestClass", new AsyncTestClass()); var result = engine.Evaluate("asyncTestClass.ReturnCompletedTask().then(x=>x)"); result = result.UnwrapIfPromise(); @@ -53,7 +53,7 @@ public void ShouldReturnedCompletedTaskConvertedToPromiseInJS() [Fact] public void ShouldTaskCatchWhenCancelled() { - Engine engine = new(); + Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop); CancellationTokenSource cancel = new(); cancel.Cancel(); engine.SetValue("token", cancel.Token); @@ -70,7 +70,7 @@ static async Task Callable(CancellationToken token) [Fact] public void ShouldReturnedTaskCatchWhenCancelled() { - Engine engine = new(); + Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop); CancellationTokenSource cancel = new(); cancel.Cancel(); engine.SetValue("token", cancel.Token); @@ -83,7 +83,7 @@ public void ShouldReturnedTaskCatchWhenCancelled() [Fact] public void ShouldTaskCatchWhenThrowError() { - Engine engine = new(); + Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop); engine.SetValue("callable", Callable); engine.SetValue("assert", new Action(Assert.True)); var result = engine.Evaluate("callable().then(_ => assert(false)).catch(_ => assert(true))"); @@ -98,7 +98,7 @@ static async Task Callable() [Fact] public void ShouldReturnedTaskCatchWhenThrowError() { - Engine engine = new(); + Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop); engine.SetValue("asyncTestClass", new AsyncTestClass()); engine.SetValue("assert", new Action(Assert.True)); var result = engine.Evaluate("asyncTestClass.ThrowAfterDelayAsync().then(_ => assert(false)).catch(_ => assert(true))"); @@ -109,7 +109,7 @@ public void ShouldReturnedTaskCatchWhenThrowError() public void ShouldTaskAwaitCurrentStack() { //https://github.com/sebastienros/jint/issues/514#issuecomment-1507127509 - Engine engine = new(); + Engine engine = new(options => options.ExperimentalFeatures = ExperimentalFeature.TaskInterop); AsyncTestClass asyncTestClass = new(); engine.SetValue("myAsyncMethod", new Func(async () => diff --git a/Jint/Options.cs b/Jint/Options.cs index b1079d1232..9eb1d6584e 100644 --- a/Jint/Options.cs +++ b/Jint/Options.cs @@ -481,8 +481,13 @@ public enum ExperimentalFeature /// Generators = 1, + /// + /// Wrapping tasks to promises + /// + TaskInterop = 2, + /// /// All coercion rules enabled. /// - All = Generators + All = Generators | TaskInterop } diff --git a/Jint/Runtime/Interop/DefaultObjectConverter.cs b/Jint/Runtime/Interop/DefaultObjectConverter.cs index 2b0be92e3a..295af89702 100644 --- a/Jint/Runtime/Interop/DefaultObjectConverter.cs +++ b/Jint/Runtime/Interop/DefaultObjectConverter.cs @@ -72,19 +72,22 @@ public static bool TryConvert(Engine engine, object value, Type? type, [NotNullW return result is not null; } - if (value is Task task) + if ((engine.Options.ExperimentalFeatures & ExperimentalFeature.TaskInterop) != ExperimentalFeature.None) { - result = JsValue.ConvertAwaitableToPromise(engine, task); - return result is not null; - } + if (value is Task task) + { + result = JsValue.ConvertAwaitableToPromise(engine, task); + return result is not null; + } #if NETSTANDARD2_1_OR_GREATER || NETCOREAPP - if (value is ValueTask valueTask) - { - result = JsValue.ConvertAwaitableToPromise(engine, valueTask); - return result is not null; - } + if (value is ValueTask valueTask) + { + result = JsValue.ConvertAwaitableToPromise(engine, valueTask); + return result is not null; + } #endif + } #if NET8_0_OR_GREATER if (value is System.Text.Json.Nodes.JsonValue jsonValue)