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
On Thu, Apr 16, 2009 at 11:03 AM, Eric Ayers <[email protected]> wrote:
> Recently I've been wrapping some of my JavaScriptObjects using the builder
> pattern where an instance of the object you are setting is in the return
> value.
>
> http://galgwt-reviews.appspot.com/21604/diff/1/18?context=10
>
> Which you would invoke as:
>
>
> DraggableObject obj = new DraggableObject(elem,
> DraggableObjectOptions.newInstance().setLeft(10).setTop(5));
>
> Can anyone think of a reason I might be shooting myself in the foot
> performance wise or code size wise as opposed to making these strict setter
> methods? I don't want to set a bad example.
>
> -Eric.
> --
> Eric Z. Ayers - GWT Team - Atlanta, GA USA
> http://code.google.com/webtoolkit/
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---