Hi Sundararajan, I created this gist with syntax highlighting for better readability: https://gist.github.com/jfrantzius/db6474f87300b45c887cdc2e45cd2dff
testObjectCreateInFunctionFails() shows where eval() seems to wrongly assume a different global and wraps unnecessarily. Regards, Jörg > Am 01.03.2017 um 09:27 schrieb Frantzius, Jörg <joerg.frantz...@aperto.com>: > > Hi Sundarajan, > > thx a lot for the explanations, this cleared the picture much for me. > > If you look at the second code snippet, though, it is not obvious where there > should be any crossing of global boundaries: > > SimpleScriptContext context = new SimpleScriptContext(); > context.setAttribute("f", engine.eval("(function () > {Object.create(this)})"), ScriptContext.ENGINE_SCOPE); > engine.eval("f.call({})", context); > > Here the function object is put into a ScriptContext that is then also passed > to eval() for invoking it, so there is no second ScriptContext involved. This > is in contrast to the first code snippet, where there is both a > SimpleBindings object and the engine’s default ScriptContext. > > By the way, if the last line passes „f" as „this“ instead of a new object > „{}": > > engine.eval("f.call(f)", context); > > Then the test succeeds. So the new object „{}“ seems to be associated with a > different global than that of the given ScriptContext, or at least Nashorn > thinks so? > > Does that mean eval() keeps or creates a global also when it is given a > ScriptContext or Bindings argument? Or is there maybe some wrapping going on > here that shouldn’t happen? > > Regards, > Jörg > > Am 01.03.2017 um 06:39 schrieb Sundararajan Athijegannathan > <sundararajan.athijegannat...@oracle.com<mailto:sundararajan.athijegannat...@oracle.com>>: > > Hi, > > In Nashorn, each ENGINE_SCOPE Bindings instance is associated with it's own > Nashorn global instance (an instance of jdk.nashorn.internal.objects.Global > class). i.e., each ENGINE_SCOPE Bindings instance is associated with a fresh > ECMAScript/JS global scope object - with it's own "Object", "Function", > "RegExp" etc. > > Nashorn represents script objects crossing JS global boundary as > ScriptObjectMirror instances. ScriptObjectMirror is also the way Java code > can access any script object (without having to deal with internal > jdk.nashorn.internal.runtime.ScriptObject). See also: > https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html > > If you access a script object from a JS global scope g1 from another JS > global scope g2, you'll get a ScriptObjectMirror wrap. Nashorn attempts to > provide seamless integration of ScriptObjectMirror instances - you can treat > ScriptObjectMirrors almost like those are script objects. But this > integration is not complete. Please see also: > https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes > > Not every JS API can work with ScriptObjectMirrors (like these APIs work with > script objects that belong to the "current" JS global scope). Object.create > is one such API. You can adjust your code slightly. For example: > > import javax.script.*; > import jdk.nashorn.api.scripting.*; > > public class Main { > public static void main(String[] args) throws Exception { > ScriptEngine e = new ScriptEngineManager().getEngineByName("nashorn"); > e.put("foo", e.eval("function() { return {} }", new SimpleBindings())); > // get "foo" > ScritptObjectMirror foo = (ScriptObjectMirror)e.get("foo"); > // eval Object.create in the global where "foo" belongs - with "foo" > set as "this" > System.out.println(foo.eval("Object.create(this)")); > } > } > > Hope this helps, > -Sundar > > On 01/03/17, 2:35 AM, Frantzius, Jörg wrote: > Hi, > in my code I’m running into an issue for which > https://github.com/coveo/nashorn-commonjs-modules/issues/3 luckily provides a > snippet for reproducing: > > @Test > public void testObjectCreateOnFunction() throws ScriptException { > ScriptEngine engine = new > ScriptEngineManager().getEngineByName("nashorn"); > engine.put("foo", engine.eval("function() { return {}; }", new > SimpleBindings())); > engine.eval("Object.create(foo());"); > } > > This fails with: > > Caused by:<eval>:1 TypeError: [object Object] is not an Object > at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:57) > at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:213) > at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:185) > at jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:172) > at jdk.nashorn.internal.objects.Global.checkObject(Global.java:2073) > at jdk.nashorn.internal.objects.NativeObject.create(NativeObject.java:261) > at jdk.nashorn.internal.scripts.Script$21$\^eval\_.:program(<eval>:1) > at > jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:623) > at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494) > at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393) > at > jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446) > ... 31 more > > In my own code, the pattern is slightly different, but it fails similarly > (SimpleScriptContext internally uses SimpleBindings as well): > > @Test > public void testObjectCreateInFunction() throws ScriptException { > ScriptEngine engine = new > ScriptEngineManager().getEngineByName("nashorn"); > SimpleScriptContext context = new SimpleScriptContext(); > context.setAttribute("f", engine.eval("(function () > {Object.create(this)})"), ScriptContext.ENGINE_SCOPE); > engine.eval("f.call({})", context); > } > > The issue seems to be that the function object internally isn’t turned from > ScriptObjectMirror into ScriptObject, so Global.checkObject() fails. > > I’d be thankful for any hints on whether this may be a bug or intended > behaviour. > > Regards, > Jörg > > > --- > > Dipl. Inf. Jörg von Frantzius, Technical Director > > E-Mail joerg.frantz...@aperto.com<mailto:joerg.frantz...@aperto.com> > > Phone +49 30 283921-318 > Fax +49 30 283921-29 > > Aperto GmbH – An IBM Company > Chausseestraße 5, D-10115 Berlin > http://www.aperto.com<http://www.aperto.de/> > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Geschäftsführer: Dirk Buddensiek, Kai Großmann, Stephan Haagen, Daniel Simon > > > > --- > > Dipl. Inf. Jörg von Frantzius, Technical Director > > E-Mail joerg.frantz...@aperto.com > > Phone +49 30 283921-318 > Fax +49 30 283921-29 > > Aperto GmbH – An IBM Company > Chausseestraße 5, D-10115 Berlin > http://www.aperto.com<http://www.aperto.de/> > http://www.facebook.com/aperto > https://www.xing.com/companies/apertoag > > HRB 77049 B, AG Berlin Charlottenburg > Geschäftsführer: Dirk Buddensiek, Kai Großmann, Stephan Haagen, Daniel Simon --- Dipl. Inf. Jörg von Frantzius, Technical Director E-Mail joerg.frantz...@aperto.com Phone +49 30 283921-318 Fax +49 30 283921-29 Aperto GmbH – An IBM Company Chausseestraße 5, D-10115 Berlin http://www.aperto.com http://www.facebook.com/aperto https://www.xing.com/companies/apertoag HRB 77049 B, AG Berlin Charlottenburg Geschäftsführer: Dirk Buddensiek, Kai Großmann, Stephan Haagen, Daniel Simon