在评估脚本后读取更新的变量

时间:2014-06-10 13:59:13

标签: java jsr223 nashorn

我正在测试一些与Rhino一起使用的JSR 223(脚本)代码,以了解它如何与Nashorn一起使用。差异的一个方面是处理通过Bindings参数传递给engine.eval()的变量的更新。在Rhino中,我可以在评估脚本时使用此方法传递动态变量绑定,然后在执行脚本后读出这些变量的任何更新值。但是,在Nashorn中,这不起作用 - 在执行脚本之后,Bindings对象中所有变量的值仍然存在其初始值。

用TestNG测试用例说明:

@Test
public void shouldSupportReadingVariablesFromBindings() throws Exception {
    // Given
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
    Bindings vars = new SimpleBindings();
    vars.put("state", 1);

    // When
    engine.eval("state = 2", vars);
    Number result = (Number) vars.get("state");

    // Then
    assertEquals(result.intValue(), 2);

}

使用Rhino(Mac OS X 10.9.3上的Apple JDK 1.6.0_65)测试通过。使用Nashorn(Oracle JDK 1.8.0_b132)它失败了。我之后尝试了各种不同的方法来阅读变量 - 调用engine.get()engine.getBindings(ScriptContext.ENGINE_SCOPE).get()engine.getContext().getBindings(...).get()等。结果始终是null

可以让它工作,如果我调用engine.put("state", 1),然后用engine.get("state")读取它,但与传递绑定相比,这似乎有点混乱一个论点。

阅读JSR-223规范,我找不到任何支持这种用法的措辞,它是否特定于引擎?还有其他方法可以在Nashorn完成我想要的东西吗?

编辑:一种方法是将每个变量包装在AtomicReference中,然后在Javascript中调用显式.set(..)方法。丑陋,但可能是可行的。

1 个答案:

答案 0 :(得分:2)

如果传递使用ScriptEngine.createBindings创建的Bindings,Nashorn会将更新后的值存储在Bindings中。 (我测试了。)

根据the OpenJDK wikithis OpenJDK bug,预计Rhino和Nashorn之间存在这种行为差异。 Nashorn并不打算与Rhino 100%兼容。