Browse Source

Fix resolve async promise timeout issue in Jint from 4.1.0 to 4.4.1 (#1250)

pull/1254/head
Noah 9 months ago
committed by GitHub
parent
commit
856709e667
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Internal/JsonMapper.cs
  2. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs
  3. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptOptions.cs
  4. 2
      backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj
  5. 5
      backend/src/Squidex/appsettings.json
  6. 27
      backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs

5
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/Internal/JsonMapper.cs

@ -109,6 +109,11 @@ public static class JsonMapper
return number;
}
if (value.IsPromise())
{
return Map(value.UnwrapIfPromise());
}
if (value is JsArray a)
{
var result = new JsonArray((int)a.Length);

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs

@ -29,6 +29,7 @@ public sealed class JintScriptEngine(IMemoryCache cache, IOptions<JintScriptOpti
private readonly CacheParser parser = new CacheParser(cache);
private readonly TimeSpan timeoutScript = options.Value.TimeoutScript;
private readonly TimeSpan timeoutExecution = options.Value.TimeoutExecution;
private readonly TimeSpan timeoutPromise = options.Value.TimeoutPromise;
public async Task<JsonValue> ExecuteAsync(ScriptVars vars, string script, ScriptOptions options = default,
CancellationToken ct = default)
@ -150,6 +151,7 @@ public sealed class JintScriptEngine(IMemoryCache cache, IOptions<JintScriptOpti
if (!Debugger.IsAttached)
{
engineOptions.Constraints.PromiseTimeout = timeoutPromise;
engineOptions.TimeoutInterval(timeoutScript);
engineOptions.CancellationToken(ct);
}

2
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptOptions.cs

@ -12,4 +12,6 @@ public sealed class JintScriptOptions
public TimeSpan TimeoutScript { get; set; } = TimeSpan.FromMilliseconds(200);
public TimeSpan TimeoutExecution { get; set; } = TimeSpan.FromMilliseconds(4000);
public TimeSpan TimeoutPromise { get; set; } = TimeSpan.FromMilliseconds(4000);
}

2
backend/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj

@ -20,7 +20,7 @@
<ItemGroup>
<PackageReference Include="Fluid.Core" Version="2.12.0" />
<PackageReference Include="GeoJSON.Net" Version="1.4.1" />
<PackageReference Include="Jint" Version="4.1.0" />
<PackageReference Include="Jint" Version="4.4.1" />
<PackageReference Include="Meziantou.Analyzer" Version="2.0.179">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

5
backend/src/Squidex/appsettings.json

@ -126,7 +126,10 @@
"timeoutExecution": "00:00:04",
// The timeout for the synchronous part of the script.
"timeoutScript": "00:00:00.200"
"timeoutScript": "00:00:00.200",
// The timeout for the asynchronous promise of the script.
"timeoutPromise": "00:00:04"
},
"languages": {

27
backend/tests/Squidex.Domain.Apps.Core.Tests/Operations/Scripting/JintScriptEngineTests.cs

@ -59,6 +59,7 @@ public class JintScriptEngineTests : IClassFixture<TranslationsFixture>
{
TimeoutScript = TimeSpan.FromSeconds(2),
TimeoutExecution = TimeSpan.FromSeconds(10),
TimeoutPromise = TimeSpan.FromSeconds(8),
}),
extensions);
}
@ -723,4 +724,30 @@ public class JintScriptEngineTests : IClassFixture<TranslationsFixture>
Assert.Equal(42.0, result.Value);
}
[Fact]
public async Task Should_run_with_blocking_timeout_promises()
{
const string script = @"
function promiseMethod() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 1000)
});
}
// Jint 4.1.0 blocking (if you remove 'async', the timeout will not occur.)
async function asyncMethod() {
return promiseMethod();
}
(async () => {
await asyncMethod();
complete()
})()
";
await Assert.ThrowsAsync<ValidationException>(() => sut.ExecuteAsync(new ScriptVars(), script));
}
}

Loading…
Cancel
Save