【发布时间】:2015-12-08 02:53:24
【问题描述】:
我有一个 Nashorn 引擎,我在其中评估了一些脚本,这些脚本公开了一些常见的实用功能和对象。我希望自定义脚本在它们自己的上下文中运行,而不是相互交叉,因此我使用 engine.createBindings() 为它们创建新的上下文:
ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
newContext.getBindings(ScriptContext.ENGINE_SCOPE).putAll(engine.getBindings(ScriptContext.ENGINE_SCOPE));
现在我可以访问在原始范围内创建的所有内容,但这也为新上下文创建了一个全新的全局对象,这意味着本机 JS 对象的实例,如 Object、Number、等与原始上下文中的对应实例不同。
这会导致一些奇怪的行为。例如,假设您有以下在引擎中评估的代码(即“父”上下文):
function foo(obj) {
print(JSON.stringify(obj, null, 4));
print(Object.getPrototypeOf(obj) === Object.prototype);
}
现在假设您的自定义脚本如下:
function bar() {
foo({a: 10, b: 20});
}
我根据newContext 对此进行评估,然后调用该函数:
engine.eval(source, newContext);
ScriptObjectMirror foo = newContext.getAttribute("foo", ScriptContext.ENGINE_SCOPE);
foo.call(null);
这会返回:
undefined
false
这是expected behavior,因为在其他上下文中创建的对象被视为外来对象。
我想要做的是公开一个通用函数库并在单个脚本引擎实例中维护它。我不想继续重新创建脚本引擎实例,因为我最终会丢失 JIT 优化(我在某处读过这个,但我现在找不到链接)。我确实喜欢对象“记住”它们的原始全局上下文这一事实,但我不希望在原生 JS 对象的情况下发生这种情况。
有没有办法创建一个全新的全局上下文,同时仍然共享 JS 全局对象实例?我已经尝试手动复制这些实例(枚举this 的属性),但是当我将它们复制到新上下文时,它们是ScriptObjectMirror 实例而不是解包版本。我认为这是因为它们最初是在不同的上下文中创建的,因此被认为是“外来的”。
【问题讨论】:
标签: javascript java nashorn