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