Fix JSON parser for NativeString in REST API responses

Latest GWT contains a change that prevents the casting of
a JavaScript String object to our NativeString and back
again. Somewhere in chain it throws a ClassCastException and
gives up, preventing the topic editing call to fail in ChangeApi.
This bug doesn't yet show up in the default build of Gerrit, as
the GWT change was made after the 2.5 release.

Switch JSON parsing to the native GWT support path, which also tries
to use the browser's native JSON parser, but can be stricter when
it has to fallback to eval(), thanks to some safety checks the GWT
team added. Once the object is parsed as a JSONValue in GWT-land
we can decide on the correct way to treat it as a JavaScriptObject
for the callback handle.

Change-Id: I027b48b8bb2d3777f0ec2ed33359d374a9997adb
This commit is contained in:
Shawn O. Pearce
2012-11-21 11:32:39 -08:00
parent 4accc9e658
commit 9cb0853696
2 changed files with 21 additions and 6 deletions

View File

@@ -19,7 +19,14 @@ import com.google.gwtjsonrpc.common.AsyncCallback;
/** Wraps a String that was returned from a JSON API. */
public final class NativeString extends JavaScriptObject {
public final native String asString() /*-{ return this; }-*/;
static NativeString wrap(String value) {
NativeString ns = (NativeString) createObject();
ns.set(value);
return ns;
}
public final native String asString() /*-{ return this.s; }-*/;
private final native void set(String v) /*-{ this.s = v; }-*/;
public static final AsyncCallback<NativeString>
unwrap(final AsyncCallback<String> cb) {

View File

@@ -32,16 +32,20 @@ public class Natives {
return Collections.emptySet();
}
@SuppressWarnings("unchecked")
public static <T extends JavaScriptObject> T parseJSON(String json) {
if (parser == null) {
parser = bestJsonParser();
if (json.startsWith("\"")) {
return (T) NativeString.wrap(parseString(parser, json));
}
// javac generics bug
return Natives.<T>parse0(parser, json);
return Natives.<T> parseObject(parser, json); // javac generics bug
}
private static native <T extends JavaScriptObject>
T parse0(JavaScriptObject p, String s)
T parseObject(JavaScriptObject p, String s)
/*-{ return p(s); }-*/;
private static native
String parseString(JavaScriptObject p, String s)
/*-{ return p(s); }-*/;
private static JavaScriptObject parser;
@@ -52,6 +56,10 @@ public class Natives {
return function(s) { return eval('(' + s + ')'); };
}-*/;
static {
parser = bestJsonParser();
}
private Natives() {
}
}