当eval带有绑定时,Nashorn找不到函数

Nashorn does not find function when eval with bindings

本文关键字:Nashorn 找不到 函数 定时 绑定 eval      更新时间:2023-09-26

当我计算有绑定或没有绑定的nashorn脚本时,有一个奇怪的区别:没有绑定调用函数没有问题,但是有了绑定就找不到函数了。下面是一个例子:

public class SimpleNashornTester {
    public static void main(String[] args) throws ScriptException, NoSuchMethodException {
        ScriptEngine jsEngine = new ScriptEngineManager().getEngineByName("nashorn");
        Compilable jsCompilable = (Compilable) jsEngine;
        Invocable jsInvocable = (Invocable) jsEngine;
        ScriptContext scriptCtxt = new SimpleScriptContext();
        Bindings engineScope = scriptCtxt.getBindings(ScriptContext.ENGINE_SCOPE);
        CompiledScript jsScript = jsCompilable.compile("function definition() {print('"Hello'")}");
        jsScript.eval(engineScope); // no error with jsScript.eval() !
        jsInvocable.invokeFunction("definition", new Object[] {});
    }
}

这会产生错误:

Exception in thread "main" java.lang.NoSuchMethodException: No such function definition
    at jdk.nashorn.api.scripting.ScriptObjectMirror.callMember(ScriptObjectMirror.java:204)

如果在脚本的求值中没有参数engineescope,则查找并调用函数。有人能解释一下这种差异吗?如何使用绑定而不出现错误?

您正在使用一个新的ScriptContext和它相关联的ENGINE_SCOPE绑定来编译脚本。invokeFunction/invokeMethod使用默认的ScriptContext(和它相关联的ENGINE_SCOPE绑定)来搜索函数。每个不同的ENGINE_SCOPE绑定都与它自己的ECMAScript全局对象(以及它自己的ECMAScript全局对象)相关联。

所以,你可以通过 修改你的程序
  1. 在调用之前将默认上下文更改为新上下文:

    // change the default ScriptContext
    jsEngine.setContext(scriptCtxt);
    jsInvocable.invokeFunction("definition", new Object[] {});
    
  2. 对于编译后的脚本也使用默认的ScriptContext。如:

    ScriptContext scriptCtxt = jsEngine.getContext(); // new SimpleScriptContext();