alicorn-systems/v8-adapter

Indexed access on Java objects

Opened this issue · 5 comments

Hello.

I want to use indexed/key access on Java objects which are not maps, lists or arrays. In Rhino it could be done by overriding public Object get(int index); public Object get(String key); on wrapper objects. Is there any way to achieve same with your library? Sorry if it mentioned somewhere, but I could not find an answer.

Thank you.

caer commented

Hi @anri-vin ,

Thanks for reaching out! When you say indexed/key access, do you mean that, given an instance of the following Java class:

public class MyJavaClass {
    public String myString = "Hello, World!";
    public int myInteger = 1337;
}

The following JavaScript code:

console.log(myJavaClassInstance["myString"]);
console.log(myJavaClassInstance.myInteger);

Would output the following to the console:

Hello, World!
1337

If so, I do not think we have a built-in feature for this; @AlexTrotsenko may be able to chime in, as he has added quite a few features along these lines in the past. If we do not have a feature for this, there are probably a few ways to implement one, but I will not be able to take charge of that at the moment.

@crahda yes it's implemented. But for encapsulation reasons it uses get/set property (as @anri-vin actually posted)

Check https://github.com/AlexTrotsenko/v8-adapter/blob/870e306dbb0b5d6194a2edceff64ee4d25bad4c5/src/test/java/io/alicorn/v8/V8JavaAdapterTest.java#L615

It can be replaced with

"var x = new WannabeBeanNoAnnotations(); x['i'] = 6688; x.i;"

I think we are not completely understanding each other. What I want is when I have Java class like this:

class JavaObject {
   private Object[] internalArray = ...;
    
   public Object getProperty(int index) {
      return internalArray[index]; 
   }
   public void setProperty(int index, Object value) {
      internalArray[index] = value;
   }
}

calling JS as following
javaObject[42]; javaObject[42] = 0;
will internally call getProperty and setProperty.

@anri-vin as far as I know - this behaviour with indexed setter is not implemented. Since I have not used this one in Rhino either - it's a bit hard to tell you want should be the easiest way to achieve this (as I am not sure about exact use case).

I would start looking in the io.alicorn.v8.V8JavaClassInterceptor api. If it's not matching your needs - then as @crahda mentioned - you can probably try implement one yourself. Normally @crahda is quite fast to reviewing PR.

Also if you are using latest version of J2V8 and thus newer V8 itself - you can likely use JS Proxy api in you app and redirect requests to the set/get methods of your object (actually Js proxy object of your Java object). I was experimenting with it in this PR, but since proxies are not supported in J2V8 4.6.0 (current target of this lib) - I skipped this change for now.

I found a solution at the moment. It's not as pretty as it can be, but it works. After injecting object to JS I execute following script for each entry in internal array (0 - is index):
v8.executeScript("Object.defineProperty(javaObject, 0, { get: function() { return this.getProperty(\"0\"); }});")