JDK9 features
Eric Pederson
ericacm at gmail.com
Tue May 17 16:47:53 UTC 2016
Thanks!
On Tuesday, May 17, 2016, Sundararajan Athijegannathan <
sundararajan.athijegannathan at oracle.com> wrote:
> 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 <
> <javascript:_e(%7B%7D,'cvml','sundararajan.athijegannathan at oracle.com');>
> sundararajan.athijegannathan at oracle.com
> <javascript:_e(%7B%7D,'cvml','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>
>> 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 loadEval function. 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 ScriptObjectMirror into 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
>> <javascript:_e(%7B%7D,'cvml','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
>>>
>>>
>>
>>
>
>
--
Sent from Gmail Mobile
More information about the nashorn-dev
mailing list