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