Surprising difference between /usr/bin/jjs and .getEngineByName("JavaScript")

Esben Andreasen esben at esbena.dk
Wed Dec 21 12:19:38 UTC 2016


Hi Hannes

Thank you for that explanation.

A follow-up, if allowed:
I understand the motivation for eliminating `undefined`, but I would really
like a way that I could avoid that elimination. Is that a discouraged use
of the API?

Implementation-wise:
I see that  `ScriptObjectMirror.translateUndefined` does the conversion
from JavaScript `undefined` to Java `null`.
I assume I could make a lightly edited copy of NashornScriptEngine.java
that omits the call to `translateUndefined` to get the effect I want. Or is
there a more elegant solution somewhere?


On Wed, Dec 21, 2016 at 11:40 AM Hannes Wallnöfer <
hannes.wallnoefer at oracle.com> wrote:

> Hi Esben,
>
> The reason you get null instead of undefined with the embedded script
> engine is that undefined is a language specific artefact that can’t be
> represented in Java. The script API translates undefined to null when it is
> returned by a script.
>
> Hannes
>
>
> > Am 21.12.2016 <21%2012%2020%2016> um 11:09 schrieb Esben Andreasen <
> esben at esbena.dk>:
> >
> > Hi
> >
> > I am not sure if this is a bug or a problem with my setup.
> > I observe a surprising difference between the "external" (jjs) and the
> > "internal" (new ScriptEngineManager().getEngineByName("JavaScript"))
> > Nashorn when evaluating a regular expression method. The two Nashorns
> seems
> > to be the same, but I am not sure how to check.
> >
> > Consider the following two interactions with Nashorn (output manually
> > transformed to have the same form):
> >
> > ```
> > Evaluating in internal Nashorn (new
> > ScriptEngineManager().getEngineByName("JavaScript")):
> >> java.lang.System.getProperty('java.version')
> > 1.8.0_111
> >> /(x)(y)?/.exec('x')[2]
> > null
> >
> > Evaluating in external Nashorn (/usr/bin/jjs):
> >> java.lang.System.getProperty('java.version')
> > 1.8.0_111
> >> /(x)(y)?/.exec('x')[2]
> > undefined
> > ```
> >
> > Observations:
> > 1. the Java version for both interactions is the same. I *think* this
> means
> > that the version of Nashorn is the same as well, but I am not sure.
> > 2. the two interactions disagree on `null/undefined` as the second entry
> of
> > the result array. The `undefined` value is the correct one according to
> > other JavaScript engines.
> >
> > Questions:
> > 1. Are the two Nashorns of the same version?
> > 2. Is the null/undefined discrepancy a bug?
> >
> > ---------------------------------------
> >
> > Additional content:
> >
> > The interactions with the Nashorns where performed with the following
> Java
> > class:
> >
> > ```
> > import javax.script.ScriptEngine;
> > import javax.script.ScriptEngineManager;
> > import javax.script.ScriptException;
> > import java.io.BufferedReader;
> > import java.io.IOException;
> > import java.io.InputStreamReader;
> > import java.nio.file.Files;
> > import java.nio.file.Path;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > import java.util.List;
> > import java.util.function.Function;
> >
> > public class NashornTest {
> >
> > public static void main(String[] args) throws ScriptException,
> IOException,
> > InterruptedException {
> > String javaVersionScript =
> "java.lang.System.getProperty('java.version')";
> > String execScript = "/(x)(y)?/.exec('x')[2]";
> >
> > showEvaluation("Evaluating in internal Nashorn (new
> > ScriptEngineManager().getEngineByName(\"JavaScript\")):",
> > NashornTest::evaluateInternally, javaVersionScript, execScript);
> > System.out.println();
> > showEvaluation("Evaluating in external Nashorn (/usr/bin/jjs):",
> > NashornTest::evaluateExternally, javaVersionScript, execScript);
> > }
> >
> > private static void showEvaluation(String title, Function<String, String>
> > evaluator, String... scripts) {
> > System.out.println(title);
> > for (String script : scripts) {
> > System.out.println("\t> " + script);
> > System.out.println("\t" + evaluator.apply(script));
> > }
> > }
> >
> > private static String evaluateInternally(String script) {
> > ScriptEngine engine = new
> > ScriptEngineManager().getEngineByName("JavaScript");
> > try {
> > return engine.eval(script) + "";
> > } catch (ScriptException e) {
> > throw new RuntimeException(e);
> > }
> > }
> >
> > private static String evaluateExternally(String script) {
> > Path scriptFile = null;
> > try {
> > scriptFile = Files.createTempFile("script", ".js");
> > Files.write(scriptFile, Arrays.asList(String.format("print(%s);",
> script)));
> >
> > Process process = Runtime.getRuntime().exec(new String[]{"/usr/bin/jjs",
> > scriptFile.toAbsolutePath().toString()});
> > BufferedReader stdInput = new BufferedReader(new
> > InputStreamReader(process.getInputStream()));
> > List<String> lines = new ArrayList<>();
> > String line;
> > while ((line = stdInput.readLine()) != null) {
> > lines.add(line);
> > }
> > return String.join("\n", lines);
> > } catch (IOException e) {
> > throw new RuntimeException(e);
> > }
> > }
> > }
> >
> > ```
>
>


More information about the nashorn-dev mailing list