gpt4 book ai didi

javascript - 在 Nashorn 中跨上下文共享原生 JavaScript 对象

转载 作者:行者123 更新时间:2023-11-30 00:17:52 26 4
gpt4 key购买 nike

我有一个 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));

现在我可以访问在原始范围内创建的所有内容,但这也为新上下文创建了一个全新的全局对象,这意味着像 Object 这样的原生 JS 对象的实例, 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因为在其他上下文中创建的对象被视为外来对象。

我正在尝试做的是公开一个公共(public)函数库并在单个脚本引擎实例中维护它。我不想继续重新创建脚本引擎实例,因为我最终失去了 JIT 优化(我在某处读到这个,但我现在找不到链接)。我确实喜欢对象“记住”它们的原始全局上下文这一事实,但我不希望这种情况发生在原生 JS 对象的情况下。

有没有办法创建一个全新的全局上下文,同时仍然共享 JS 全局对象实例?我已经尝试手动复制这些实例(枚举 this 的属性),但是当我将它们复制到新上下文时,它们是 ScriptObjectMirror 实例而不是展开的实例版本。我认为这是因为它们最初是在不同的环境中创建的,因此被认为是“外国的”。

最佳答案

不幸的是,这似乎是不可能的。我什至解开对象并取回 native 对象(我从主线程执行此操作),然后在新上下文中覆盖这些对象。不幸的是,这仍然行不通,因为在 Java 中表示 native 对象的 Java 类维护对创建的原始实例的内部引用(用于对象的原型(prototype))。

对于上述两种情况,我的解决方法是针对对象测试执行此操作:

var proto = Object.getPrototypeOf(object);
return (typeof proto.constructor !== "undefined" && (proto.constructor.name === Object.prototype.constructor.name));

对于 JSON,我通过评估 Douglas Crockford's JSON library 覆盖了原生 JSON 对象在主要上下文中,以及每个新上下文中。不过,我确实需要做一些修改才能让它在 Nashorn 中工作。第一个是让它重新定义 JSON 对象而不先检查它是否存在(所以只需删除 if 测试)。第二种是在 stringify 中使用对象本身的 hasOwnProperty。所以下面一行:

if (Object.prototype.hasOwnProperty.call(value, k))

更改为:

if (Object.prototype.hasOwnProperty.call(value, k) || (value.hasOwnProperty && value.hasOwnProperty(k)))

通过这两项更改,我能够让事情正常进行。

关于javascript - 在 Nashorn 中跨上下文共享原生 JavaScript 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34147164/

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