Estou construindo um motor que usa Jint para executar um arquivo javascript com várias funções.
O problema é que se houver
tudo o que você obtém do Jint é uma JavaScriptException sem contexto de onde o erro ocorreu.
No momento, estou relegado a adicionar instruções de log apenas para encontrar o problema no script.
Seria extremamente útil se qualquer lançamento de Error () viesse com a propriedade stack preenchida com o stacktrace das funções js.
Eu tive o mesmo problema, onde alguns scripts longos seriam extremamente difíceis de depurar. O que fizemos foi embrulhar Engine.Execute
em nosso próprio bloco try
e re-lançar com os valores de Engine.GetLastSyntaxNode().Location.Start
. Exemplo:
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);
}
Observe que seria muito melhor se o objeto location
fosse _sempre_ parte do objeto JavaScriptException
.
Obrigado, isso é muito útil.
Ainda acho que seria muito valioso ter um stacktrace disponível. O motivo é que (no meu caso) o script é montado dinamicamente, portanto, ir de um número de linha para a linha real no script dinâmico exige um pouco mais de trabalho.
Para alguns erros de análise, encontrei também a exceção Esprima.ParserException
.
E achei útil adicionar também o texto da linha que causou o erro (conforme impresso na exceção ClearScript)
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;
}
Comentários muito úteis
Eu tive o mesmo problema, onde alguns scripts longos seriam extremamente difíceis de depurar. O que fizemos foi embrulhar
Engine.Execute
em nosso próprio blocotry
e re-lançar com os valores deEngine.GetLastSyntaxNode().Location.Start
. Exemplo: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); }
Observe que seria muito melhor se o objeto
location
fosse _sempre_ parte do objetoJavaScriptException
.