Skip to content

Commit c2bd6d5

Browse files
committed
In JavaScriptEngineSwitcher.Jint fixed a error that occurred during the recursive execution and evaluation of JS files
1 parent b82b228 commit c2bd6d5

File tree

4 files changed

+271
-8
lines changed

4 files changed

+271
-8
lines changed

src/JavaScriptEngineSwitcher.Jint/JavaScriptEngineSwitcher.Jint.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<Description>JavaScriptEngineSwitcher.Jint contains adapter `JintJsEngine` (wrapper for the Jint JavaScript Engine (http://github.com/sebastienros/jint) version 2.11.58).</Description>
1313
<PackageIconUrl>https://raw.githubusercontent.com/Taritsyn/JavaScriptEngineSwitcher/master/Icons/JavaScriptEngineSwitcher_Jint_Logo128x128.png</PackageIconUrl>
1414
<PackageTags>JavaScriptEngineSwitcher;JavaScript;ECMAScript;Jint</PackageTags>
15-
<PackageReleaseNotes>Fixed a error that occurs in the strict mode when generating an error message.</PackageReleaseNotes>
15+
<PackageReleaseNotes>Fixed a error that occurred during the recursive execution and evaluation of JS files.</PackageReleaseNotes>
1616
</PropertyGroup>
1717

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

src/JavaScriptEngineSwitcher.Jint/JintJsEngine.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Text;
34

45
using IOriginalCallable = Jint.Native.ICallable;
@@ -12,6 +13,7 @@
1213
using OriginalRecursionDepthOverflowException = Jint.Runtime.RecursionDepthOverflowException;
1314
using OriginalStatementsCountOverflowException = Jint.Runtime.StatementsCountOverflowException;
1415
using OriginalTypeReference = Jint.Runtime.Interop.TypeReference;
16+
using OriginalTypes = Jint.Runtime.Types;
1517
using OriginalValue = Jint.Native.JsValue;
1618

1719
using AdvancedStringBuilder;
@@ -61,6 +63,11 @@ public sealed class JintJsEngine : JsEngineBase
6163
private readonly UniqueDocumentNameManager _documentNameManager =
6264
new UniqueDocumentNameManager(DefaultDocumentName);
6365

66+
/// <summary>
67+
/// List of primitive class names
68+
/// </summary>
69+
private static ISet<string> _primitiveClassNames = new HashSet<string> { "Boolean", "Number", "String" };
70+
6471

6572
/// <summary>
6673
/// Constructs an instance of adapter for the Jint JS engine
@@ -120,9 +127,21 @@ private OriginalValue MapToScriptType(object value)
120127
/// <returns>The mapped value</returns>
121128
private object MapToHostType(OriginalValue value)
122129
{
123-
if (value.IsUndefined())
130+
switch (value.Type)
124131
{
125-
return Undefined.Value;
132+
case OriginalTypes.Undefined:
133+
return Undefined.Value;
134+
135+
case OriginalTypes.Object:
136+
var objInstance = value.As<OriginalObjectInstance>();
137+
if (objInstance != null && !_primitiveClassNames.Contains(objInstance.Class))
138+
{
139+
return objInstance;
140+
}
141+
else
142+
{
143+
break;
144+
}
126145
}
127146

128147
return value.ToObject();

src/JavaScriptEngineSwitcher.Jint/readme.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
=============
1818
RELEASE NOTES
1919
=============
20-
Fixed a error that occurs in the strict mode when generating an error message.
20+
Fixed a error that occurred during the recursive execution and evaluation of JS
21+
files.
2122

2223
=============
2324
DOCUMENTATION

test/JavaScriptEngineSwitcher.Tests/Jint/InteropTests.cs

Lines changed: 247 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
namespace JavaScriptEngineSwitcher.Tests.Jint
1+
using System;
2+
using System.IO;
3+
4+
using Xunit;
5+
6+
using JavaScriptEngineSwitcher.Core;
7+
8+
namespace JavaScriptEngineSwitcher.Tests.Jint
29
{
310
public class InteropTests : InteropTestsBase
411
{
@@ -12,9 +19,245 @@ protected override string EngineName
1219

1320
#region Recursive calls
1421

15-
// TODO: Remove after fixing a error
16-
public override void RecursiveEvaluationOfFilesIsCorrect()
17-
{ }
22+
#region Mapping of errors
23+
24+
[Fact]
25+
public void MappingCompilationErrorDuringRecursiveEvaluationOfFilesIsCorrect()
26+
{
27+
// Arrange
28+
const string directoryPath = "Files/recursiveEvaluation/compilationError";
29+
const string input = "require('index').calculateResult();";
30+
31+
// Act
32+
JsCompilationException exception = null;
33+
34+
using (var jsEngine = CreateJsEngine())
35+
{
36+
try
37+
{
38+
Func<string, object> loadModule = path => {
39+
string absolutePath = Path.Combine(directoryPath, $"{path}.js");
40+
string code = File.ReadAllText(absolutePath);
41+
object result = jsEngine.Evaluate(code, absolutePath);
42+
43+
return result;
44+
};
45+
46+
jsEngine.EmbedHostObject("require", loadModule);
47+
double output = jsEngine.Evaluate<double>(input);
48+
}
49+
catch (JsCompilationException e)
50+
{
51+
exception = e;
52+
}
53+
}
54+
55+
// Assert
56+
Assert.NotNull(exception);
57+
Assert.Equal("Compilation error", exception.Category);
58+
Assert.Equal("Unexpected token ,", exception.Description);
59+
Assert.Equal("SyntaxError", exception.Type);
60+
Assert.Equal("math.js", exception.DocumentName);
61+
Assert.Equal(25, exception.LineNumber);
62+
Assert.Equal(11, exception.ColumnNumber);
63+
Assert.Empty(exception.SourceFragment);
64+
}
65+
66+
[Fact]
67+
public void MappingRuntimeErrorDuringRecursiveEvaluationOfFilesIsCorrect()
68+
{
69+
// Arrange
70+
const string directoryPath = "Files/recursiveEvaluation/runtimeError";
71+
const string input = "require('index').calculateResult();";
72+
73+
// Act
74+
JsRuntimeException exception = null;
75+
76+
using (var jsEngine = CreateJsEngine())
77+
{
78+
try
79+
{
80+
Func<string, object> loadModule = path => {
81+
string absolutePath = Path.Combine(directoryPath, $"{path}.js");
82+
string code = File.ReadAllText(absolutePath);
83+
object result = jsEngine.Evaluate(code, absolutePath);
84+
85+
return result;
86+
};
87+
88+
jsEngine.EmbedHostObject("require", loadModule);
89+
double output = jsEngine.Evaluate<double>(input);
90+
}
91+
catch (JsRuntimeException e)
92+
{
93+
exception = e;
94+
}
95+
}
96+
97+
// Assert
98+
Assert.NotNull(exception);
99+
Assert.Equal("Runtime error", exception.Category);
100+
Assert.Equal("argumens is not defined", exception.Description);
101+
Assert.Equal("ReferenceError", exception.Type);
102+
Assert.Equal("math.js", exception.DocumentName);
103+
Assert.Equal(10, exception.LineNumber);
104+
Assert.Equal(4, exception.ColumnNumber);
105+
Assert.Empty(exception.SourceFragment);
106+
Assert.Empty(exception.CallStack);
107+
}
108+
109+
[Fact]
110+
public void MappingHostErrorDuringRecursiveEvaluationOfFilesIsCorrect()
111+
{
112+
// Arrange
113+
const string directoryPath = "Files/recursiveEvaluation/hostError";
114+
const string input = "require('index').calculateResult();";
115+
116+
// Act
117+
FileNotFoundException exception = null;
118+
119+
using (var jsEngine = CreateJsEngine())
120+
{
121+
try
122+
{
123+
Func<string, object> loadModule = path => {
124+
string absolutePath = Path.Combine(directoryPath, $"{path}.js");
125+
string code = File.ReadAllText(absolutePath);
126+
object result = jsEngine.Evaluate(code, absolutePath);
127+
128+
return result;
129+
};
130+
131+
jsEngine.EmbedHostObject("require", loadModule);
132+
double output = jsEngine.Evaluate<double>(input);
133+
}
134+
catch (FileNotFoundException e)
135+
{
136+
exception = e;
137+
}
138+
}
139+
140+
// Assert
141+
Assert.NotNull(exception);
142+
Assert.StartsWith("Could not find file '", exception.Message);
143+
}
144+
145+
[Fact]
146+
public void MappingCompilationErrorDuringRecursiveExecutionOfFilesIsCorrect()
147+
{
148+
// Arrange
149+
const string directoryPath = "Files/recursiveExecution/compilationError";
150+
const string variableName = "num";
151+
152+
// Act
153+
JsCompilationException exception = null;
154+
155+
using (var jsEngine = CreateJsEngine())
156+
{
157+
try
158+
{
159+
Action<string> executeFile = path => jsEngine.ExecuteFile(path);
160+
161+
jsEngine.SetVariableValue("directoryPath", directoryPath);
162+
jsEngine.EmbedHostObject("executeFile", executeFile);
163+
jsEngine.ExecuteFile(Path.Combine(directoryPath, "mainFile.js"));
164+
165+
int output = jsEngine.GetVariableValue<int>(variableName);
166+
}
167+
catch (JsCompilationException e)
168+
{
169+
exception = e;
170+
}
171+
}
172+
173+
// Assert
174+
Assert.NotNull(exception);
175+
Assert.Equal("Compilation error", exception.Category);
176+
Assert.Equal("Unexpected token ILLEGAL", exception.Description);
177+
Assert.Equal("SyntaxError", exception.Type);
178+
Assert.Equal("secondFile.js", exception.DocumentName);
179+
Assert.Equal(1, exception.LineNumber);
180+
Assert.Equal(6, exception.ColumnNumber);
181+
Assert.Empty(exception.SourceFragment);
182+
}
183+
184+
[Fact]
185+
public void MappingRuntimeErrorDuringRecursiveExecutionOfFilesIsCorrect()
186+
{
187+
// Arrange
188+
const string directoryPath = "Files/recursiveExecution/runtimeError";
189+
const string variableName = "num";
190+
191+
// Act
192+
JsRuntimeException exception = null;
193+
194+
using (var jsEngine = CreateJsEngine())
195+
{
196+
try
197+
{
198+
Action<string> executeFile = path => jsEngine.ExecuteFile(path);
199+
200+
jsEngine.SetVariableValue("directoryPath", directoryPath);
201+
jsEngine.EmbedHostObject("executeFile", executeFile);
202+
jsEngine.ExecuteFile(Path.Combine(directoryPath, "mainFile.js"));
203+
204+
int output = jsEngine.GetVariableValue<int>(variableName);
205+
}
206+
catch (JsRuntimeException e)
207+
{
208+
exception = e;
209+
}
210+
}
211+
212+
// Assert
213+
Assert.NotNull(exception);
214+
Assert.Equal("Runtime error", exception.Category);
215+
Assert.Equal("nuм is not defined", exception.Description);
216+
Assert.Equal("ReferenceError", exception.Type);
217+
Assert.Equal("secondFile.js", exception.DocumentName);
218+
Assert.Equal(1, exception.LineNumber);
219+
Assert.Equal(1, exception.ColumnNumber);
220+
Assert.Equal("", exception.SourceFragment);
221+
Assert.Equal(
222+
"",
223+
exception.CallStack
224+
);
225+
}
226+
227+
[Fact]
228+
public void MappingHostErrorDuringRecursiveExecutionOfFilesIsCorrect()
229+
{
230+
// Arrange
231+
const string directoryPath = "Files/recursiveExecution/hostError";
232+
const string variableName = "num";
233+
234+
// Act
235+
FileNotFoundException exception = null;
236+
237+
using (var jsEngine = CreateJsEngine())
238+
{
239+
try
240+
{
241+
Action<string> executeFile = path => jsEngine.ExecuteFile(path);
242+
243+
jsEngine.SetVariableValue("directoryPath", directoryPath);
244+
jsEngine.EmbedHostObject("executeFile", executeFile);
245+
jsEngine.ExecuteFile(Path.Combine(directoryPath, "mainFile.js"));
246+
247+
int output = jsEngine.GetVariableValue<int>(variableName);
248+
}
249+
catch (FileNotFoundException e)
250+
{
251+
exception = e;
252+
}
253+
}
254+
255+
// Assert
256+
Assert.NotNull(exception);
257+
Assert.Equal("File '" + directoryPath + "/secondFile.jsx' not exist.", exception.Message);
258+
}
259+
260+
#endregion
18261

19262
#endregion
20263

0 commit comments

Comments
 (0)