简体   繁体   中英

How to use Object.defineProperty in javascriptcore for android

I'm using this library to run some javascript on android - https://github.com/LiquidPlayer/LiquidCore/wiki/LiquidCore-as-a-Native-Javascript-Engine

I've got some objects that I am exposing to javascript no problem, but I would like to bind some functions to that class as true getter/setter properties.

The syntax for doing this in javascript is:

Object.defineProperty(viewWrapper, 'width', {
    get: function () {
       return viewWrapper.view.width();
    }
});

I've found this class: http://ericwlange.github.io/org/liquidplayer/webkit/javascriptcore/JSObjectPropertiesMap.html

I've seen this reference in apples docs: https://developer.apple.com/documentation/javascriptcore/jsvalue/1451542-defineproperty

The reason for me doing this, is to shadow existing objects perfectly, so I have to be able to replicate the getter/setter style. I could do the work at the javascript layer, but I'm trying to write the least code possible, and expose fully formed objects from the java side.

I tried this on this page, but it just ended up binding the functions themselves.

https://github.com/ericwlange/AndroidJSCore/issues/20

There is another way to do it that is not particularly well documented, but is far more elegant. You can use the @jsexport attribute on a JSObject .

private class Foo extends JSObject {
    Foo(JSContext ctx) { super(ctx); }

    @jsexport(type = Integer.class)
    Property<Integer> x;

    @jsexport(type = String.class)
    Property<String>  y;

    @jsexport(attributes = JSPropertyAttributeReadOnly)
    Property<String> read_only;

    @SuppressWarnings("unused")
    @jsexport(attributes = JSPropertyAttributeReadOnly | JSPropertyAttributeDontDelete)
    int incr(int x) {
        return x+1;
    }
}

Then you can use the getter/setter methods in both Java and Javascript:

Foo foo = new Foo(ctx);
ctx.property("foo", foo);
ctx.evaluateScript("foo.x = 5; foo.y = 'test';");
assertEquals((Integer)5, foo.x.get());
assertEquals("test", foo.y.get());
foo.x.set(6);
foo.y.set("test2");
assertEquals(6, foo.property("x").toNumber().intValue());
assertEquals("test2", foo.property("y").toString());
assertEquals(6, ctx.evaluateScript("foo.x").toNumber().intValue());
assertEquals("test2", 
    ctx.evaluateScript("foo.y").toString());
ctx.evaluateScript("foo.x = 11");
assertEquals((Integer)11, foo.x.get());
assertEquals(21, 
    ctx.evaluateScript("foo.incr(20)").toNumber().intValue());

foo.read_only.set("Ok!");
assertEquals("Ok!", foo.read_only.get());
foo.read_only.set("Not Ok!");
assertEquals("Ok!", foo.read_only.get());
ctx.evaluateScript("foo.read_only = 'boo';");
assertEquals("Ok!", foo.read_only.get());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM