Search code examples
javascriptjavarhinonashorn

Access variable of ScriptContext using Nashorn JavaScript Engine (Java 8)


I used the following code with the Rhino JavaScript engine in Java:

@Test
public void testRhino() throws ScriptException {
    final ScriptEngineManager factory = new ScriptEngineManager();
    final ScriptEngine engine = factory.getEngineByName("rhino");
    final String raw = "I am the raw value injected";
    final ScriptContext ctx = new SimpleScriptContext();
    ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);

    String script = "var result = 'I am a result';";
    script += "java.lang.System.out.println(raw);";
    script += "'I am a returned value';";

    final Object res = engine.eval(script, ctx);
    System.out.println(ctx.getAttribute("result"));
    System.out.println(res);
}

The output of the script (using Rhino) is:

I am the raw value injected
I am a result
I am a returned value

Within the Nashorn JavaScript engine, I get no value for the result:

@Test
public void testNashorn() throws ScriptException {
    final ScriptEngineManager factory = new ScriptEngineManager();
    final ScriptEngine engine = factory.getEngineByName("nashorn");
    final String raw = "I am the raw value injected";
    final ScriptContext ctx = new SimpleScriptContext();
    ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);

    String script = "var result = 'I am a result';";
    script += "java.lang.System.out.println(raw);";
    script += "'I am a returned value';";

    final Object res = engine.eval(script, ctx);
    System.out.println(ctx.getAttribute("result"));
    System.out.println(res);
}

returns

I am the raw value injected
null
I am a returned value

How can I access the value of the result variable of the ScriptContext using the nashorn engine?


Solution

  • If you use ScriptEngine.createEngine API to create ENGINE_SCOPE Bindings, it'll work as expected:

    import javax.script.*;
    
    public class Main {
      public static void main(String[] args) throws Exception {
    
        final ScriptEngineManager factory = new ScriptEngineManager();
        final ScriptEngine engine = factory.getEngineByName("nashorn");
        final String raw = "I am the raw value injected";
        final ScriptContext ctx = new SimpleScriptContext();
    
        // **This is the inserted line**
        ctx.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
    
        ctx.setAttribute("raw", raw, ScriptContext.ENGINE_SCOPE);
    
        String script = "var result = 'I am a result';";
        script += "java.lang.System.out.println(raw);";
        script += "'I am a returned value';";
    
        final Object res = engine.eval(script, ctx);
        System.out.println(ctx.getAttribute("result"));
        System.out.println(res);
     }
    }