JDK9 features

Sundararajan Athijegannathan sundararajan.athijegannathan at oracle.com
Fri May 13 04:30:42 UTC 2016


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