JDK9 features

Sundararajan Athijegannathan sundararajan.athijegannathan at oracle.com
Tue May 17 14:53:44 UTC 2016


Hi,

Filed a bug: https://bugs.openjdk.java.net/browse/JDK-8157160

Thanks,

-Sundar


On 5/13/2016 8:16 PM, Eric Pederson wrote:
> Hi Sundar - 
>
> It would be helpful for sure.  We use JSON for serialization and
> debugging a lot.  Also if it worked it could simplify our
> custom ScriptObjectMirror -> native object conversion logic from 30
> lines down to JSON.parse(JSON.stringify(scriptObjMirror)) :).
>
> Besides the JSON stuff our biggest problem has been
> ScriptObjectMirrors being treated like regular objects and passed down
> call chains and then either throwing exceptions or silently failing
> and it's hard to figure out why.  Junior developers get completely
> baffled.  We have solved the problem with the commonjs/require loading
> pattern on the script loading side and the proxy pattern on the Java
> calling side.  It would be nice to have official solutions for these
> but it's not urgent.  It might be something worth adding to the
> documentation.
>
> Thanks,
>
>
>
> -- Eric
>
> On Fri, May 13, 2016 at 12:30 AM, Sundararajan Athijegannathan
> <sundararajan.athijegannathan at oracle.com
> <mailto:sundararajan.athijegannathan at oracle.com>> wrote:
>
>     Hi Eric,
>
>     That commonjs/require loading pattern is not bad [wrapping eval'ed
>     code inside a function]. If your loaded scripts are (somewhat)
>     well-behaved, it does solve the problem of global namespace pollution.
>
>     Yes, ScriptObjectMirrors are not uniformly treated like
>     ScriptObject everywhere.  But, I'm not sure how far we can fix
>     that :( Is JSON handling (w.r.t ScriptObjectMirror) your main pain
>     point? We *may* be able to address that.
>
>     Thanks,
>
>     -Sundar
>
>
>     On 5/12/2016 11:10 PM, Eric Pederson wrote:
>>     Hi Sundar:
>>
>>     1. I investigated loadWithNewGlobal because it looked promising
>>     for this use case.  Say you use loadWithNewGlobal to load a
>>     function.  If you call the loaded function and it returns an
>>     object or array the caller gets a ScriptObjectMirror.  The
>>     problems with a ScriptObjectMirror "object" are: 
>>
>>       * Cannot call Object methods like keys or getOwnPropertyNames. 
>>         You get an exception: TypeError: cannot call undefined.  To
>>         iterate over the properties you must use a for in loop.
>>       * Cannot convert ScriptObjectMirror to JSON using
>>         JSON.stringify.  It returns undefined.
>>
>>     If the function loaded with loadWithNewGlobal returns an array
>>     then things are better.  Interestingly you can call most Array
>>     methods (like forEach and map) on a ScriptObjectMirror "array". 
>>     But JSON.stringify also returns undefined.  
>>
>>     I did find one issue with an array returned by a
>>     loadWithNewGlobal loaded function - calling sort with a
>>     comparator.  For example, if the loaded function returned
>>     testArray, a ScriptObjectMirror "array":
>>
>>         *var **/sorted /*= */testArray/*.sort(*function*(a, b) {
>>
>>             *return *a - b; });
>>
>>      
>>
>>     throws an exception_: _TypeError: function(a, b) { return a -
>>     b; } is not a function. 
>>
>>
>>     These were the same "mutant" issues that we also saw with
>>     JSObjects returned by Java methods.  
>>
>>
>>     The hack that we are using now to load code without effecting the
>>     global namespace is the same one discussed in this thread:
>>
>>     http://thread.gmane.org/gmane.comp.java.openjdk.nashorn.devel/1722.
>>
>>
>>     The code that we are using is copied/adapted from Vertx (thanks,
>>     Tim!):
>>
>>
>>     function loadEval(path) {
>>
>>         *var *dir = *new **/File/*(path).getParent();
>>
>>         *var *body = /readFile/(path);
>>
>>         *var *moduleFunc =    
>>
>>             *"function(exports, module, require, __filename,
>>         __dirname){" *+ body + *"**\n**}**\n**//# sourceURL=" *+ path;
>>
>>
>>         *try {*
>>
>>             *var *func = eval(moduleFunc);
>>
>>         } *catch *(ex) {
>>
>>             *if *(ex *instanceof **SyntaxError*) {
>>
>>                 /// WARNING! Large pile of Yak hair ahead!
>>         /
>>
>>         /        /*var *ne = ex.nashornException;
>>
>>                 *var *cause = ne.cause;
>>
>>                 *var *msg = cause.message.replace(*"<eval>"*, file);
>>
>>                 *var *lineNumber = cause.*lineNumber;*
>>
>>                 console.log(*"ERROR: " *+ msg + *" in file " *+ file
>>         + *" at line " *+ lineNumber);
>>             }
>>
>>             *throw *ex;
>>         }
>>
>>         *var *module = { *exports*: {} };
>>
>>         func(module.*exports*, module, require, path, dir);
>>
>>         *return *module.*exports*;
>>
>>     }
>>
>>
>>     This seems like a hack to me - but I'm coming from the Java world
>>     so this may be par for the course in Javascript-land :)  Hack or
>>     no, it is the best of both worlds: it does not change the global
>>     namespace, yet the code that it returns lives in the global
>>     context, so if you call a loaded function it will return a native
>>     object, not a ScriptObjectMirror.  
>>
>>
>>     We'd like to have a built-in equivalent of this
>>     loadEvalfunction.  It doesn't need to use those specific
>>     arguments (export, module, etc), but you must be able to pass
>>     arguments in to provide a context to the loaded code.  
>>
>>
>>     Alternatively if you could make ScriptObjectMirrors 100%
>>     compatible with native objects that would work too.  Then we
>>     could use loadWithNewGlobal.
>>
>>
>>     2.  The problem that we are having with objects returned by Java
>>     methods is the same as what I described above because the
>>     returned JSObjects are seen as ScriptObjectMirrors by the calling
>>     Javascript code.  
>>
>>
>>     What we are doing now is wrapping each Java object with a
>>     Javascript proxy.  When you call the proxy it calls the
>>     corresponding Java method, then converts the returned
>>     ScriptObjectMirrorinto a native JS object using a custom
>>     conversion function.  
>>
>>
>>     What would be nice for this use case is a standard function to
>>     convert ScriptObjectMirrors to native JS objects (what I was
>>     calling asJSONCompatible below).   Or if ScriptObjectMirrors were
>>     100% compatible that would be even better - we could get rid of
>>     our JS proxy objects.
>>
>>
>>     I'm happy to file some enhancement requests.  Though it seems
>>     like the bug trackers are read-only to the general public though,
>>     how would I get access?
>>
>>
>>     Thanks,
>>
>>
>>
>>     -- Eric
>>
>>     On Thu, May 12, 2016 at 12:36 AM, Sundararajan Athijegannathan
>>     <sundararajan.athijegannathan at oracle.com
>>     <mailto:sundararajan.athijegannathan at oracle.com>> wrote:
>>
>>         Hi,
>>
>>         Thanks for your comments!
>>
>>         Making comments on forthcoming JDK releases is hard :)
>>         Whatever I'm
>>         saying now, may not happen - the usual disclaimer applies.
>>
>>         No, we expect that only a subset of ES6 features will be
>>         implemented for
>>         Java 9.
>>
>>         1. On loading definitions without changing global namespace:
>>         you meant
>>         current global namespace? loadWithNewGlobal creates a new
>>         global and
>>         loads definitions into that.
>>
>>         Would that be useful for you? or anything else? Which hack you're
>>         referring to? Please file an enhancement with your requirements.
>>
>>         2. on JSON: Again, will you please provide a simple test case
>>         and/or
>>         file an enhancement with requirements?
>>
>>         Thanks,
>>         -Sundar
>>
>>         On 5/12/2016 12:56 AM, Eric Pederson wrote:
>>         > I've been noticing the Java 9 ES6 features tweeted by
>>         @sundararajan_a
>>         > <https://twitter.com/sundararajan_a>.  Looks awesome!  Will
>>         there be full
>>         > ES6 support in Java 9?
>>         >
>>         > There are a couple of other things we would love to see in
>>         the updated
>>         > Nashorn:
>>         >
>>         > 1. We've been using the same hack that you recommended to
>>         Tim Fox for
>>         > loading functions without changing the global namespace -
>>         the Avatar/js
>>         > CommonJS/require hack.  It would be great if this was
>>         supported natively in
>>         > Nashorn via a new loadXXX().
>>         >
>>         > 2. It would be also be great to have the inverse of
>>         asJSONCompatible for a)
>>         > JSObjects returned by Java code and b) objects from other
>>         scopes.  Our name
>>         > for ScriptObjectMirrors in Javascript code is "mutant
>>         objects": they look
>>         > like regular JS objects but they are missing most of their
>>         DNA, and you
>>         > don't realize until you get an exception or silent failure
>>         somewhere down
>>         > the call chain where it's difficult to figure out why :)
>>         >
>>         > Anyway, the upcoming stuff looks great!
>>         >
>>         > Thanks,
>>         >
>>         > -- Eric
>>
>>
>
>



More information about the nashorn-dev mailing list