JsInterop Object Literal

556 views
Skip to first unread message

Brandon Donnelson

unread,
Mar 20, 2016, 2:05:00 AM3/20/16
to GWT Contributors
Can JsInterop create an object literal? 

var foo = {a:0, b:1};


Brandon Donnelson

unread,
Mar 20, 2016, 2:11:06 AM3/20/16
to GWT Contributors

Ray Cromwell

unread,
Mar 20, 2016, 3:08:10 AM3/20/16
to google-web-toolkit-contributors
Right now, the best you can do is

@JsType(isNative = true, namespace =JsPackage.GLOBAL, name = "Object")
class MyLiteral {
}

And put js properties on the object
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/3c62911e-0304-4181-b6d3-03b4689debb9%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Brandon Donnelson

unread,
Mar 20, 2016, 2:38:11 PM3/20/16
to GWT Contributors
Thank you! That's awesome. 


On Sunday, March 20, 2016 at 12:08:10 AM UTC-7, Ray Cromwell wrote:
Right now, the best you can do is

@JsType(isNative = true, namespace =JsPackage.GLOBAL, name = "Object")
class MyLiteral {
}

And put js properties on the object


On Sat, Mar 19, 2016 at 11:11 PM, Brandon Donnelson
<branfl...@gmail.com> wrote:
> I found a doc talking about object literal creation
> https://docs.google.com/document/d/1DFrC-GtcK7cu6DGxaWCswvb2fai9cnrWPvGcdgsKlBw/edit.
>
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an

Paul Stockley

unread,
Mar 21, 2016, 9:22:44 AM3/21/16
to GWT Contributors
I think having a really succinct way of dealing with JS Object literals will be key to inter-op with existing java script code. Is the plan to land the enhanced support in the 2.x code base or will this be j2cl only? I really hope it will be included on 2.x

In the meantime I have come up with a few alternatives that can be implemented now. I will post details later this week.

Paul Stockley

unread,
Mar 22, 2016, 12:42:23 AM3/22/16
to GWT Contributors
I have come up with 3 approaches to creating object literals given the current JsInterop capabilities:

1) Construct and set the fields individually

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
   int field1;
   String field2;
}

SomeObjectLiteral o = new SomeObjectLiteral();
o.field1 = 1;
o.field2 = "Some value";

2) Define a fluent interface

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
   int field1;
   String field2;


   @JsOverlay
public final SomeObjectLiteral Field1(int v) {
field1 = v;
return this;
}

   @JsOverlay
public final SomeObjectLiteral Field2(String v) {
field2 = v;
return this;
}
}

You can then write

new SomeObjectLiteral().Field1(1).Field2("A value");

Note I didn't call the setter setFieldx. This is because you currently get a runtime error if you do this.


2) Use an ObjectLiteral Helper

You can define a helper similar to

public class ObjectLiteral {
public static <O> O $(O base, Object ...fieldValues) {
String fieldName = null;

for(Object f : fieldValues) {
if (fieldName == null)
fieldName = (String)f;
else {
if (f instanceof Integer)
setField(base, fieldName, ((Integer) f).intValue());
else if (f instanceof Double)
setField(base, fieldName, ((Double) f).doubleValue());
else if (f instanceof Boolean)
setField(base, fieldName, ((Boolean) f).booleanValue());
else
setField(base, fieldName, f);

fieldName = null;
}
}

return base;
}

private final static native void setField(Object literal, String fieldName, int i) /*-{
literal[fieldName] = i;
}-*/;

private final static native void setField(Object literal, String fieldName, double d) /*-{
literal[fieldName] = d;
}-*/;

private final static native void setField(Object literal, String fieldName, boolean b) /*-{
literal[fieldName] = b;
}-*/;

private final static native void setField(Object literal, String fieldName, Object o) /*-{
literal[fieldName] = o;
}-*/;
}

You can then write

import static com.xxx.ObjectLiteral.$;

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
   int field1;
   String field2;
}

$(new SomeObjectLiteral(), "field1",123, "field2","some value")

You would probably want to add some more error checking to the helper. This approach probably isn't 
particularly efficient, especially if you pass a lot of field values that get boxed into Object primitives. 
It would be nice if the compiler unboxed varargs passed to isNative=true methods. If this was true you
could write a much more efficient javascript version.


Ignacio Baca Moreno-Torres

unread,
Mar 22, 2016, 3:25:13 AM3/22/16
to GWT Contributors
If your concert is to be able to write one-line initializers, and you are using java8 syntax you also do something like that:

public static <T> T apply(T t, Consumer<T> fn) {
fn.accept(t);
return t;

}

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
int field1;
String field2;
}

{
    SomeObjectLiteral sol = apply(new SomeObjectLiteral(), o -> { o.field1 = 1; o.field2 = "str"; });
}

Copied from kotlin (although without method extensions and method inline is not the same ;)), this is usable for client and server code when you need to initialize small pojos without fluent api.

Paul Stockley

unread,
Mar 22, 2016, 9:01:35 AM3/22/16
to GWT Contributors
That's a nice approach.

Brandon Donnelson

unread,
Mar 22, 2016, 12:08:14 PM3/22/16
to GWT Contributors
Thanks Paul. I haven't seen use of the JsOverlay yet, that's nifty. 

Nice Ignacio. 

--
You received this message because you are subscribed to a topic in the Google Groups "GWT Contributors" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit-contributors/bix56s-OJ-E/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-web-toolkit-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-web-toolkit-contributors/7650afe9-7570-4372-b1c3-6311b5fee382%40googlegroups.com.

Jens

unread,
Mar 22, 2016, 12:53:10 PM3/22/16
to GWT Contributors

If your concert is to be able to write one-line initializers, and you are using java8 syntax you also do something like that:

public static <T> T apply(T t, Consumer<T> fn) {
fn.accept(t);
return t;
}

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class SomeObjectLiteral {
int field1;
String field2;
}

{
SomeObjectLiteral sol = apply(new SomeObjectLiteral(), o -> { o.field1 = 1; o.field2 = "str"; });
}

Copied from kotlin (although without method extensions and method inline is not the same ;)), this is usable for client and server code when you need to initialize small pojos without fluent api.

Looks like a good example how to over-use lambdas. IMHO its just more complicated without any added value if its just for initialization.

SomeObjectLiteral sol = apply(new SomeObjectLiteral(), o -> { o.field1 = 1; o.field2 = "str"; });
SomeObjectLiteral sol = new SomeObjectLiteral(); sol.field1 = 1; sol.field2 = "str";

Old school is even shorter ;-) 

-- J.

Ray Cromwell

unread,
Mar 22, 2016, 1:09:42 PM3/22/16
to google-web-toolkit-contributors
Use an annotation processor

@AutoLiteral
@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class MyFoo {
public int field1, field2;

}

@Generated(...)
@JsType(IsNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class MyFooLiteral extends MyFoo {
public MyFooLiteral make() { return new MyFooLiteral(); }
@JsOverlay
final public MyFooLiteral field1(int x) { field1 = x; }
@JsOverlay
final public MyFooLiteral field2(int x) { field2 = x; }
}


callFunc(MyFooLiteral.make().field1(42).field2(99));
> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to google-web-toolkit-co...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/c007f5d8-48cc-43d5-a813-fa2acaa37337%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages