11using System ;
22using System . Text ;
3+ using System . Threading ;
34
45using Jint ;
56using IOriginalPrimitiveInstance = Jint . Native . IPrimitiveInstance ;
2728
2829using CoreStrings = JavaScriptEngineSwitcher . Core . Resources . Strings ;
2930using WrapperCompilationException = JavaScriptEngineSwitcher . Core . JsCompilationException ;
31+ using WrapperInterruptedException = JavaScriptEngineSwitcher . Core . JsInterruptedException ;
3032using WrapperRuntimeException = JavaScriptEngineSwitcher . Core . JsRuntimeException ;
3133using WrapperTimeoutException = JavaScriptEngineSwitcher . Core . JsTimeoutException ;
3234using 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 }
0 commit comments