How to properly implement JSObject to provide conversion of Gson JsonElement objects?

Jesse Schulman jesse at dreamtsoft.com
Fri Jun 2 16:38:42 UTC 2017


That's the approach I took too, however I avoided the eval by doing
bindings.get("Object").newObject() but you should be able to do the same
thing against the engine if you don't use different bindings.

On Thu, Jun 1, 2017 at 5:32 PM Daniel Einspanjer <deinspanjer at gmail.com>
wrote:

> Yes, that is the bug.
>
> My work around isn't great, I just had to avoid using any form of custom
> JSObject. Instead, I do an eval('new Object()') to get a holder and put my
> object and functions inside it via put().
>
> -Daniel
>
> On Thu, Jun 1, 2017, 6:30 PM Jesse Schulman <jesse at dreamtsoft.com> wrote:
>
>> Ironically, I'm hitting a similar issue with a library doing an
>> Object.keys() call against a custom JSObject, can you share the solution
>> you've taken?
>>
>> Also, I'm guessing this is the RFE you created:
>> https://bugs.openjdk.java.net/browse/JDK-8181203?jql=text%20~%20%22Object.keys%20nashorn%22
>>
>> Thanks!
>> Jesse
>>
>> On Tue, May 30, 2017 at 9:34 AM Daniel Einspanjer <deinspanjer at gmail.com>
>> wrote:
>>
>>> Thank you, yes that is very similar to the approach I went down.
>>> Ultimately I hit another roadblock that forced me to approach the entire
>>> issue differently.  The JS library I am interacting with uses Object.keys()
>>> and currently, Nashorn doesn't support Object.keys() calls with custom
>>> JSObjects.  I filed an RFE for that, but due to the issue, I'm having to
>>> avoid using JSObject entirely.
>>>
>>> Thanks again for your reply.
>>>
>>> -Daniel
>>>
>>> On Tue, May 30, 2017 at 12:29 PM Jesse Schulman <jesse at dreamtsoft.com>
>>> wrote:
>>>
>>>> If you haven't got this working yet, one possible solution is to return
>>>> anonymous inner AbstractJSObject that returns true for isFunction calls:
>>>>
>>>>    public Object getMember(String name) {
>>>>       if ("map".equals(name)) {
>>>>          return new AbstractJSObject() {
>>>>             @Override
>>>>             public Object call(Object thiz, Object... args) {
>>>>                // delegate to your JsonArray.map method from this
>>>> annonymous inner class
>>>>                // in your example nashorn should pass you a single
>>>> instance of ScriptObjectMirror for args that returns true for isFunction()
>>>> call
>>>>             }
>>>>
>>>>             @Override
>>>>             public boolean isFunction() {
>>>>                   return true;
>>>>             }
>>>>          };
>>>>       }
>>>>
>>>>       return null;
>>>>    }
>>>>
>>>>
>>>> Hope that helps!
>>>> Jesse
>>>>
>>>> On Thu, May 25, 2017 at 1:11 PM Daniel Einspanjer <
>>>> deinspanjer at gmail.com> wrote:
>>>>
>>>>> I have a project that makes extensive use of the Google Gson library.
>>>>>
>>>>> In this particular case, I have a JsonArray object (which implements
>>>>> iterable) containing a collection of objects.  In pure JSON it would
>>>>> look
>>>>> like this:
>>>>>
>>>>> [ 1, true, {"a": "b"}, [1,2] ]
>>>>>
>>>>> In Gson JsonElements, it looks like this:
>>>>>
>>>>> arr = new JsonArray();
>>>>> arr.add(1);
>>>>> arr.add(true);
>>>>>
>>>>> obj = new JsonObject();
>>>>> obj.addProperty("a", "b");
>>>>>
>>>>> arr.add(obj);
>>>>>
>>>>> innerArr = new JsonArray();
>>>>> innerArr.add(1);
>>>>> innerArr.add(2);
>>>>>
>>>>> arr.add(innerArr);
>>>>>
>>>>> I am calling a Javascript function in Nashorn that is trying to do a
>>>>> map
>>>>> over this array:
>>>>>
>>>>> nash.eval("function doIt(arr) { print(arr.map(function(item) { return
>>>>> (typeof item); })); }");
>>>>>
>>>>> So, in order for this to work with my own arbitrary object
>>>>> (JsonArray), I
>>>>> believe I need to implement JSObject.
>>>>>
>>>>> I created the wrapper class that implements it, using the underlying
>>>>> JsonArray object as a delegate.  things like isArray() and such are
>>>>> trivial, but I'm having trouble with the map.
>>>>> I have a map method that takes a functional interface which is
>>>>> available
>>>>> for the JsonArray object.
>>>>>
>>>>> Nashorn calls getMember("map") when the doIt function is executed.  I
>>>>> cannot figure out how to give it an appropriate function reference to
>>>>> my
>>>>> JsonArray.map method.
>>>>> I was able to handle getMember("toString") easily enough, but the
>>>>> problem
>>>>> is that method doesn't take any arguments, so returning a simple
>>>>> Callable<Object> is fine for it, but map is going to take arguments
>>>>> that I
>>>>> don't know about ahead of time.
>>>>>
>>>>> I would really appreciate some assistance here.  Thanks.
>>>>>
>>>>> -Daniel
>>>>>
>>>>


More information about the nashorn-dev mailing list