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


Reply via email to