Search code examples
javajava-8nashorn

Get Nashorn script line number during interpretation


My code uses Nashorn to provide scripting functionality to the user, with many classes and functions implemented on Java exposed to the scripts through Nashorn.

One of the tasks of the program is of course to report any errors relating to the scripts to the user when encountered. This is very simple if a ScriptException occurs, as simply catching the exception and using the method getLineNumber() returns the correct value. However, occasionally an exception occurs not due to the syntax, but due to the way the Java-side code is called, for example due to a null parameter which was supposed to be a valid object. These cause other kinds of exceptions, which can still be caught around the call to the eval method, but since these do not have a getLineNumber() method its impossible to guess where the interpreter was left.

Is there a way I can get the last executed line somehow from the Nashorn engine?

The code roughly looks like this:

try {
    engine.eval( script);       
    // successful
    return -1;
} catch ( ScriptException e)
{
    // the ScriptException reports the line number
    return e.getLineNumber();
}
catch ( Exception e)
{
    // is it possible to get the line number here too?
    // ... 
    return lineNumber;
}

Solution

  • There is a standard Nashorn API to get StackTraceElement[] for "script frames" from a given arbitrary Throwable object.

    jdk.nashorn.api.scripting.NashornException class has

    public static StackTraceElement[] getScriptFrames(Throwable exception)

    method

    https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/NashornException.html#getScriptFrames-java.lang.Throwable-

    You can pass arbitrary Throwable object and get back StackTraceElement array for the script frames. The top most script frame would be the zero'th element of the array and you can call getLineNumber on the StackTraceElement object.

    This way, you can avoid dependency on nashorn internal package prefixes.