I am trying to run a javascript script with the new Java 8 Nashorn javascript engine but it fails with the following error:
<eval>:1 ReferenceError: "readFully" is not defined
The script uses the readFully function that should be defined in the global scope nashorn is run with the scripting mode enabled (wich is default when running through a ScriptEngine as seen here http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-December/002562.html).
Here is a sample to reproduce the error:
import java.io.FileNotFoundException;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
public class Test {
public static void main(String[] argv) throws FileNotFoundException, ScriptException {
ScriptEngine scriptEngine = new ScriptEngineManager().getEngineByName("nashorn");
scriptEngine.eval("print('Hey!');print(print);print(readFully);");
}
}
This sample prints Hey ! and then the source code of the print function (another nashorn built-in function) and finally it should print the source code of the readFully method. But I have this Exception instead:
Exception in thread "main" javax.script.ScriptException: ReferenceError: "readFully" is not defined in <eval> at line number 1
at jdk.nashorn.api.scripting.NashornScriptEngine.throwAsScriptException(NashornScriptEngine.java:586)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:570)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:525)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:521)
at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:192)
at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)
at com.github.bringking.maven.requirejs.Test.main(Test.java:14)
Caused by: <eval>:1 ReferenceError: "readFully" is not defined
at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:58)
at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:320)
at jdk.nashorn.internal.runtime.ECMAErrors.referenceError(ECMAErrors.java:292)
at jdk.nashorn.api.scripting.NashornScriptEngine.__noSuchProperty__(NashornScriptEngine.java:272)
at jdk.nashorn.internal.scripts.Script$engine.L:35(nashorn:engine/resources/engine.js:37)
at jdk.nashorn.internal.scripts.Script$\^eval\_.runScript(<eval>:1)
at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:535)
at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:209)
at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:378)
at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:568)
... 5 more
When the sample script is run with the nashorn command line with the -scripting parameter (with the jjs tool of the jdk), all is fine. Here is the result of the same script:
Hey!
function print() { [native code] }
function readFully() { [native code] }
I could rewrite a readFully method and bind it with the script context, but I prefer to understand why it does not work and use already built-in functions.
Regards
Technical Article. Until Java SE 7, JDKs shipped with a JavaScript scripting engine based on Mozilla Rhino. Java SE 8 will instead ship with a new engine called Oracle Nashorn, which is based on JSR 292 and invokedynamic .
Nashorn: Nashorn is a JavaScript engine which is introduced in JDK 8. With the help of Nashorn, we can execute JavaScript code at Java Virtual Machine. Nashorn is introduced in JDK 8 to replace existing JavaScript engine i.e. Rhino.
With the release of Java 11, Nashorn was deprecated citing challenges to maintenance, and has been removed from JDK 15 onwards. Nashorn development continues on GitHub as a standalone OpenJDK project and the separate release can be used in Java project from Java 11 and up.
Finally, I have implemented a readFully function that I use in my script (Only compatible with Nashorn):
function readFully(url) {
var result = "";
var imports = new JavaImporter(java.net, java.lang, java.io);
with (imports) {
var urlObj = null;
try {
urlObj = new URL(url);
} catch (e) {
// If the URL cannot be built, assume it is a file path.
urlObj = new URL(new File(url).toURI().toURL());
}
var reader = new BufferedReader(new InputStreamReader(urlObj.openStream()));
var line = reader.readLine();
while (line != null) {
result += line + "\n";
line = reader.readLine();
}
reader.close();
}
return result;
}
readFully is not a standard JavaScript function and it is likely not standard in Nashorn either.
There were similar issues when Rhino was chosen for inclusion in the Sun implementation of Java 6. The scripting tool may provide enhancements that are not present in the embedded API. readFully is not a documented function in the Java 8 Nashorn API.
In previous versions of Java the specification stated that provided scripting engines were an implementation detail of the JRE vendor. I am not aware if Java 8 makes anything about the engines provided mandatory or whether it makes any future compatibility guarantees. I would check JSR-337 thoroughly if this was likely to be an issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With