Skip to content

Commit 95d29a9

Browse files
committed
Added a ability to interrupt execution of the script
1 parent 00cdbf1 commit 95d29a9

26 files changed

+999
-238
lines changed

NuGet/MsieJavaScriptEngine.nuspec

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
<requireLicenseAcceptance>false</requireLicenseAcceptance>
1313
<description>This library is a .NET wrapper for working with the JavaScript engines of Internet Explorer and Edge (JsRT versions of Chakra, ActiveScript version of Chakra and Classic JavaScript Engine). Project was based on the code of SassAndCoffee.JavaScript (http://github.com/paulcbetts/SassAndCoffee), Chakra Sample Hosts (http://github.com/panopticoncentral/chakra-host) and jsrt-dotnet (http://github.com/robpaveza/jsrt-dotnet).</description>
1414
<summary>This library is a .NET wrapper for working with the JavaScript engines of Internet Explorer and Edge (JsRT versions of Chakra, ActiveScript version of Chakra and Classic JavaScript Engine).</summary>
15-
<releaseNotes>1. In ActiveScript modes now are uses the short names of error categories;
16-
2. In `Classic` mode during debugging now script error contains a full stack trace;
17-
3. In JsRT modes the compilation error messages now contains a information about the error location.</releaseNotes>
15+
<releaseNotes>Added a ability to interrupt execution of the script.</releaseNotes>
1816
<copyright>Copyright (c) 2012-2017 Andrey Taritsyn - http://www.taritsyn.ru</copyright>
1917
<language>en-US</language>
2018
<tags>JavaScript ECMAScript MSIE IE Edge Chakra</tags>

NuGet/readme.txt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,7 @@
2121
=============
2222
RELEASE NOTES
2323
=============
24-
1. In ActiveScript modes now are uses the short names of error categories;
25-
2. In `Classic` mode during debugging now script error contains a full stack
26-
trace;
27-
3. In JsRT modes the compilation error messages now contains a information about
28-
the error location.
24+
Added a ability to interrupt execution of the script.
2925

3026
============
3127
PROJECT SITE

src/MsieJavaScriptEngine.Net4/MsieJavaScriptEngine.Net40.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,15 @@
255255
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\IActiveScriptSite.cs">
256256
<Link>ActiveScript\IActiveScriptSite.cs</Link>
257257
</Compile>
258+
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\IActiveScriptSiteInterruptPoll.cs">
259+
<Link>ActiveScript\IActiveScriptSiteInterruptPoll.cs</Link>
260+
</Compile>
258261
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\IActiveScriptWrapper.cs">
259262
<Link>ActiveScript\IActiveScriptWrapper.cs</Link>
260263
</Compile>
264+
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\JsErrorNumber.cs">
265+
<Link>ActiveScript\JsErrorNumber.cs</Link>
266+
</Compile>
261267
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\ScriptGCType.cs">
262268
<Link>ActiveScript\ScriptGCType.cs</Link>
263269
</Compile>
@@ -285,6 +291,9 @@
285291
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\ScriptTextFlags.cs">
286292
<Link>ActiveScript\ScriptTextFlags.cs</Link>
287293
</Compile>
294+
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\ScriptThreadId.cs">
295+
<Link>ActiveScript\ScriptThreadId.cs</Link>
296+
</Compile>
288297
<Compile Include="..\MsieJavaScriptEngine\ActiveScript\ScriptThreadState.cs">
289298
<Link>ActiveScript\ScriptThreadState.cs</Link>
290299
</Compile>
@@ -483,6 +492,9 @@
483492
<Compile Include="..\MsieJavaScriptEngine\JsRuntimeException.cs">
484493
<Link>JsRuntimeException.cs</Link>
485494
</Compile>
495+
<Compile Include="..\MsieJavaScriptEngine\JsScriptInterruptedException.cs">
496+
<Link>JsScriptInterruptedException.cs</Link>
497+
</Compile>
486498
<Compile Include="..\MsieJavaScriptEngine\MsieJsEngine.cs">
487499
<Link>MsieJsEngine.cs</Link>
488500
</Compile>

src/MsieJavaScriptEngine/ActiveScript/ActiveScriptException.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace MsieJavaScriptEngine.ActiveScript
99
public sealed class ActiveScriptException : Exception
1010
{
1111
/// <summary>
12-
/// Error code
12+
/// The HRESULT of the error
1313
/// </summary>
1414
private int _errorCode;
1515

@@ -44,7 +44,7 @@ public sealed class ActiveScriptException : Exception
4444
private string _sourceFragment = string.Empty;
4545

4646
/// <summary>
47-
/// Gets or sets a error code
47+
/// Gets or sets a HRESULT of the error
4848
/// </summary>
4949
public int ErrorCode
5050
{

src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.ScriptSite.cs

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,16 @@
1212
using MsieJavaScriptEngine.Resources;
1313
using MsieJavaScriptEngine.Utilities;
1414

15-
using HResultHelpers = MsieJavaScriptEngine.Helpers.ComHelpers.HResult;
16-
1715
namespace MsieJavaScriptEngine.ActiveScript
1816
{
1917
/// <summary>
2018
/// Active Script site
2119
/// </summary>
2220
internal abstract partial class ActiveScriptJsEngineBase
2321
{
24-
private sealed class ScriptSite : IActiveScriptSite, IActiveScriptSiteDebug32, IActiveScriptSiteDebug64,
25-
IActiveScriptSiteDebugEx, ICustomQueryInterface
22+
private sealed class ScriptSite : IActiveScriptSite, IActiveScriptSiteInterruptPoll,
23+
IActiveScriptSiteDebug32, IActiveScriptSiteDebug64, IActiveScriptSiteDebugEx,
24+
ICustomQueryInterface
2625
{
2726
/// <summary>
2827
/// Instance of Active Script engine
@@ -40,6 +39,25 @@ public ScriptSite(ActiveScriptJsEngineBase jsEngine)
4039
}
4140

4241

42+
/// <summary>
43+
/// Processes a Active Script error
44+
/// </summary>
45+
/// <param name="error">Instance of <see cref="IActiveScriptError"/></param>
46+
private void ProcessActiveScriptError(IActiveScriptError error)
47+
{
48+
var activeScriptException = CreateActiveScriptException(error);
49+
if (_jsEngine._engineMode == JsEngineMode.Classic
50+
&& activeScriptException.ErrorCode == ComErrorCode.E_ABORT)
51+
{
52+
// Script execution was interrupted explicitly. At this point the script
53+
// engine might be in an odd state; the following call seems to get it back
54+
// to normal.
55+
_jsEngine._activeScriptWrapper.SetScriptState(ScriptState.Started);
56+
}
57+
58+
_jsEngine._lastException = activeScriptException;
59+
}
60+
4361
/// <summary>
4462
/// Creates a instance of <see cref="ActiveScriptException"/>
4563
/// </summary>
@@ -51,10 +69,19 @@ private ActiveScriptException CreateActiveScriptException(IActiveScriptError err
5169
error.GetExceptionInfo(out exceptionInfo);
5270

5371
int hResult = exceptionInfo.scode;
54-
int errorCode = HResultHelpers.GetCode(hResult);
5572
bool isSyntaxError = IsSyntaxError(hResult);
56-
string category = exceptionInfo.bstrSource;
57-
string description = exceptionInfo.bstrDescription;
73+
string category;
74+
string description;
75+
if (hResult == ComErrorCode.E_ABORT)
76+
{
77+
category = string.Empty;
78+
description = CommonStrings.Runtime_ScriptInterrupted;
79+
}
80+
else
81+
{
82+
category = _jsEngine.ShortenErrorCategoryName(exceptionInfo.bstrSource);
83+
description = exceptionInfo.bstrDescription;
84+
}
5885
string helpLink = string.Empty;
5986
if (!string.IsNullOrWhiteSpace(exceptionInfo.bstrHelpFile))
6087
{
@@ -84,7 +111,7 @@ private ActiveScriptException CreateActiveScriptException(IActiveScriptError err
84111

85112
var activeScriptException = new ActiveScriptException(message)
86113
{
87-
ErrorCode = errorCode,
114+
ErrorCode = hResult,
88115
Category = category,
89116
Description = description,
90117
SourceContext = sourceContext,
@@ -106,10 +133,11 @@ private static bool IsSyntaxError(int hResult)
106133
{
107134
bool isSyntaxError = false;
108135

109-
if (HResultHelpers.GetFacility(hResult) == HResultHelpers.FACILITY_CONTROL)
136+
if (ComHelpers.HResult.GetFacility(hResult) == ComErrorCode.FACILITY_CONTROL)
110137
{
111-
int errorCode = HResultHelpers.GetCode(hResult);
112-
isSyntaxError = errorCode >= 1002 && errorCode <= 1035;
138+
int errorNumber = ComHelpers.HResult.GetCode(hResult);
139+
isSyntaxError = errorNumber >= (int)JsErrorNumber.SyntaxError
140+
&& errorNumber <= (int)JsErrorNumber.ThrowMustBeFollowedByExpressionOnSameSourceLine;
113141
}
114142

115143
return isSyntaxError;
@@ -129,8 +157,11 @@ private string GetErrorDetails(string category, string description, bool isSynta
129157
uint sourceContext, uint lineNumber, int columnNumber)
130158
{
131159
var errorBuilder = new StringBuilder();
132-
errorBuilder.AppendFormatLine("{0}: {1}",
133-
_jsEngine.ShortenErrorCategoryName(category), description);
160+
if (!string.IsNullOrWhiteSpace(category))
161+
{
162+
errorBuilder.AppendFormat("{0}: ", category);
163+
}
164+
errorBuilder.AppendLine(description);
134165

135166
if (_jsEngine._processDebugManagerWrapper != null)
136167
{
@@ -312,7 +343,7 @@ public void GetItemInfo(string name, ScriptInfoFlags mask, ref IntPtr pUnkItem,
312343
if (item == null)
313344
{
314345
throw new COMException(
315-
string.Format(NetFrameworkStrings.Runtime_ItemNotFound, name), ComErrorCode.ElementNotFound);
346+
string.Format(NetFrameworkStrings.Runtime_ItemNotFound, name), ComErrorCode.E_ELEMENT_NOT_FOUND);
316347
}
317348

318349
if (mask.HasFlag(ScriptInfoFlags.IUnknown))
@@ -339,7 +370,7 @@ public void OnStateChange(ScriptState state)
339370

340371
public void OnScriptError(IActiveScriptError error)
341372
{
342-
_jsEngine._lastException = CreateActiveScriptException(error);
373+
ProcessActiveScriptError(error);
343374
}
344375

345376
public void OnEnterScript()
@@ -350,6 +381,35 @@ public void OnLeaveScript()
350381

351382
#endregion
352383

384+
#region IActiveScriptSiteInterruptPoll implementation
385+
386+
public uint QueryContinue()
387+
{
388+
int hResult;
389+
390+
if (_jsEngine._engineMode == JsEngineMode.ChakraActiveScript
391+
&& _jsEngine._interruptRequested)
392+
{
393+
hResult = ComErrorCode.E_ABORT;
394+
var activeScriptException = new ActiveScriptException(
395+
CommonStrings.Runtime_ScriptInterrupted)
396+
{
397+
ErrorCode = hResult,
398+
Description = CommonStrings.Runtime_ScriptInterrupted
399+
};
400+
401+
_jsEngine._lastException = activeScriptException;
402+
}
403+
else
404+
{
405+
hResult = ComErrorCode.S_OK;
406+
}
407+
408+
return NumericHelpers.SignedAsUnsigned(hResult);
409+
}
410+
411+
#endregion
412+
353413
#region IActiveScriptSiteDebug32 and IActiveScriptSiteDebug64 implementation
354414

355415
public void GetRootApplicationNode(out IDebugApplicationNode node)
@@ -363,7 +423,7 @@ public void OnScriptErrorDebug(IActiveScriptErrorDebug errorDebug, out bool ente
363423
var error = errorDebug as IActiveScriptError;
364424
if (error != null)
365425
{
366-
_jsEngine._lastException = CreateActiveScriptException(error);
426+
ProcessActiveScriptError(error);
367427
}
368428

369429
enterDebugger = true;

0 commit comments

Comments
 (0)