gpt4 book ai didi

java - 原型(prototype)在 nashorn 中从 globalscope 更改为 enginescope

转载 作者:行者123 更新时间:2023-12-01 14:27:48 27 4
gpt4 key购买 nike

我正在尝试将一些库预加载到全局范围内(例如 chai.js)。这改变了一些对象的原型(prototype),我意识到这适用于 ENGINE_SCOPE 但不适用于 GLOBAL_SCOPE。

最小的例子:

ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
Bindings globalBindings = engine.createBindings();
engine.eval("Object.prototype.test = function(arg){print(arg);}", globalBindings);

//works as expected, printing "hello"
engine.getContext().setBindings(globalBindings, ScriptContext.ENGINE_SCOPE);
engine.eval("var x = {}; x.test('hello');");

//throws TypeError: null is not a function in <eval> at line number 1
engine.getContext().setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
engine.getContext().setBindings(globalBindings, ScriptContext.GLOBAL_SCOPE);
engine.eval("var x = {}; x.test('hello');");

是否有解决方法使其按预期工作,即更改从全局范围正确传播到引擎范围?

最佳答案

为什么你的代码不起作用

全局作用域只能用于简单的变量映射。例如:

ScriptContext defCtx = engine.getContext();
defCtx.getBindings(ScriptContext.GLOBAL_SCOPE).put("foo", "hello");

Object 存在于引擎范围内,因此甚至不会在全局范围内搜索与其相关的任何映射(在您的情况下为 Object.prototype.test)。

文档摘录:

The default context's ENGINE_SCOPE is a wrapped instance of ECMAScript "global" object - which is the "this" in top level script expressions. So, you can access ECMAScript top-level objects like "Object", "Math", "RegExp", "undefined" from this scope object. Nashorn Global scope object is represented by an internal implementation class called jdk.nashorn.internal.objects.Global. Instance of this class is wrapped as a jdk.nashorn.api.scripting.ScriptObjectMirror instance. ScriptObjectMirror class implements javax.script.Bindings interface. Please note that the context's GLOBAL_SCOPE Bindings and nashorn global object are different. Nashorn's global object is associated with ENGINE_SCOPE and not with GLOBAL_SCOPE. GLOBAL_SCOPE object of default script context is a javax.script.SimpleBindings instance.The user can fill it with name, value pairs from the java code.

https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes

解决方案

  1. 继续使用引擎作用域
  2. 通过在 Java 命令行中指定 -Dnashorn.args=--global-per-engine 来使用 --global-per-engine 选项。然后 Nashorn 将使用全局对象的单个实例进行所有脚本评估,无论是否传递了 ScriptContext。
  3. 使用成熟的 ScriptContext 而不是 Bindings:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
SimpleScriptContext context = new SimpleScriptContext();
engine.eval("Object.prototype.test = function(arg){print(arg);}", context);
engine.eval("var x = {}; x.test('hello');", context);

如何运行多个脚本,每次都加载库,但之前的执行没有留下任何东西

每次您需要一个带有库的新上下文时,只需创建它:

public static void main(String[] args) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
SimpleScriptContext context1 = createContextWithLibraries(engine);
//works as expected, printing "hello"
engine.eval("var x = {}; x.test('hello'); var y = 'world';", context1);
SimpleScriptContext context2 = createContextWithLibraries(engine);
//works as expected, printing "hello"
engine.eval("var x = {}; x.test('hello');", context2);
//works as expected, printing "world"
engine.eval("print(y);", context1);
//fails with exception since there is no "y" variable in context2
engine.eval("print(y);", context2);
}

private static SimpleScriptContext createContextWithLibraries(ScriptEngine engine) throws ScriptException {
SimpleScriptContext context = new SimpleScriptContext();
engine.eval("Object.prototype.test = function(arg){print(arg);}", context);
return context;
}

关于java - 原型(prototype)在 nashorn 中从 globalscope 更改为 enginescope,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60946483/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com