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.Executein our owntryblock, and re-throw with theEngine.GetLastSyntaxNode().Location.Startvalues. 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
locationobject was _always_ part of theJavaScriptExceptionobject.