我正在测试一些与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(..)
方法。丑陋,但可能是可行的。
答案 0 :(得分:2)
如果传递使用ScriptEngine.createBindings创建的Bindings,Nashorn会将更新后的值存储在Bindings中。 (我测试了。)
根据the OpenJDK wiki和this OpenJDK bug,预计Rhino和Nashorn之间存在这种行为差异。 Nashorn并不打算与Rhino 100%兼容。