From sundararajan.athijegannathan at oracle.com Wed Mar 1 05:39:30 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Wed, 01 Mar 2017 11:09:30 +0530 Subject: Object.create() fails on function in SimpleBindings In-Reply-To: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> References: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> Message-ID: <58B65E92.2050507@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::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(: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.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 > From Joerg.Frantzius at aperto.com Wed Mar 1 08:27:35 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Wed, 1 Mar 2017 08:27:35 +0000 Subject: Object.create() fails on function in SimpleBindings In-Reply-To: <58B65E92.2050507@oracle.com> References: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> <58B65E92.2050507@oracle.com> Message-ID: <7E5D3470-1F38-409D-80D2-FD1D06876479@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 >: 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::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(: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.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.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.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 From Joerg.Frantzius at aperto.com Wed Mar 1 08:51:59 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Wed, 1 Mar 2017 08:51:59 +0000 Subject: Object.create() fails on function in SimpleBindings In-Reply-To: <7E5D3470-1F38-409D-80D2-FD1D06876479@aperto.com> References: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> <58B65E92.2050507@oracle.com> <7E5D3470-1F38-409D-80D2-FD1D06876479@aperto.com> Message-ID: <932FFF75-B82F-4400-8833-3DD019BB3753@aperto.com> 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 : > > 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 >: > > 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::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(: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.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.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.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.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.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 From sundararajan.athijegannathan at oracle.com Wed Mar 1 10:28:57 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Wed, 01 Mar 2017 15:58:57 +0530 Subject: Object.create() fails on function in SimpleBindings In-Reply-To: <932FFF75-B82F-4400-8833-3DD019BB3753@aperto.com> References: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> <58B65E92.2050507@oracle.com> <7E5D3470-1F38-409D-80D2-FD1D06876479@aperto.com> <932FFF75-B82F-4400-8833-3DD019BB3753@aperto.com> Message-ID: <58B6A269.3070908@oracle.com> Hi J?rg, Actually you're dealing with two JS global scopes in this case as well! The first eval ("function() { Object.create(this) }") is evaluating code using the script engine default context - which has it's own ENGINE_SCOPE Bindings and it's associated JS global scope object. In your second eval, you're using a fresh (non-default) ScriptContext - which has it's own ENGINE_SCOPE Bindings (and hence it's own associated JS global which is different from that of the engine's default ScriptContext)! "this" in Object.create(this) call in your first eval would be the "this" object passed to function "f". You're passing an object created another context's ENGINE_SCOPE as param! I changed your code to use the same (non-default) context for both the eval calls (to force the same JS global in Object.create calling eval and the caller eval). The modified code below works. import javax.script.*; import jdk.nashorn.api.scripting.*; public class Main { public static void main(String[] args) throws Exception { ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); SimpleScriptContext context = new SimpleScriptContext(); // It was -> context.setAttribute("f", engine.eval("(function () {Object.create(this)})"), ScriptContext.ENGINE_SCOPE); context.setAttribute("f", engine.eval("(function () {Object.create(this)})", context), ScriptContext.ENGINE_SCOPE); engine.eval("f.call({})", context); } } Hope this explains, -Sundar On 01/03/17, 2:21 PM, Frantzius, J?rg wrote: > 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: >> >> 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>: >> >> 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::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(: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.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.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.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.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.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 > > From Joerg.Frantzius at aperto.com Wed Mar 1 15:10:10 2017 From: Joerg.Frantzius at aperto.com (=?utf-8?B?RnJhbnR6aXVzLCBKw7ZyZw==?=) Date: Wed, 1 Mar 2017 15:10:10 +0000 Subject: Object.create() fails on function in SimpleBindings In-Reply-To: <58B6A269.3070908@oracle.com> References: <6498197B-39BB-45E0-87B4-8E91513E9EFB@aperto.com> <58B65E92.2050507@oracle.com> <7E5D3470-1F38-409D-80D2-FD1D06876479@aperto.com> <932FFF75-B82F-4400-8833-3DD019BB3753@aperto.com> <58B6A269.3070908@oracle.com> Message-ID: <0CABA929-E8B3-4C8B-9F99-956D0F975D4A@aperto.com> Hi Sundararajan, thanks for pointing out the missing context argument, you are absolutely right. Back to the drawing board for me? Regards, J?rg Am 01.03.2017 um 11:28 schrieb Sundararajan Athijegannathan >: Hi J?rg, Actually you're dealing with two JS global scopes in this case as well! The first eval ("function() { Object.create(this) }") is evaluating code using the script engine default context - which has it's own ENGINE_SCOPE Bindings and it's associated JS global scope object. In your second eval, you're using a fresh (non-default) ScriptContext - which has it's own ENGINE_SCOPE Bindings (and hence it's own associated JS global which is different from that of the engine's default ScriptContext)! "this" in Object.create(this) call in your first eval would be the "this" object passed to function "f". You're passing an object created another context's ENGINE_SCOPE as param! I changed your code to use the same (non-default) context for both the eval calls (to force the same JS global in Object.create calling eval and the caller eval). The modified code below works. import javax.script.*; import jdk.nashorn.api.scripting.*; public class Main { public static void main(String[] args) throws Exception { ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn"); SimpleScriptContext context = new SimpleScriptContext(); // It was -> context.setAttribute("f", engine.eval("(function () {Object.create(this)})"), ScriptContext.ENGINE_SCOPE); context.setAttribute("f", engine.eval("(function () {Object.create(this)})", context), ScriptContext.ENGINE_SCOPE); engine.eval("f.call({})", context); } } Hope this explains, -Sundar On 01/03/17, 2:21 PM, Frantzius, J?rg wrote: 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>: 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>: 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::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(: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.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.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.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.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.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.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.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 From srinivas.dama at oracle.com Thu Mar 2 14:36:04 2017 From: srinivas.dama at oracle.com (Srinivas Dama) Date: Thu, 2 Mar 2017 06:36:04 -0800 (PST) Subject: RFR: 8156743: ES6 for..of should work for Java Maps and Sets Message-ID: Hello, Please review http://cr.openjdk.java.net/~sdama/8156743/webrev.00/ for https://bugs.openjdk.java.net/browse/JDK-8156743 Regards, Srinivas From szegedia at gmail.com Thu Mar 2 15:31:07 2017 From: szegedia at gmail.com (Attila Szegedi) Date: Thu, 2 Mar 2017 16:31:07 +0100 Subject: RFR: 8156743: ES6 for..of should work for Java Maps and Sets In-Reply-To: References: Message-ID: <3FB336BF-67CE-4D78-946B-5633E66682C2@gmail.com> Contrary to the issue name, I don?t see anything for handling Set in the patch, but I guess that?s because Set is a Collection and those already work? As an aside? I was looking into your use of NativeJava.from to convert a Java array to a NativeArray, and realized that we have at least 3 ways to do it, each with different drawbacks: 1. NativeJava.from as used in this patch. Its drawback is that it defensively always clones the array (here we woulnd?t need to clone it, although it doesn?t hurt) 2. Global.instance.wrapAsObject. Its drawback is that its Object[] case is further down the if/else list than NativeJava.from (5th instanceof vs. 2nd) 3. Global.instance.allocate. (This one is primarily used from generated bytecode.) Its drawback is that it iterates over the elements scanning for any ScriptRuntime.EMPTY values. I guess we could pass in a boolean flag to indicate there are no empty values to skip this scan (compiler could set the flag when it can prove the array literal it?s constructing has no empties). This doesn?t affect your patch - I think NativeJava.from() is a decent choice. So, +1. Attila. > On 02 Mar 2017, at 15:36, Srinivas Dama wrote: > > Hello, > > Please review http://cr.openjdk.java.net/~sdama/8156743/webrev.00/ > for https://bugs.openjdk.java.net/browse/JDK-8156743 > > Regards, > Srinivas > From sundararajan.athijegannathan at oracle.com Thu Mar 2 15:52:12 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Thu, 02 Mar 2017 21:22:12 +0530 Subject: RFR: 8156743: ES6 for..of should work for Java Maps and Sets In-Reply-To: References: Message-ID: <58B83FAC.4050201@oracle.com> Quick comment: File: ScriptRuntime.java 404 if (obj != null && obj instanceof Map) { should just be if (obj instanceof Map) { -Sundar On 02/03/17, 8:06 PM, Srinivas Dama wrote: > Hello, > > Please review http://cr.openjdk.java.net/~sdama/8156743/webrev.00/ > for https://bugs.openjdk.java.net/browse/JDK-8156743 > > Regards, > Srinivas > From james.laskey at oracle.com Thu Mar 2 16:34:21 2017 From: james.laskey at oracle.com (James Laskey) Date: Thu, 2 Mar 2017 12:34:21 -0400 Subject: RFR: 8156743: ES6 for..of should work for Java Maps and Sets In-Reply-To: References: Message-ID: <0D408967-EFD4-43A6-8669-34812A047F7E@oracle.com> +1 Sent from my iPhone > On Mar 2, 2017, at 10:36 AM, Srinivas Dama wrote: > > Hello, > > Please review http://cr.openjdk.java.net/~sdama/8156743/webrev.00/ > for https://bugs.openjdk.java.net/browse/JDK-8156743 > > Regards, > Srinivas > From srinivas.dama at oracle.com Thu Mar 2 16:39:48 2017 From: srinivas.dama at oracle.com (Srinivas Dama) Date: Thu, 2 Mar 2017 08:39:48 -0800 (PST) Subject: RFR: 8156743: ES6 for..of should work for Java Maps and Sets In-Reply-To: <3FB336BF-67CE-4D78-946B-5633E66682C2@gmail.com> References: <3FB336BF-67CE-4D78-946B-5633E66682C2@gmail.com> Message-ID: <4adfab13-fe9d-4d3b-bb49-e6a2c3a20c19@default> Hi Attila, Thank you for the detailed review. Regards, Srinivas -----Original Message----- From: Attila Szegedi [mailto:szegedia at gmail.com] Sent: Thursday, March 02, 2017 9:01 PM To: Srinivas Dama Cc: Nashorn-dev Subject: Re: RFR: 8156743: ES6 for..of should work for Java Maps and Sets Contrary to the issue name, I don?t see anything for handling Set in the patch, but I guess that?s because Set is a Collection and those already work? As an aside? I was looking into your use of NativeJava.from to convert a Java array to a NativeArray, and realized that we have at least 3 ways to do it, each with different drawbacks: 1. NativeJava.from as used in this patch. Its drawback is that it defensively always clones the array (here we woulnd?t need to clone it, although it doesn?t hurt) 2. Global.instance.wrapAsObject. Its drawback is that its Object[] case is further down the if/else list than NativeJava.from (5th instanceof vs. 2nd) 3. Global.instance.allocate. (This one is primarily used from generated bytecode.) Its drawback is that it iterates over the elements scanning for any ScriptRuntime.EMPTY values. I guess we could pass in a boolean flag to indicate there are no empty values to skip this scan (compiler could set the flag when it can prove the array literal it?s constructing has no empties). This doesn?t affect your patch - I think NativeJava.from() is a decent choice. So, +1. Attila. > On 02 Mar 2017, at 15:36, Srinivas Dama wrote: > > Hello, > > Please review http://cr.openjdk.java.net/~sdama/8156743/webrev.00/ > for https://bugs.openjdk.java.net/browse/JDK-8156743 > > Regards, > Srinivas > From pmlopes at gmail.com Thu Mar 9 12:20:03 2017 From: pmlopes at gmail.com (Paulo Lopes) Date: Thu, 9 Mar 2017 13:20:03 +0100 Subject: Can we define a method name alias when using a Java object/class form Nashorn? Message-ID: Hi, For the Vert.x project I've created a simple Promise implementation as available in a Browser. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise I've then played with babel to transpile the ES7 async - await to Promises and I must say that it works fine under Nashorn. Now my concern is that since this code is always in the hot-path I'd like to translate it to Java so it could be executed/jitted faster, however the Promise API has a small issue with that, it defines a method named: "catch" https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch This is forbidden name for a java method since according to the JLS "catch" is a reserved word and Java is way more strict than JS. My question is, now: Do I need to implement this using the JSObject interface where I can react to a "getMember" to return a Function and then handle it on the "call" method, or is there some "magic" where I can keep it all under a single Java object and make an alias? I expect that if I implement the JSObject that I'll start making to many small lived objects and the performance improvements would be lost with the GC pressure... From james.laskey at oracle.com Thu Mar 9 12:36:11 2017 From: james.laskey at oracle.com (Jim Laskey (Oracle)) Date: Thu, 9 Mar 2017 08:36:11 -0400 Subject: Can we define a method name alias when using a Java object/class form Nashorn? In-Reply-To: References: Message-ID: You might consider using an ordinary JS object to wrap the Java Promise Object. Even though the wrapper exists, the indirection should eventually optimize out (more so than for JSObject.) As far as having more objects about, I think it?s small relative to other objects in the background (MethodHandles.) This will also give you the advantage of having Promise be a real JS Object. Who knows what kinds of things users hang off of the promise. Cheers, ? Jim > On Mar 9, 2017, at 8:20 AM, Paulo Lopes wrote: > > Hi, > > For the Vert.x project I've created a simple Promise implementation as > available in a Browser. > > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise > > I've then played with babel to transpile the ES7 async - await to Promises > and I must say that it works fine under Nashorn. > > Now my concern is that since this code is always in the hot-path I'd like > to translate it to Java so it could be executed/jitted faster, however the > Promise API has a small issue with that, it defines a method named: "catch" > > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch > > This is forbidden name for a java method since according to the JLS "catch" > is a reserved word and Java is way more strict than JS. My question is, now: > > Do I need to implement this using the JSObject interface where I can react > to a "getMember" to return a Function and then handle it on the "call" > method, or is there some "magic" where I can keep it all under a single > Java object and make an alias? > > I expect that if I implement the JSObject that I'll start making to many > small lived objects and the performance improvements would be lost with the > GC pressure... From rberdeen at hubspot.com Thu Mar 9 21:10:13 2017 From: rberdeen at hubspot.com (Ryan Berdeen) Date: Thu, 9 Mar 2017 16:10:13 -0500 Subject: Broken property access on objects from other contexts? Message-ID: I'm running into an issue passing plain JS objects to a function created with loadWithNewGlobal. I didn't expect property access to behave differently on objects from other contexts, but the behavior when using numeric keys seems broken. Is there a safe way to pass objects between contexts so that the property access semantics don't change? I wrote a simple test script. It creates a function with a new global that is simply o[i] = o[i]. If the key (once converted to a string) exists in o, this shouldn't change the value in o. var reassignNewGlobal = loadWithNewGlobal({ script: '(function (o, i) { o[i] = o[i]; })', name: 'test.js' }); function test(i) { var o = {}; o[i] = true; o[i] = o[i]; print('expected: ' + JSON.stringify(o)); reassignNewGlobal(o, i); print('actual: ' + JSON.stringify(o)); print(); } test(-2147483649); test(-2147483648); test(2147483647); test(2147483648); Running this, I get expected: {"-2147483649":true} actual: {"-2147483649":true,"-1":null} expected: {"-2147483648":true} actual: {"-2147483648":null} expected: {"2147483647":true} actual: {"2147483647":true} expected: {"2147483648":true} actual: {"2147483648":true,"-1":null} There are a few strange things here: * The issue that broke my actual application, which is that you can't read properties with names outside the range of int * Setting a property with a name outside the range of int actually sets a property named "-1" * You can't get properties with negative names, but you can set them * When the value is missing due to one of the above, null is returned rather than undefined Debugging through this, it looked like the logic driving this is in JSObjectLinker get/put, but I couldn't tell from there if this behavior was intentional or a bug. I would expect keys to be converted to strings except when the target is an array, but it instead seems based on whether they key is an int or a long. I tested tested this with with the Oracle JRE 1.8.0_66-b17 and 9-ea+158. Thanks! Ryan From hannes.wallnoefer at oracle.com Fri Mar 10 14:32:38 2017 From: hannes.wallnoefer at oracle.com (=?utf-8?Q?Hannes_Walln=C3=B6fer?=) Date: Fri, 10 Mar 2017 15:32:38 +0100 Subject: Broken property access on objects from other contexts? In-Reply-To: References: Message-ID: Thanks for the report, Ryan! I have filed the issue below and I?m working on the fix. https://bugs.openjdk.java.net/browse/JDK-8176511 Hannes > Am 09.03.2017 um 22:10 schrieb Ryan Berdeen : > > I'm running into an issue passing plain JS objects to a function created > with loadWithNewGlobal. I didn't expect property access to behave > differently on objects from other contexts, but the behavior when using > numeric keys seems broken. > > Is there a safe way to pass objects between contexts so that the property > access semantics don't change? > > I wrote a simple test script. It creates a function with a new global that > is simply o[i] = o[i]. If the key (once converted to a string) exists in o, > this shouldn't change the value in o. > > var reassignNewGlobal = loadWithNewGlobal({ > script: '(function (o, i) { o[i] = o[i]; })', > name: 'test.js' > }); > > function test(i) { > var o = {}; > o[i] = true; > o[i] = o[i]; > print('expected: ' + JSON.stringify(o)); > reassignNewGlobal(o, i); > print('actual: ' + JSON.stringify(o)); > print(); > } > > test(-2147483649); > test(-2147483648); > test(2147483647); > test(2147483648); > > Running this, I get > > expected: {"-2147483649":true} > actual: {"-2147483649":true,"-1":null} > > expected: {"-2147483648":true} > actual: {"-2147483648":null} > > expected: {"2147483647":true} > actual: {"2147483647":true} > > expected: {"2147483648":true} > actual: {"2147483648":true,"-1":null} > > There are a few strange things here: > * The issue that broke my actual application, which is that you can't read > properties with names outside the range of int > * Setting a property with a name outside the range of int actually sets a > property named "-1" > * You can't get properties with negative names, but you can set them > * When the value is missing due to one of the above, null is returned > rather than undefined > > Debugging through this, it looked like the logic driving this is > in JSObjectLinker get/put, but I couldn't tell from there if this behavior > was intentional or a bug. I would expect keys to be converted to strings > except when the target is an array, but it instead seems based on whether > they key is an int or a long. > > I tested tested this with with the Oracle JRE 1.8.0_66-b17 and 9-ea+158. > > Thanks! > > Ryan From hannes.wallnoefer at oracle.com Fri Mar 10 16:32:13 2017 From: hannes.wallnoefer at oracle.com (=?utf-8?Q?Hannes_Walln=C3=B6fer?=) Date: Fri, 10 Mar 2017 17:32:13 +0100 Subject: RFR: 8176511: JSObject property access is broken for numeric keys outside the int range Message-ID: <3F088EFC-9B4F-404C-B832-04B23D15A355@oracle.com> Please review 8176511: JSObject property access is broken for numeric keys outside the int range Bug: https://bugs.openjdk.java.net/browse/JDK-8176511 Webrev: http://cr.openjdk.java.net/~hannesw/8176511/webrev/ Thanks, Hannes From sundararajan.athijegannathan at oracle.com Mon Mar 13 04:17:37 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Mon, 13 Mar 2017 09:47:37 +0530 Subject: RFR: 8176511: JSObject property access is broken for numeric keys outside the int range In-Reply-To: <3F088EFC-9B4F-404C-B832-04B23D15A355@oracle.com> References: <3F088EFC-9B4F-404C-B832-04B23D15A355@oracle.com> Message-ID: <58C61D61.7050707@oracle.com> +1 On 10/03/17, 10:02 PM, Hannes Walln?fer wrote: > Please review 8176511: JSObject property access is broken for numeric keys outside the int range > > Bug: https://bugs.openjdk.java.net/browse/JDK-8176511 > Webrev: http://cr.openjdk.java.net/~hannesw/8176511/webrev/ > > Thanks, > Hannes From marcus at lagergren.net Fri Mar 17 18:56:57 2017 From: marcus at lagergren.net (Marcus Lagergren) Date: Fri, 17 Mar 2017 19:56:57 +0100 Subject: RFR: 8176511: JSObject property access is broken for numeric keys outside the int range In-Reply-To: <3F088EFC-9B4F-404C-B832-04B23D15A355@oracle.com> References: <3F088EFC-9B4F-404C-B832-04B23D15A355@oracle.com> Message-ID: <577D2FEF-99E6-4282-8647-FFE83D8EDA25@lagergren.net> +1 Sent from my iPhone > On 10 Mar 2017, at 17:32, Hannes Walln?fer wrote: > > Please review 8176511: JSObject property access is broken for numeric keys outside the int range > > Bug: https://bugs.openjdk.java.net/browse/JDK-8176511 > Webrev: http://cr.openjdk.java.net/~hannesw/8176511/webrev/ > > Thanks, > Hannes From zalim.bashorov at jetbrains.com Mon Mar 20 10:34:04 2017 From: zalim.bashorov at jetbrains.com (Zalim Bashorov) Date: Mon, 20 Mar 2017 13:34:04 +0300 Subject: Bug with labeled break in catch and finally x Message-ID: Hello! I found the bug in nashorn (1.8.0_121) -- all following functions return undefined but should return "OK": function box1() { label: { try { throw 1; } catch (e) { break label; } throw 2; } return 'OK'; }; function box2() { label: { try { throw 1; } finally { break label; } throw 2; } return 'OK'; }; function box3() { label: { try { throw 1; } finally { break label; } } return 'OK'; }; Where can I file an issue about it? Thanks! -- Best regards, Zalim Bashorov Developer JetBrains http://www.jetbrains.com The Drive to Develop From sundararajan.athijegannathan at oracle.com Mon Mar 20 14:31:16 2017 From: sundararajan.athijegannathan at oracle.com (Sundararajan Athijegannathan) Date: Mon, 20 Mar 2017 20:01:16 +0530 Subject: Bug with labeled break in catch and finally x In-Reply-To: References: Message-ID: <58CFE7B4.3060901@oracle.com> Hi, This seems to be a bug. Thanks for reporting. Please file a bug. Thanks, -Sundar On 20/03/17, 4:04 PM, Zalim Bashorov wrote: > Hello! > > I found the bug in nashorn (1.8.0_121) -- all following functions return > undefined but should return "OK": > > function box1() { > label: { > try { > throw 1; > } > catch (e) { > break label; > } > throw 2; > } > return 'OK'; > }; > > function box2() { > label: { > try { > throw 1; > } > finally { > break label; > } > throw 2; > } > return 'OK'; > }; > > function box3() { > label: { > try { > throw 1; > } > finally { > break label; > } > } > return 'OK'; > }; > > > Where can I file an issue about it? > > Thanks! > -- > Best regards, > Zalim Bashorov > Developer > JetBrains > http://www.jetbrains.com > The Drive to Develop