I have a Nashorn engine in which I evaluate some scripts that expose some common utility functions and objects. I want custom scripts to run in their own contexts and not step over each other, so I create new contexts for them using engine.createBindings():
ScriptContext newContext = new SimpleScriptContext(); newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE); newContext.getBindings(ScriptContext.ENGINE_SCOPE).putAll(engine.getBindings(ScriptContext.ENGINE_SCOPE)); Now I have access to everything that was created in the original scope, but this also creates an entirely-new global-object for the new context, which means that instances of native JS objects like Object, Number, etc. are different from corresponding instances in the original context. This leads to some strange behavior. For example, assume you have the following code that was evaluated in the engine (i.e., the "parent" context"): function foo(obj) { print(JSON.stringify(obj, null, 4)); print(Object.getPrototypeOf(obj) === Object.prototype);} Now let's say your custom script is as follows: function bar() { foo({a: 10, b: 20});} I evaluate this against newContext and then invoke the function: engine.eval(source, newContext);ScriptObjectMirror foo = newContext.getAttribute("foo", ScriptContext.ENGINE_SCOPE); foo.call(null); This returns: undefinedfalse This is expected behavior <https://bugs.openjdk.java.net/browse/JDK-8067642> because objects created in other contexts are treated as foreign objects. What I'm trying to do is to expose a common library of functions and maintain that within a single script-engine instance. I don't want to keep recreating script-engine instances because I end up losing JIT optimizations (I read this somewhere, but I can't find the link right now). I do like the fact that objects "remember" their originating global-context, but I'd like that not to happen in the case of native JS objects. Is there a way to create an entirely-new global context, while still sharing JS global-object instances? I've tried manually copying over these instances (enumerating the properties of this), but when I copy them over to the new context, they are ScriptObjectMirror instances and not the unwrapped versions. I assume this is because they were originally created in a different context and therefore are considered to be "foreign". I'm also open to doing this in a completely different manner. I looked at using --global-per-engine, but I noticed that anything exposed by the custom script seemed to end up in the main context instead of the new context that I have created. In general I'm just looking for a way to have isolated execution contexts while still sharing native JS object instances across these contexts. Thanks! -- Ruin untold; And thine own sadness, Sing in the grass, When eve has forgot, that no more hear common things that gleam and pass; But seek alone to lip, sad Rose of love and ruin untold; And thine own mother Can know it as I know More than another What makes your own sadness, Set in her eyes. map{@n=split//;$j.=$n[0]x$n[1]}split/:/,"01:11:02". ":11:01:11:02:13:01:11:01:11:01:13:02:12:01:13:01". ":11:04:11:06:12:04:11:01:12:01:13:02:12:01:14:01". ":13:01:11:03:12:01:11:04:12:02:11:01:11:01:13:02". ":11:03:11:06:11:01:11:05:12:02:11:01:11:01:13:02". ":11:02:12:01:12:04:11:06:12:01:11:04:12:04:11:01". ":12:03:12:01:12:01:11:01:12:01:12:02:11:01:11:01". ":13:02:11:01:02:11:01:12:02";map{print chr unpack" i",pack"B32",$_}$j=~m/.{8}/g