[Our emails crossed..]
Yes, script objects returned from ScriptEngine's eval methods are always
wrapped as ScriptObjectMirrors.
But if you pass a script object to a java method that accepts Object
type, then it is passed "as is". i.e., no wrapping. But if your method
signature uses JSObject or ScriptObjectMirror, then you get a wrapped
instance. This is to avoid wrap check for every "Object" accepting Java
method call.
When you create callback interface implemenations, the interface
implementation sets right nashorn scope at the entry of method calls.
-Sundar
On Tuesday 10 December 2013 06:49 PM, Tim Fox wrote:
I did a bit more digging here and inspected (in Java) the classes of
objects passed from JavaScript into Java in the following two cases:
1) Objects explicitly passed from JavaScript to Java, e.g. in a script:
someJavaObject.callJavaMethod(..);
2) Objects passed to Java from JavaScript by returning them from the
execution of a script, i.e. the last statement of a script which is
returned to Java via the return value of engine.eval(...)
It seems that objects passed to Java code via 1) do not implement
jdk.nashorn.api.scripting.ScriptObjectMirror but objects passed in 2)
do implement jdk.nashorn.api.scripting.ScriptObjectMirror
So, it seems that I can workaround the issue by not explicitly passing
objects from JS to Java but returning them from the execution of the
script.
I have to say that the current behaviour seems a bit inconsistent to
me, shouldn't all objects passed to Java from JS be wrapped in
ScriptObjectMirror to ensure the correct scope is used whenever they
are executed? I'm not sure why some objects passed to Java are wrapped
and others aren't...
I'm also concerned about the case of callbacks. Let's say I have a
Java object which allows a handler to be set:
class MyObject {
private Runnable handler;
void setHandler(Runnable handler) {
this.handler = handler;
}
void callHandler() {
handler.run();
}
}
And I call an instance of this object from inside a JS script:
myJavaObject.setHandler(function() {
// Will this JS function be called with the correct scope?
});
The object that gets passed to setHandler does not implement
ScriptObjectMirror, so when the JS handler function is called, can we
be sure it wil be executed in the correct scope?
On 10/12/13 12:41, Tim Fox wrote:
Hi Sundar,
I see you resolved this issue as a non issue here
https://bugs.openjdk.java.net/browse/JDK-8029604
Unfortunately I am unable to add comments to the bug so I have a few
questions...
>> In either mode, Java level Bindings instance backed Java objects
as script variables are "read only"
Can you elaborate what this means? Do you mean the Java object
_reference_ is read only? I.e. JavaScript can't replace the global
variable with anything else. I imagine ensuring that the Java object
itself is read-only would be an extremely difficult thing to do.
>> You can get ScriptObjectMirror wrapper of ScriptFunctions and
ScriptObjects and share/call/use it from anywhere (ScriptObjectMirror
takes care of setting right nashorn Global object in thread local
storage).
It seems like this is what we need to do to implement CommonJS
require-like functionality as we need to export objects from scopes
such that they are callable from different scopes. This is essential
for implementing any "node-like" functionality using Nashorn.
I can't see anything in the javax.script API that mentions
ScriptObjectMirror, ScriptFunctions or ScriptObjects, so I assume
these are in a different API. Is this API documented anywhere, and is
it a public API? If you could give a simple code example of how my
simple test program could be adapted using this other API, that would
be a great help :)
I guess this also implies that what I want to do is impossible using
the javax.script API?
On 05/12/13 13:55, A. Sundararajan wrote:
Hi,
Please use "tools" category and include scripting/nashorn in your
description or title or label somewhere.
PS. we are working on getting appropriate category.
Thanks
Sundar
On Thursday 05 December 2013 06:43 PM, Tim Fox wrote:
Thanks I am trying to submit a bug here:
http://bugreport.sun.com/bugreport/submit_intro.do
as directed in the link your provided, but I can't see any category
I can file it against that seems appropriate for Nashorn...
On 05/12/13 13:00, A. Sundararajan wrote:
Please file a bug using web interface. Process explained in this
post by Jim:
http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-December/002515.html
Thanks
-Sundar
On Thursday 05 December 2013 06:14 PM, Tim Fox wrote:
Oops! Forgot to provide a link to the example...
Here it is:
https://gist.github.com/purplefox/7804105
On 05/12/13 12:42, Tim Fox wrote:
Hello Nashorn folks,
I've been playing around with Nashorn today, and in particular
I've been trying to implement commonJS-like require()
functionality, but having some problems. Most probably I am
doing something stupid...
I'm sure you all know, with commonJS modules you can "require"
them from your JS scripts, e.g.
var someObject = require("modulename");
Then in modulename.js
you do your stuff then export the object that ends up being
returned from the require, e.g.
var someObject = {
foo: "bar"
}
module.exports = someObject;
One key thing is that modules have their own scope, so any
globals defined in modulename.js shouldn't be visible in the
script that requires them, and vice versa.
While trying to implement this using Nashorn and running scripts
in different scopes I've found it's possible for Nashorn to get
confused about what scope it's using, and for scopes to leak
from one to another.
I created this simple runnable example to demonstrate the issue.
I wonder if anyone can advise whether this is a bug, or perhaps
I am using the API incorrectly. If the latter, could you advise
on the proper way to use the API to implement this kind of
functionality.
Many thanks