PluginAPI: Don't convert to String in RestApi.get() method
RestApi helper class makes use of ActionContext that makes use of RestApi in Gerrit core to route Rest calls. Because ActionContext was optimized for invocations from JavaScript plugin hooks, it's converting NativeString to String. The easiest way to see why this behaviour is needed is to investigate the call graph: ActionButton => ActionContext.call() => ActionContext.get() => RestApiCore.get() => return NativeString.asString() => alert() called from JavaSrcipt that dump string content. An example of this approach is implemented in cookbook-plugin: 1 function onSayHelloProject(c) { 2 var f = c.textfield(); 3 var t = c.checkbox(); 4 var b = c.button('Say hello', {onclick: function(){ 5 c.call( 6 {message: f.value, french: t.checked}, 7 function(r) { 8 c.hide(); 9 window.alert(r); 10 c.refresh(); 11 }); 12 }}); Without this implicit conversion the output on the line 9 in the example above would not be: "Hello dude..." but "[Object]". While this implicit conversion is needed and correct in this use case, when calling Rest API invocations from ActionButton, it is not wanted and wrong when called from normal plugin screen through RestApiPlugin, that makes itself use of the same implementation of ActionContext, to route the RestAPI calls to RestApiCore implementation. The call graph: PluginScreen => RestApiPlugin.get() => ActionContext.get() => RestApiCore.get() => return NativeString.asString() => type error That's because in this use case, no implicit conversion should happen, as the callback expects NativeString and not String, e.g.: private void retrieveGerritVersion(final Screen screen) { new RestApi("config").view("server").view("version") .get(new AsyncCallback<NativeString>() { @Override public void onSuccess(NativeString r) { screen.setPageTitle("cookbook index@" + r.asString()); } [...] Conclusion: while correct and expected in one use case, it's wrong and leads to breakage in another use case. To rectify it, avoid conversion when called from RestApiPlugin, as it's never wanted: PluginScreen => RestApiPlugin.get() => ActionContext.get2() => RestApiCore.get() => return NativeString The same problem is fixed for the other Rest methods {put|post|delete}. Change-Id: Id6c042478cab797838c1808602712a48039ec062
This commit is contained in:
parent
9b8240b0f6
commit
a4bccbfafe
@ -157,6 +157,14 @@ public class ActionContext extends JavaScriptObject {
|
|||||||
api.get(wrap(cb));
|
api.get(wrap(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #get(RestApi, JavaScriptObject)} but without converting
|
||||||
|
* a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void getRaw(RestApi api, final JavaScriptObject cb) {
|
||||||
|
api.get(wrapRaw(cb));
|
||||||
|
}
|
||||||
|
|
||||||
static final void post(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
|
static final void post(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
|
||||||
if (NativeString.is(in)) {
|
if (NativeString.is(in)) {
|
||||||
post(api, ((NativeString) in).asString(), cb);
|
post(api, ((NativeString) in).asString(), cb);
|
||||||
@ -165,14 +173,42 @@ public class ActionContext extends JavaScriptObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #post(RestApi, JavaScriptObject, JavaScriptObject)} but
|
||||||
|
* without converting a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void postRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
|
||||||
|
if (NativeString.is(in)) {
|
||||||
|
postRaw(api, ((NativeString) in).asString(), cb);
|
||||||
|
} else {
|
||||||
|
api.post(in, wrapRaw(cb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static final void post(RestApi api, String in, JavaScriptObject cb) {
|
static final void post(RestApi api, String in, JavaScriptObject cb) {
|
||||||
api.post(in, wrap(cb));
|
api.post(in, wrap(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #post(RestApi, String, JavaScriptObject)} but without
|
||||||
|
* converting a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void postRaw(RestApi api, String in, JavaScriptObject cb) {
|
||||||
|
api.post(in, wrapRaw(cb));
|
||||||
|
}
|
||||||
|
|
||||||
static final void put(RestApi api, JavaScriptObject cb) {
|
static final void put(RestApi api, JavaScriptObject cb) {
|
||||||
api.put(wrap(cb));
|
api.put(wrap(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #put(RestApi, JavaScriptObject)} but without converting
|
||||||
|
* a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void putRaw(RestApi api, JavaScriptObject cb) {
|
||||||
|
api.put(wrapRaw(cb));
|
||||||
|
}
|
||||||
|
|
||||||
static final void put(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
|
static final void put(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
|
||||||
if (NativeString.is(in)) {
|
if (NativeString.is(in)) {
|
||||||
put(api, ((NativeString) in).asString(), cb);
|
put(api, ((NativeString) in).asString(), cb);
|
||||||
@ -181,14 +217,42 @@ public class ActionContext extends JavaScriptObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #put(RestApi, JavaScriptObject, JavaScriptObject)} but
|
||||||
|
* without converting a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void putRaw(RestApi api, JavaScriptObject in, JavaScriptObject cb) {
|
||||||
|
if (NativeString.is(in)) {
|
||||||
|
putRaw(api, ((NativeString) in).asString(), cb);
|
||||||
|
} else {
|
||||||
|
api.put(in, wrapRaw(cb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static final void put(RestApi api, String in, JavaScriptObject cb) {
|
static final void put(RestApi api, String in, JavaScriptObject cb) {
|
||||||
api.put(in, wrap(cb));
|
api.put(in, wrap(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #put(RestApi, String, JavaScriptObject)} but without
|
||||||
|
* converting a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void putRaw(RestApi api, String in, JavaScriptObject cb) {
|
||||||
|
api.put(in, wrapRaw(cb));
|
||||||
|
}
|
||||||
|
|
||||||
static final void delete(RestApi api, JavaScriptObject cb) {
|
static final void delete(RestApi api, JavaScriptObject cb) {
|
||||||
api.delete(wrap(cb));
|
api.delete(wrap(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as {@link #delete(RestApi, JavaScriptObject)} but without
|
||||||
|
* converting a {@link NativeString} result to String.
|
||||||
|
*/
|
||||||
|
static final void deleteRaw(RestApi api, JavaScriptObject cb) {
|
||||||
|
api.delete(wrapRaw(cb));
|
||||||
|
}
|
||||||
|
|
||||||
private static GerritCallback<JavaScriptObject> wrap(final JavaScriptObject cb) {
|
private static GerritCallback<JavaScriptObject> wrap(final JavaScriptObject cb) {
|
||||||
return new GerritCallback<JavaScriptObject>() {
|
return new GerritCallback<JavaScriptObject>() {
|
||||||
@Override
|
@Override
|
||||||
@ -202,4 +266,13 @@ public class ActionContext extends JavaScriptObject {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GerritCallback<JavaScriptObject> wrapRaw(final JavaScriptObject cb) {
|
||||||
|
return new GerritCallback<JavaScriptObject>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JavaScriptObject result) {
|
||||||
|
ApiGlue.invoke(cb, result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,6 +102,12 @@ public class ApiGlue {
|
|||||||
Lcom/google/gwt/core/client/JavaScriptObject;)
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
(this._api(u), b);
|
(this._api(u), b);
|
||||||
},
|
},
|
||||||
|
get_raw: function(u,b) {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::getRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), b);
|
||||||
|
},
|
||||||
post: function(u,i,b) {
|
post: function(u,i,b) {
|
||||||
if (typeof i == 'string') {
|
if (typeof i == 'string') {
|
||||||
@com.google.gerrit.client.api.ActionContext::post(
|
@com.google.gerrit.client.api.ActionContext::post(
|
||||||
@ -117,6 +123,21 @@ public class ApiGlue {
|
|||||||
(this._api(u), i, b);
|
(this._api(u), i, b);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
post_raw: function(u,i,b) {
|
||||||
|
if (typeof i == 'string') {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::postRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Ljava/lang/String;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), i, b);
|
||||||
|
} else {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::postRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), i, b);
|
||||||
|
}
|
||||||
|
},
|
||||||
put: function(u,i,b) {
|
put: function(u,i,b) {
|
||||||
if (b) {
|
if (b) {
|
||||||
if (typeof i == 'string') {
|
if (typeof i == 'string') {
|
||||||
@ -139,6 +160,28 @@ public class ApiGlue {
|
|||||||
(this._api(u), i);
|
(this._api(u), i);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
put_raw: function(u,i,b) {
|
||||||
|
if (b) {
|
||||||
|
if (typeof i == 'string') {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::putRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Ljava/lang/String;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), i, b);
|
||||||
|
} else {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::putRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), i, b);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::putRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), i);
|
||||||
|
}
|
||||||
|
},
|
||||||
'delete': function(u,b) {
|
'delete': function(u,b) {
|
||||||
@com.google.gerrit.client.api.ActionContext::delete(
|
@com.google.gerrit.client.api.ActionContext::delete(
|
||||||
Lcom/google/gerrit/client/rpc/RestApi;
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
@ -151,6 +194,12 @@ public class ApiGlue {
|
|||||||
Lcom/google/gwt/core/client/JavaScriptObject;)
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
(this._api(u), b);
|
(this._api(u), b);
|
||||||
},
|
},
|
||||||
|
del_raw: function(u,b) {
|
||||||
|
@com.google.gerrit.client.api.ActionContext::deleteRaw(
|
||||||
|
Lcom/google/gerrit/client/rpc/RestApi;
|
||||||
|
Lcom/google/gwt/core/client/JavaScriptObject;)
|
||||||
|
(this._api(u), b);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}-*/;
|
}-*/;
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ public class RestApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static native void get(String p, JavaScriptObject r)
|
private static native void get(String p, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.get(p, r) }-*/;
|
/*-{ $wnd.Gerrit.get_raw(p, r) }-*/;
|
||||||
|
|
||||||
public <T extends JavaScriptObject>
|
public <T extends JavaScriptObject>
|
||||||
void put(AsyncCallback<T> cb) {
|
void put(AsyncCallback<T> cb) {
|
||||||
@ -118,7 +118,7 @@ public class RestApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static native void put(String p, JavaScriptObject r)
|
private static native void put(String p, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.put(p, r) }-*/;
|
/*-{ $wnd.Gerrit.put_raw(p, r) }-*/;
|
||||||
|
|
||||||
public <T extends JavaScriptObject>
|
public <T extends JavaScriptObject>
|
||||||
void put(String content, AsyncCallback<T> cb) {
|
void put(String content, AsyncCallback<T> cb) {
|
||||||
@ -127,7 +127,7 @@ public class RestApi {
|
|||||||
|
|
||||||
private static native
|
private static native
|
||||||
void put(String p, String c, JavaScriptObject r)
|
void put(String p, String c, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.put(p, c, r) }-*/;
|
/*-{ $wnd.Gerrit.put_raw(p, c, r) }-*/;
|
||||||
|
|
||||||
public <T extends JavaScriptObject>
|
public <T extends JavaScriptObject>
|
||||||
void put(JavaScriptObject content, AsyncCallback<T> cb) {
|
void put(JavaScriptObject content, AsyncCallback<T> cb) {
|
||||||
@ -136,7 +136,7 @@ public class RestApi {
|
|||||||
|
|
||||||
private static native
|
private static native
|
||||||
void put(String p, JavaScriptObject c, JavaScriptObject r)
|
void put(String p, JavaScriptObject c, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.put(p, c, r) }-*/;
|
/*-{ $wnd.Gerrit.put_raw(p, c, r) }-*/;
|
||||||
|
|
||||||
public <T extends JavaScriptObject>
|
public <T extends JavaScriptObject>
|
||||||
void post(String content, AsyncCallback<T> cb) {
|
void post(String content, AsyncCallback<T> cb) {
|
||||||
@ -145,7 +145,7 @@ public class RestApi {
|
|||||||
|
|
||||||
private static native
|
private static native
|
||||||
void post(String p, String c, JavaScriptObject r)
|
void post(String p, String c, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.post(p, c, r) }-*/;
|
/*-{ $wnd.Gerrit.post_raw(p, c, r) }-*/;
|
||||||
|
|
||||||
public <T extends JavaScriptObject>
|
public <T extends JavaScriptObject>
|
||||||
void post(JavaScriptObject content, AsyncCallback<T> cb) {
|
void post(JavaScriptObject content, AsyncCallback<T> cb) {
|
||||||
@ -154,14 +154,14 @@ public class RestApi {
|
|||||||
|
|
||||||
private static native
|
private static native
|
||||||
void post(String p, JavaScriptObject c, JavaScriptObject r)
|
void post(String p, JavaScriptObject c, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.post(p, c, r) }-*/;
|
/*-{ $wnd.Gerrit.post_raw(p, c, r) }-*/;
|
||||||
|
|
||||||
public void delete(AsyncCallback<NoContent> cb) {
|
public void delete(AsyncCallback<NoContent> cb) {
|
||||||
delete(path(), wrap(cb));
|
delete(path(), wrap(cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native void delete(String p, JavaScriptObject r)
|
private static native void delete(String p, JavaScriptObject r)
|
||||||
/*-{ $wnd.Gerrit.del(p, r) }-*/;
|
/*-{ $wnd.Gerrit.del_raw(p, r) }-*/;
|
||||||
|
|
||||||
private static native <T extends JavaScriptObject>
|
private static native <T extends JavaScriptObject>
|
||||||
JavaScriptObject wrap(AsyncCallback<T> b) /*-{
|
JavaScriptObject wrap(AsyncCallback<T> b) /*-{
|
||||||
|
Loading…
Reference in New Issue
Block a user