Skip to content

Commit e1809a0

Browse files
TaritsynDaniel15
authored andcommitted
Added a ability to select the default JavaScript engine (#413)
* Added a ability to select the default JavaScript engine * Added a unit tests
1 parent 5168caa commit e1809a0

File tree

3 files changed

+150
-7
lines changed

3 files changed

+150
-7
lines changed

src/React.Core/Exceptions/ReactEngineNotFoundException.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ public class ReactEngineNotFoundException : ReactException
2525
/// </summary>
2626
public ReactEngineNotFoundException() : base(GetMessage()) { }
2727

28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="ReactEngineNotFoundException"/> class.
30+
/// </summary>
31+
/// <param name="message">The message that describes the error.</param>
32+
public ReactEngineNotFoundException(string message) : base(message) { }
33+
2834
#if NET40
2935
/// <summary>
3036
/// Used by deserialization
@@ -40,8 +46,8 @@ private static string GetMessage()
4046
{
4147
return
4248
"No usable JavaScript engine was found. Please install a JavaScript engine such " +
43-
"as React.JavaScriptEngine.ClearScriptV8 (on Windows) or " +
44-
"React.JavaScriptEngine.VroomJs (on Linux and Mac OS X). Refer to the ReactJS.NET " +
49+
"as JavaScriptEngineSwitcher.V8.V8JsEngine (on Windows) or " +
50+
"React.VroomJsEngine (on Linux and Mac OS X). Refer to the ReactJS.NET " +
4551
"documentation for more details.";
4652
}
4753
}

src/React.Core/JavaScriptEngineFactory.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,23 @@ public virtual void ReturnEngineToPool(IJsEngine engine)
251251
private static Func<IJsEngine> GetFactory(JsEngineSwitcher jsEngineSwitcher, bool allowMsie)
252252
{
253253
EnsureJsEnginesRegistered(jsEngineSwitcher, allowMsie);
254+
255+
string defaultEngineName = jsEngineSwitcher.DefaultEngineName;
256+
if (!string.IsNullOrWhiteSpace(defaultEngineName))
257+
{
258+
var engineFactory = jsEngineSwitcher.EngineFactories.Get(defaultEngineName);
259+
if (engineFactory != null)
260+
{
261+
return engineFactory.CreateEngine;
262+
}
263+
else
264+
{
265+
throw new ReactEngineNotFoundException(
266+
"Could not find a factory, that creates an instance of the JavaScript " +
267+
"engine with name `" + defaultEngineName + "`.");
268+
}
269+
}
270+
254271
foreach (var engineFactory in jsEngineSwitcher.EngineFactories)
255272
{
256273
IJsEngine engine = null;

tests/React.Tests/Core/JavaScriptEngineFactoryTest.cs

Lines changed: 125 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ namespace React.Tests.Core
1919
{
2020
public class JavaScriptEngineFactoryTest
2121
{
22+
private static object _engineSwitcherSynchronizer = new object();
23+
24+
2225
private JavaScriptEngineFactory CreateBasicFactory()
2326
{
2427
var config = new Mock<IReactSiteConfiguration>();
@@ -44,11 +47,17 @@ Func<IJsEngine> innerEngineFactory
4447
engineFactory.Setup(x => x.CreateEngine()).Returns(innerEngineFactory);
4548

4649
// JsEngineSwitcher is a singleton :(
47-
var engineFactories = JsEngineSwitcher.Instance.EngineFactories;
48-
engineFactories.Clear();
49-
engineFactories.Add(engineFactory.Object);
50-
51-
return new JavaScriptEngineFactory(JsEngineSwitcher.Instance, config.Object, fileSystem.Object);
50+
lock (_engineSwitcherSynchronizer)
51+
{
52+
var engineSwitcher = JsEngineSwitcher.Instance;
53+
engineSwitcher.DefaultEngineName = string.Empty;
54+
55+
var engineFactories = engineSwitcher.EngineFactories;
56+
engineFactories.Clear();
57+
engineFactories.Add(engineFactory.Object);
58+
59+
return new JavaScriptEngineFactory(engineSwitcher, config.Object, fileSystem.Object);
60+
}
5261
}
5362

5463
[Fact]
@@ -176,5 +185,116 @@ public void ShouldCatchErrorsWhileLoadingScripts()
176185
var ex = Assert.Throws<ReactScriptLoadException>(() => factory.GetEngineForCurrentThread());
177186
Assert.Equal("Error while loading \"foo.js\": Fail\r\nLine: 42\r\nColumn: 911", ex.Message);
178187
}
188+
189+
[Fact]
190+
public void ShouldReturnDefaultEngine()
191+
{
192+
const string someEngineName = "SomeEngine";
193+
const string defaultEngineName = "DefaultEngine";
194+
const string someOtherEngineName = "SomeOtherEngine";
195+
196+
var someEngineFactory = new Mock<IJsEngineFactory>();
197+
someEngineFactory.Setup(x => x.EngineName).Returns(someEngineName);
198+
someEngineFactory.Setup(x => x.CreateEngine()).Returns(() =>
199+
{
200+
var someEngine = new Mock<IJsEngine>();
201+
someEngine.Setup(x => x.Name).Returns(someEngineName);
202+
return someEngine.Object;
203+
});
204+
205+
var defaultEngineFactory = new Mock<IJsEngineFactory>();
206+
defaultEngineFactory.Setup(x => x.EngineName).Returns(defaultEngineName);
207+
defaultEngineFactory.Setup(x => x.CreateEngine()).Returns(() =>
208+
{
209+
var defaultEngine = new Mock<IJsEngine>();
210+
defaultEngine.Setup(x => x.Name).Returns(defaultEngineName);
211+
return defaultEngine.Object;
212+
});
213+
214+
var someOtherEngineFactory = new Mock<IJsEngineFactory>();
215+
someOtherEngineFactory.Setup(x => x.EngineName).Returns(someOtherEngineName);
216+
someOtherEngineFactory.Setup(x => x.CreateEngine()).Returns(() =>
217+
{
218+
var someOtherEngine = new Mock<IJsEngine>();
219+
someOtherEngine.Setup(x => x.Name).Returns(someOtherEngineName);
220+
return someOtherEngine.Object;
221+
});
222+
223+
var config = new Mock<IReactSiteConfiguration>();
224+
config.Setup(x => x.ScriptsWithoutTransform).Returns(new List<string>());
225+
config.Setup(x => x.LoadReact).Returns(true);
226+
227+
var fileSystem = new Mock<IFileSystem>();
228+
229+
JavaScriptEngineFactory factory;
230+
231+
// JsEngineSwitcher is a singleton :(
232+
lock (_engineSwitcherSynchronizer)
233+
{
234+
var engineSwitcher = JsEngineSwitcher.Instance;
235+
engineSwitcher.DefaultEngineName = defaultEngineName;
236+
237+
var engineFactories = engineSwitcher.EngineFactories;
238+
engineFactories.Clear();
239+
engineFactories.Add(someEngineFactory.Object);
240+
engineFactories.Add(defaultEngineFactory.Object);
241+
engineFactories.Add(someOtherEngineFactory.Object);
242+
243+
factory = new JavaScriptEngineFactory(engineSwitcher, config.Object, fileSystem.Object);
244+
}
245+
246+
var engine = factory.GetEngineForCurrentThread();
247+
248+
Assert.Equal(defaultEngineName, engine.Name);
249+
}
250+
251+
[Fact]
252+
public void ShouldThrowIfDefaultEngineFactoryNotFound()
253+
{
254+
const string someEngineName = "SomeEngine";
255+
const string defaultEngineName = "DefaultEngine";
256+
const string someOtherEngineName = "SomeOtherEngine";
257+
258+
var someEngineFactory = new Mock<IJsEngineFactory>();
259+
someEngineFactory.Setup(x => x.EngineName).Returns(someEngineName);
260+
someEngineFactory.Setup(x => x.CreateEngine()).Returns(() =>
261+
{
262+
var someEngine = new Mock<IJsEngine>();
263+
someEngine.Setup(x => x.Name).Returns(someEngineName);
264+
return someEngine.Object;
265+
});
266+
267+
var someOtherEngineFactory = new Mock<IJsEngineFactory>();
268+
someOtherEngineFactory.Setup(x => x.EngineName).Returns(someOtherEngineName);
269+
someOtherEngineFactory.Setup(x => x.CreateEngine()).Returns(() =>
270+
{
271+
var someOtherEngine = new Mock<IJsEngine>();
272+
someOtherEngine.Setup(x => x.Name).Returns(someOtherEngineName);
273+
return someOtherEngine.Object;
274+
});
275+
276+
var config = new Mock<IReactSiteConfiguration>();
277+
config.Setup(x => x.ScriptsWithoutTransform).Returns(new List<string>());
278+
config.Setup(x => x.LoadReact).Returns(true);
279+
280+
var fileSystem = new Mock<IFileSystem>();
281+
282+
// JsEngineSwitcher is a singleton :(
283+
lock (_engineSwitcherSynchronizer)
284+
{
285+
var engineSwitcher = JsEngineSwitcher.Instance;
286+
engineSwitcher.DefaultEngineName = defaultEngineName;
287+
288+
var engineFactories = engineSwitcher.EngineFactories;
289+
engineFactories.Clear();
290+
engineFactories.Add(someEngineFactory.Object);
291+
engineFactories.Add(someOtherEngineFactory.Object);
292+
293+
Assert.Throws<ReactEngineNotFoundException>(() =>
294+
{
295+
var factory = new JavaScriptEngineFactory(engineSwitcher, config.Object, fileSystem.Object);
296+
});
297+
}
298+
}
179299
}
180300
}

0 commit comments

Comments
 (0)