我正在测试一些与 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 中完成我想要的吗?
编辑:一种可行的方法是将每个变量包装在 an 中AtomicReference
,然后.set(..)
在 Javascript 中调用显式方法。丑陋,但可能可行。