Skip to content

Commit e149667

Browse files
committed
Optimized a performance of the IsSupported methods
1 parent 47e2f95 commit e149667

File tree

11 files changed

+376
-226
lines changed

11 files changed

+376
-226
lines changed

src/MsieJavaScriptEngine/ActiveScript/ActiveScriptJsEngineBase.cs

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Runtime.InteropServices;
77
using System.Windows.Threading;
88

9+
using Constants;
910
using Helpers;
1011
using Resources;
1112
using Utilities;
@@ -117,27 +118,52 @@ protected ActiveScriptJsEngineBase(string clsid, string engineModeName, string l
117118
/// Checks a support of the JavaScript engine on the machine
118119
/// </summary>
119120
/// <param name="clsid">CLSID of JavaScript engine</param>
121+
/// <param name="isSupported">Flag indicating whether this JavaScript engine is supported</param>
122+
/// <param name="supportSynchronizer">Support synchronizer</param>
120123
/// <returns>Result of check (true - supports; false - does not support)</returns>
121-
protected static bool IsSupported(string clsid)
124+
protected static bool IsSupported(string clsid, ref bool? isSupported, ref object supportSynchronizer)
122125
{
123-
bool isSupported;
124-
IntPtr pActiveScript = IntPtr.Zero;
125-
126-
try
127-
{
128-
pActiveScript = ComHelpers.CreateInstanceByClsid<IActiveScript>(clsid);
129-
isSupported = true;
130-
}
131-
catch
126+
if (isSupported.HasValue)
132127
{
133-
isSupported = false;
128+
return isSupported.Value;
134129
}
135-
finally
130+
131+
lock (supportSynchronizer)
136132
{
137-
ComHelpers.ReleaseAndEmpty(ref pActiveScript);
138-
}
133+
if (isSupported.HasValue)
134+
{
135+
return isSupported.Value;
136+
}
137+
138+
IntPtr pActiveScript = IntPtr.Zero;
139+
140+
try
141+
{
142+
pActiveScript = ComHelpers.CreateInstanceByClsid<IActiveScript>(clsid);
143+
isSupported = true;
144+
}
145+
catch (COMException e)
146+
{
147+
if (e.ErrorCode == ComErrorCode.ClassNotRegistered)
148+
{
149+
isSupported = false;
150+
}
151+
else
152+
{
153+
isSupported = null;
154+
}
155+
}
156+
catch
157+
{
158+
isSupported = null;
159+
}
160+
finally
161+
{
162+
ComHelpers.ReleaseAndEmpty(ref pActiveScript);
163+
}
139164

140-
return isSupported;
165+
return isSupported.HasValue && isSupported.Value;
166+
}
141167
}
142168

143169
/// <summary>

src/MsieJavaScriptEngine/ActiveScript/ActiveScriptSiteWrapper.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99

1010
using EXCEPINFO = System.Runtime.InteropServices.ComTypes.EXCEPINFO;
1111

12+
using Constants;
1213
using Helpers;
1314
using Resources;
1415

1516
internal class ActiveScriptSiteWrapper : IActiveScriptSite, IDisposable
1617
{
17-
private const int TYPE_ERROR_ELEMENT_NOT_FOUND = unchecked((int)(0x8002802B));
18-
1918
/// <summary>
2019
/// Instance of native JavaScript engine
2120
/// </summary>
@@ -400,7 +399,7 @@ public void GetItemInfo(string name, ScriptInfoFlags returnMask, out object item
400399
item = GetItem(name);
401400
if (item == null)
402401
{
403-
throw new COMException(string.Format(Strings.Runtime_ItemNotFound, name), TYPE_ERROR_ELEMENT_NOT_FOUND);
402+
throw new COMException(string.Format(Strings.Runtime_ItemNotFound, name), ComErrorCode.ElementNotFound);
404403
}
405404
}
406405
else

src/MsieJavaScriptEngine/ActiveScript/ChakraActiveScriptJsEngine.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ internal sealed class ChakraActiveScriptJsEngine : ActiveScriptJsEngineBase
99
{
1010
private const string CHAKRA_CLSID = "{16d51579-a30b-4c8b-a276-0ff4dc41e755}";
1111

12+
/// <summary>
13+
/// Flag indicating whether this JavaScript engine is supported
14+
/// </summary>
15+
private static bool? _isSupported;
16+
17+
/// <summary>
18+
/// Support synchronizer
19+
/// </summary>
20+
private static object _supportSynchronizer = new object();
21+
1222

1323
/// <summary>
1424
/// Constructs instance of the Chakra ActiveScript JavaScript engine
@@ -25,7 +35,7 @@ public ChakraActiveScriptJsEngine()
2535
/// <returns>Result of check (true - supports; false - does not support)</returns>
2636
public static bool IsSupported()
2737
{
28-
bool isSupported = IsSupported(CHAKRA_CLSID);
38+
bool isSupported = IsSupported(CHAKRA_CLSID, ref _isSupported, ref _supportSynchronizer);
2939

3040
return isSupported;
3141
}

src/MsieJavaScriptEngine/ActiveScript/ClassicActiveScriptJsEngine.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ internal sealed class ClassicActiveScriptJsEngine : ActiveScriptJsEngineBase
99
{
1010
private const string CLASSIC_CLSID = "{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}";
1111

12+
/// <summary>
13+
/// Flag indicating whether this JavaScript engine is supported
14+
/// </summary>
15+
private static bool? _isSupported;
16+
17+
/// <summary>
18+
/// Support synchronizer
19+
/// </summary>
20+
private static object _supportSynchronizer = new object();
21+
1222

1323
/// <summary>
1424
/// Constructs instance of the Classic MSIE JavaScript engine
@@ -27,7 +37,7 @@ public ClassicActiveScriptJsEngine(bool useEcmaScript5Polyfill, bool useJson2Lib
2737
/// <returns>Result of check (true - supports; false - does not support)</returns>
2838
public static bool IsSupported()
2939
{
30-
bool isSupported = IsSupported(CLASSIC_CLSID);
40+
bool isSupported = IsSupported(CLASSIC_CLSID, ref _isSupported, ref _supportSynchronizer);
3141

3242
return isSupported;
3343
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace MsieJavaScriptEngine.Constants
2+
{
3+
/// <summary>
4+
/// COM error codes
5+
/// </summary>
6+
internal static class ComErrorCode
7+
{
8+
public const int ElementNotFound = unchecked((int)(0x8002802B));
9+
10+
public const int ClassNotRegistered = unchecked((int)(0x80040154));
11+
}
12+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace MsieJavaScriptEngine.Constants
2+
{
3+
/// <summary>
4+
/// DLL names
5+
/// </summary>
6+
internal static class DllName
7+
{
8+
public const string JScript9 = "jscript9.dll";
9+
10+
public const string Chakra = "chakra.dll";
11+
}
12+
}

src/MsieJavaScriptEngine/JsRt/Edge/ChakraEdgeJsRtJsEngine.cs

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,19 @@ internal sealed class ChakraEdgeJsRtJsEngine : IInnerJsEngine
2929
private readonly EdgeJsContext _jsContext;
3030

3131
/// <summary>
32-
/// Synchronizer
32+
/// Flag indicating whether this JavaScript engine is supported
3333
/// </summary>
34-
private readonly object _synchronizer = new object();
34+
private static bool? _isSupported;
35+
36+
/// <summary>
37+
/// Support synchronizer
38+
/// </summary>
39+
private static readonly object _supportSynchronizer = new object();
40+
41+
/// <summary>
42+
/// Run synchronizer
43+
/// </summary>
44+
private readonly object _runSynchronizer = new object();
3545

3646
/// <summary>
3747
/// Flag that object is destroyed
@@ -96,21 +106,43 @@ private static EdgeJsRuntime CreateJsRuntime()
96106
/// <returns>Result of check (true - supports; false - does not support)</returns>
97107
public static bool IsSupported()
98108
{
99-
bool isSupported;
109+
if (_isSupported.HasValue)
110+
{
111+
return _isSupported.Value;
112+
}
100113

101-
try
114+
lock (_supportSynchronizer)
102115
{
103-
using (CreateJsRuntime())
116+
if (_isSupported.HasValue)
104117
{
105-
isSupported = true;
118+
return _isSupported.Value;
106119
}
107-
}
108-
catch
109-
{
110-
isSupported = false;
111-
}
112120

113-
return isSupported;
121+
try
122+
{
123+
using (CreateJsRuntime())
124+
{
125+
_isSupported = true;
126+
}
127+
}
128+
catch (DllNotFoundException e)
129+
{
130+
if (e.Message.IndexOf("'" + DllName.Chakra + "'", StringComparison.OrdinalIgnoreCase) != -1)
131+
{
132+
_isSupported = false;
133+
}
134+
else
135+
{
136+
_isSupported = null;
137+
}
138+
}
139+
catch
140+
{
141+
_isSupported = null;
142+
}
143+
144+
return _isSupported.HasValue && _isSupported.Value;
145+
}
114146
}
115147

116148
/// <summary>
@@ -264,7 +296,7 @@ private JsRuntimeException ConvertJsExceptionToJsRuntimeException(
264296

265297
private void InvokeScript(Action action)
266298
{
267-
lock (_synchronizer)
299+
lock (_runSynchronizer)
268300
using (new EdgeJsScope(_jsContext))
269301
{
270302
try
@@ -280,7 +312,7 @@ private void InvokeScript(Action action)
280312

281313
private T InvokeScript<T>(Func<T> func)
282314
{
283-
lock (_synchronizer)
315+
lock (_runSynchronizer)
284316
using (new EdgeJsScope(_jsContext))
285317
{
286318
try
@@ -301,7 +333,7 @@ private T InvokeScript<T>(Func<T> func)
301333
/// managed objects contained in fields of class</param>
302334
private void Dispose(bool disposing)
303335
{
304-
lock (_synchronizer)
336+
lock (_runSynchronizer)
305337
{
306338
if (!_disposed)
307339
{

0 commit comments

Comments
 (0)