ScriptObjectMirrors

Serguei Mourachov smourachov at gmail.com
Fri Oct 17 04:12:09 UTC 2014


I mean methods of JSObject such as (get/set)(Member/Slot)  and call(). I 
hope object passed to/from those will not be wrapped/unwrapped, although 
the are technically Java methods  .

SM

On 10/16/2014 9:01 PM, A. Sundararajan wrote:
> There is no notion of wrap/unwrap of user implemented JSObject - so 
> those won't be affected. JSObject itself is just another Java type and 
> so would be between script and Java code "as is".
>
> Only for Object param types of Java methods will receive wrapped 
> ScriptObjects - argument filter will be inserted for such parameters. 
> Actually a filter is already installed for such params to handle 
> ConsString objects - so ScriptObject wrapping is just another 
> incremental check+wrap in that filter. And Object returning Java 
> methods will have unwrapper filter on return value (on the script 
> side). Other Java parameter types/return type should not be affected 
> at all. Providing another command line option implies we keep checking 
> it in argument/return type filter methods - which would be costly.
>
> -Sundar
>
> On Friday 17 October 2014 09:23 AM, Serguei Mourachov wrote:
>> Sundar
>>
>> Will it also affect classes implementing JSObject?
>> IMO, we should have an option to disable this wrap/unwrap behavior in 
>> cases when it significantly affecting performance.
>>
>> SM
>>
>> On 10/16/2014 6:44 AM, A. Sundararajan wrote:
>>> There were many questions in this list and elsewhere on 
>>> ScriptObjectMirror. This email is to clarify those.
>>>
>>> Nashorn represents JavaScript objects as instances of implementation 
>>> class called jdk.nashorn.internal.runtime.ScriptObject or one of 
>>> it's subclasses (like NativeArray, NativeRegExp etc. - or even 
>>> generated ones like jdk.nashorn.internal.scripts.JO4 etc)
>>>
>>> When ScriptObjects are returned from a script function or evaluated 
>>> script code, ScriptEngine.eval returns an instanceof 
>>> jdk.nashorn.api.scripting.ScriptObjectMirror.
>>>
>>> http://cr.openjdk.java.net/~sundar/jdk.nashorn.api/9/javadoc/jdk/nashorn/api/scripting/ScriptObjectMirror.html 
>>>
>>>
>>> Example:
>>>
>>>     ScriptEngine e = new 
>>> ScriptEngineManager().getEngineByName("nashorn");
>>>     Object obj = e.eval("var obj = { foo: 23 }"); // obj is an 
>>> instance of ScriptObjectMirror
>>>
>>> Caller can cast the result to ScriptObjectMirror to access 
>>> properties of that script object or call methods on it. All 
>>> javax.script interface methods returning Object (ScriptEngine.eval, 
>>> Invocable.invokeFunction, Invocable.invokeMethod) return 
>>> ScriptObjectMirror if underlying script or script function/method 
>>> returns a JS object.
>>>
>>> But, if you call any Java method accepting Object type param or 
>>> assign to element of Object[], then Nashorn was not wrapping 
>>> ScriptObject in the past. i.e., 'raw' ScriptObject (or subclass) 
>>> instances "escaped" to Java layer. If you try to cast those to 
>>> ScriptObjectMirror from Java code, you got ClassCastException. Also, 
>>> if you passed such raw object as "self" parameter for 
>>> Invocable.invokeMethod, you would IllegalArgumentException. This was 
>>> causing a lot of confusion - script objects got to java code 
>>> sometimes as wrapped mirror objects and sometimes as 'raw' objects!
>>>
>>> With a recent change
>>>
>>> http://hg.openjdk.java.net/jdk9/dev/nashorn/rev/a8d44c7c2ac0
>>>
>>> in jdk9 and the corresponding backport to jdk8u-dev
>>>
>>> http://hg.openjdk.java.net/jdk8u/jdk8u-dev/nashorn/rev/a35c8136c045
>>>
>>> the way nashorn wraps internal ScriptObjects to ScriptObjectMirror 
>>> has changed. Script objects are always wrapped to ScriptObjectMirror 
>>> - even when you're calling Java method that accepts "Object" type 
>>> value. Also, return values from java methods returning Object are 
>>> "unwrapped" (if the return value is a ScriptObjectMirror) when it 
>>> gets to script execution.
>>>
>>> Example:
>>>
>>>     // list gets ScriptObjectMirror as element
>>>     engine.eval("var m = new java.util.HashMap(); l.put('myobj', { 
>>> foo: 33 });");
>>>     engine.eval("var obj = m.get('myobj'); // obj gets unwrapped as 
>>> ScriptObject here");
>>>
>>> With this change, raw ScriptObjects don't escape to Java layer at all.
>>>
>>> Hope this helps,
>>> -Sundar
>>
>



More information about the nashorn-dev mailing list