Skip to content

Commit b374561

Browse files
committed
In JavaScriptEngineSwitcher.Jint added a ability to interrupt execution of the script
1 parent bfe8fa0 commit b374561

File tree

6 files changed

+108
-16
lines changed

6 files changed

+108
-16
lines changed

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"sdk": {
3-
"version": "3.1.301"
3+
"version": "3.1.302"
44
}
55
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System.Threading;
2+
3+
using IOriginalConstraint = Jint.IConstraint;
4+
5+
namespace JavaScriptEngineSwitcher.Jint
6+
{
7+
internal sealed class CustomCancellationConstraint : IOriginalConstraint
8+
{
9+
private CancellationToken _cancellationToken;
10+
11+
12+
public CustomCancellationConstraint(CancellationToken cancellationToken)
13+
{
14+
_cancellationToken = cancellationToken;
15+
}
16+
17+
18+
public void Check()
19+
{
20+
if (_cancellationToken.IsCancellationRequested)
21+
{
22+
throw new ScriptExecutionCanceledException();
23+
}
24+
}
25+
26+
public void Reset(CancellationToken cancellationToken)
27+
{
28+
_cancellationToken = cancellationToken;
29+
}
30+
31+
public void Reset()
32+
{ }
33+
}
34+
}

src/JavaScriptEngineSwitcher.Jint/JavaScriptEngineSwitcher.Jint.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<Description>JavaScriptEngineSwitcher.Jint contains adapter `JintJsEngine` (wrapper for the Jint JavaScript Engine (http://github.com/sebastienros/jint) version 3.0.0 Beta 1828).</Description>
1414
<PackageIcon>icon.png</PackageIcon>
1515
<PackageTags>JavaScriptEngineSwitcher;JavaScript;ECMAScript;Jint</PackageTags>
16-
<PackageReleaseNotes>Jint was updated to version 3.0.0 Beta 1828.</PackageReleaseNotes>
16+
<PackageReleaseNotes>Added a ability to interrupt execution of the script.</PackageReleaseNotes>
1717
</PropertyGroup>
1818

1919
<Import Project="../../build/common.props" />

src/JavaScriptEngineSwitcher.Jint/JintJsEngine.cs

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Text;
3+
using System.Threading;
34

45
using Jint;
56
using IOriginalPrimitiveInstance = Jint.Native.IPrimitiveInstance;
@@ -27,6 +28,7 @@
2728

2829
using CoreStrings = JavaScriptEngineSwitcher.Core.Resources.Strings;
2930
using WrapperCompilationException = JavaScriptEngineSwitcher.Core.JsCompilationException;
31+
using WrapperInterruptedException = JavaScriptEngineSwitcher.Core.JsInterruptedException;
3032
using WrapperRuntimeException = JavaScriptEngineSwitcher.Core.JsRuntimeException;
3133
using WrapperTimeoutException = JavaScriptEngineSwitcher.Core.JsTimeoutException;
3234
using WrapperUsageException = JavaScriptEngineSwitcher.Core.JsUsageException;
@@ -53,6 +55,16 @@ public sealed class JintJsEngine : JsEngineBase
5355
/// </summary>
5456
private OriginalEngine _jsEngine;
5557

58+
/// <summary>
59+
/// Token source for canceling of script execution
60+
/// </summary>
61+
private CancellationTokenSource _cancellationTokenSource;
62+
63+
/// <summary>
64+
/// Constraint for canceling of script execution
65+
/// </summary>
66+
private CustomCancellationConstraint _cancellationConstraint;
67+
5668
/// <summary>
5769
/// Synchronizer of code execution
5870
/// </summary>
@@ -78,13 +90,17 @@ public JintJsEngine()
7890
/// <param name="settings">Settings of the Jint JS engine</param>
7991
public JintJsEngine(JintSettings settings)
8092
{
93+
_cancellationTokenSource = new CancellationTokenSource();
94+
_cancellationConstraint = new CustomCancellationConstraint(_cancellationTokenSource.Token);
95+
8196
JintSettings jintSettings = settings ?? new JintSettings();
8297

8398
try
8499
{
85100
_jsEngine = new OriginalEngine(options => {
86101
options
87102
.AllowDebuggerStatement(jintSettings.AllowDebuggerStatement)
103+
.Constraint(_cancellationConstraint)
88104
.DebugMode(jintSettings.EnableDebugging)
89105
.LimitMemory(jintSettings.MemoryLimit)
90106
.LimitRecursion(jintSettings.MaxRecursionDepth)
@@ -187,8 +203,9 @@ private static WrapperCompilationException WrapParserException(OriginalParserExc
187203
return wrapperCompilationException;
188204
}
189205

190-
private static WrapperRuntimeException WrapRuntimeException(OriginalRuntimeException originalRuntimeException)
206+
private WrapperRuntimeException WrapRuntimeException(OriginalRuntimeException originalRuntimeException)
191207
{
208+
WrapperRuntimeException wrapperRuntimeException;
192209
string message = originalRuntimeException.Message;
193210
if (string.IsNullOrWhiteSpace(message))
194211
{
@@ -227,11 +244,17 @@ private static WrapperRuntimeException WrapRuntimeException(OriginalRuntimeExcep
227244

228245
message = JsErrorHelpers.GenerateScriptErrorMessage(type, description, documentName, lineNumber,
229246
columnNumber);
247+
248+
wrapperRuntimeException = new WrapperRuntimeException(message, EngineName, EngineVersion,
249+
originalJavaScriptException);
230250
}
231251
else if (originalRuntimeException is OriginalMemoryLimitExceededException)
232252
{
233253
type = JsErrorType.Common;
234254
message = JsErrorHelpers.GenerateScriptErrorMessage(type, description, string.Empty);
255+
256+
wrapperRuntimeException = new WrapperRuntimeException(message, EngineName, EngineVersion,
257+
originalRuntimeException);
235258
}
236259
else if (originalRuntimeException is OriginalRecursionDepthOverflowException)
237260
{
@@ -266,28 +289,45 @@ private static WrapperRuntimeException WrapRuntimeException(OriginalRuntimeExcep
266289

267290
type = JsErrorType.Range;
268291
message = JsErrorHelpers.GenerateScriptErrorMessage(type, description, callStack);
292+
293+
wrapperRuntimeException = new WrapperRuntimeException(message, EngineName, EngineVersion,
294+
originalRecursionException);
269295
}
270296
else if (originalRuntimeException is OriginalStatementsCountOverflowException)
271297
{
272298
type = JsErrorType.Range;
273299
message = JsErrorHelpers.GenerateScriptErrorMessage(type, description, string.Empty);
300+
301+
wrapperRuntimeException = new WrapperRuntimeException(message, EngineName, EngineVersion,
302+
originalRuntimeException);
303+
}
304+
else if (originalRuntimeException is ScriptExecutionCanceledException)
305+
{
306+
_cancellationTokenSource = new CancellationTokenSource();
307+
_cancellationConstraint.Reset(_cancellationTokenSource.Token);
308+
309+
type = JsErrorType.Common;
310+
message = CoreStrings.Runtime_ScriptInterrupted;
311+
description = message;
312+
313+
wrapperRuntimeException = new WrapperInterruptedException(message,
314+
EngineName, EngineVersion, originalRuntimeException);
274315
}
275316
else
276317
{
277318
type = JsErrorType.Common;
278319
message = JsErrorHelpers.GenerateScriptErrorMessage(type, description, string.Empty);
320+
321+
wrapperRuntimeException = new WrapperRuntimeException(message, EngineName, EngineVersion,
322+
originalRuntimeException);
279323
}
280324

281-
var wrapperRuntimeException = new WrapperRuntimeException(message, EngineName, EngineVersion,
282-
originalRuntimeException)
283-
{
284-
Description = description,
285-
Type = type,
286-
DocumentName = documentName,
287-
LineNumber = lineNumber,
288-
ColumnNumber = columnNumber,
289-
CallStack = callStack
290-
};
325+
wrapperRuntimeException.Description = description;
326+
wrapperRuntimeException.Type = type;
327+
wrapperRuntimeException.DocumentName = documentName;
328+
wrapperRuntimeException.LineNumber = lineNumber;
329+
wrapperRuntimeException.ColumnNumber = columnNumber;
330+
wrapperRuntimeException.CallStack = callStack;
291331

292332
return wrapperRuntimeException;
293333
}
@@ -602,7 +642,7 @@ protected override void InnerEmbedHostType(string itemName, Type type)
602642

603643
protected override void InnerInterrupt()
604644
{
605-
throw new NotSupportedException();
645+
_cancellationTokenSource.Cancel();
606646
}
607647

608648
protected override void InnerCollectGarbage()
@@ -641,7 +681,7 @@ public override bool SupportsScriptPrecompilation
641681
/// </summary>
642682
public override bool SupportsScriptInterruption
643683
{
644-
get { return false; }
684+
get { return true; }
645685
}
646686

647687
/// <summary>
@@ -663,6 +703,13 @@ public override void Dispose()
663703
lock (_executionSynchronizer)
664704
{
665705
_jsEngine = null;
706+
_cancellationConstraint = null;
707+
708+
if (_cancellationTokenSource != null)
709+
{
710+
_cancellationTokenSource.Dispose();
711+
_cancellationTokenSource = null;
712+
}
666713
}
667714
}
668715
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using OriginalRuntimeException = Jint.Runtime.JintException;
2+
3+
namespace JavaScriptEngineSwitcher.Jint
4+
{
5+
public class ScriptExecutionCanceledException : OriginalRuntimeException
6+
{
7+
public ScriptExecutionCanceledException()
8+
: base("The script execution was canceled.")
9+
{ }
10+
}
11+
}

src/JavaScriptEngineSwitcher.Jint/readme.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
=============
1818
RELEASE NOTES
1919
=============
20-
Jint was updated to version 3.0.0 Beta 1828.
20+
Added a ability to interrupt execution of the script.
2121

2222
=============
2323
DOCUMENTATION

0 commit comments

Comments
 (0)