Well, for one thing, there appears to be a bug in the compiler.
Consider the following:
public void onModuleLoad() {
Window.alert(Builder.newInstance().setFoo("Hello").setBar("World")
.setBaz("!").toString());
}
static final class Builder extends JavaScriptObject {
protected Builder() {
}
public static Builder newInstance() {
return createObject().cast();
}
public native Builder setFoo(String x) /*-{
this.foo = x;
return this;
}-*/;
public native Builder setBar(String x) /*-{
this.bar = x;
return this;
}-*/;
public native Builder setBaz(String x) /*-{
this.baz = x;
return this;
}-*/;
}
The output from this is:
$wnd.alert($toString($setBaz($setBar(({}.foo = 'Hello' , {}), 'World'), '!')));
The multi-expression that is inlined in place of setFoo() does not
yield the right 'this' value.
You can workaround this bug by preventing the JsInliner from inlining,
you can do this in several ways, one way is to violate evaluation
order, e.g.
public native Builder setFoo(String x) /*-{
return x=this.foo=x, this;
}-*/;
This forces 'x' to be evaluated before 'this$static' which is the real
first parameter of this method, so inlining is derailed. The
generated code then looks like this:
$wnd.alert($toString($setBaz($setBar($setFoo({}, 'Hello'), 'World'), '!')));
function $setFoo(this$static, x){
return x = this$static.foo = x , this$static;
}
In an ideal world, we'd have something like this generated as JS:
DraggableObjectOptions.newInstance().setLeft(10).setTop(5)
becomes
{left: 10, top: 5}
One way to accomplish this to have your builder use 'eval' and String
concat, e.g.
static final class Builder extends JavaScriptObject {
protected Builder() {}
public static native Builder newInstance() /*-{
return "{";
}-*/;
public native Builder setFoo(int x) /*-{
return this + "foo:"+x+", ";
}-*/;
public native Builder setBar(int x) /*-{
return this + "bar: "+x+", ";
}-*/;
public native Builder setBaz(int x) /*-{
return this + "baz: "+x+", ";
}-*/;
public native Builder end() /*-{
return eval(this + "}");
}-*/;
}
(hosted mode version not shown)
With proper static simplification in JS, something like
setFoo(10).setBar(20).setBaz(30) is compiled to:
eval("{foo:10,bar:20,baz:30}")
Of course, eval is yucky to use.
-Ray