I'm building an engine that uses Jint to execute a javascript file with a bunch of functions.
The problem is that if there is
all you get out of Jint is a JavaScriptException with no context as to where the error occurred.
Right now I'm relegated to adding log statements just to find the problem in the script.
It would be extremely helpful if any throwing of Error() would come with the stack property filled in with the stacktrace of the js functions.
I had the same problem, where some long scripts would be extremely hard to debug. What we did is wrap Engine.Execute
in our own try
block, and re-throw with the Engine.GetLastSyntaxNode().Location.Start
values. Example:
c#
var engine = new Engine();
try
{
engine.Execute("some code that throws...");
}
catch(JavaScriptException exc)
{
var location = engine.GetLastSyntaxNode().Location.Start;
throw new ApplicationException(
String.Format("{0} (Line {1}, Column {2})",
exc.Error,
location.Line,
location.Column
), exc);
}
Note that it would be much better if the location
object was _always_ part of the JavaScriptException
object.
Thanks, that is very helpful.
I still think it would be very valuable to have a stacktrace available. The reason is that (in my case) the script is dynamically assembled, so getting from a line number to the actual line in the dynamic script takes a little extra work.
For some parsing errors I encountered also the Esprima.ParserException
exception.
And I found useful to add also the text of the line causing the error (as printed in ClearScript exception)
public void Run(string script)
{
JintEngine.Execute(script);
catch (Esprima.ParserException ex)
{
throw new ApplicationException($"{ex.Error} (Line {ex.LineNumber}, Column {ex.Column}), -> {ReadLine(script, ex.LineNumber)})", ex);
}
catch (Jint.Runtime.JavaScriptException ex)
{
throw new ApplicationException($"{ex.Error} (Line {ex.LineNumber}, Column {ex.Column}), -> {ReadLine(script, ex.LineNumber)})", ex);
}
}
private static string ReadLine(string text, int lineNumber)
{
using var reader = new System.IO.StringReader(text);
string line;
int currentLineNumber = 0;
do
{
currentLineNumber += 1;
line = reader.ReadLine();
}
while (line != null && currentLineNumber < lineNumber);
return (currentLineNumber == lineNumber) ? line : string.Empty;
}
Most helpful comment
I had the same problem, where some long scripts would be extremely hard to debug. What we did is wrap
Engine.Execute
in our owntry
block, and re-throw with theEngine.GetLastSyntaxNode().Location.Start
values. Example:c# var engine = new Engine(); try { engine.Execute("some code that throws..."); } catch(JavaScriptException exc) { var location = engine.GetLastSyntaxNode().Location.Start; throw new ApplicationException( String.Format("{0} (Line {1}, Column {2})", exc.Error, location.Line, location.Column ), exc); }
Note that it would be much better if the
location
object was _always_ part of theJavaScriptException
object.