Object.create() fails on function in SimpleBindings

Sundararajan Athijegannathan sundararajan.athijegannathan at oracle.com
Wed Mar 1 05:39:30 UTC 2017


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.frantzius at 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
>


More information about the nashorn-dev mailing list