Made flipper plugins a little more robust

Summary: Added some assertions and string casts to make plugins a bit more robust

Reviewed By: passy

Differential Revision: D19427909

fbshipit-source-id: 46a3138805db865b538f745fae25ce1897e35736
This commit is contained in:
Michel Weststrate
2020-01-16 04:45:03 -08:00
committed by Facebook Github Bot
parent db9c41303d
commit 28fd95589f
3 changed files with 40 additions and 12 deletions

View File

@@ -72,10 +72,14 @@ public class FlipperReactNativeJavaScriptPluginManager {
}
public void send(String pluginId, String method, String data) {
FlipperReactNativeJavaScriptPlugin plugin = getPlugin(pluginId);
if (data == null) {
plugin.getConnection().send(method, (FlipperObject) null);
return;
}
// Optimization: throwing raw strings around to the desktop would probably avoid some double
// parsing...
Object parsedData = parseJSON(data);
FlipperReactNativeJavaScriptPlugin plugin = getPlugin(pluginId);
if (parsedData instanceof FlipperArray) {
plugin.getConnection().send(method, (FlipperArray) parsedData);
} else {
@@ -134,14 +138,17 @@ public class FlipperReactNativeJavaScriptPluginManager {
}
private static Object /* FlipperArray | FlipperObject */ parseJSON(String json) {
if (json == null) {
return null;
}
// returns either a FlipperObject or Flipper array, pending the data
try {
JSONTokener tokener = new JSONTokener(json);
if (tokener.nextClean() == '[') {
char firstChar = tokener.nextClean();
tokener.back();
if (firstChar == '[') {
return new FlipperArray(new JSONArray(tokener));
} else {
tokener.back();
return new FlipperObject(new JSONObject(tokener));
}
} catch (JSONException e) {

View File

@@ -32,12 +32,14 @@ public class FlipperReactNativeJavaScriptReceiver implements FlipperReceiver {
@Override
public void onReceive(FlipperObject params, FlipperResponder responder) throws Exception {
String responderId = manager.createResponderId(responder);
WritableMap eventData = Arguments.createMap();
eventData.putString("plugin", plugin);
eventData.putString("method", method);
eventData.putString("params", params.toJsonString());
if (responder != null) {
String responderId = manager.createResponderId(responder);
eventData.putString("responderId", responderId);
}
module.sendJSEvent("react-native-flipper-receive-event", eventData);
}
}

View File

@@ -17,6 +17,20 @@ export default Flipper;
const listeners = {}; // plugin#method -> callback
const plugins = {}; // plugin -> Plugin
function assertSerializable(data) {
if (
data === undefined ||
Array.isArray(data) ||
(data && typeof data === 'object')
) {
return true;
}
throw new Error(
'Flipper: Expected serializable (undefined, an array or an object). Got: ' +
data,
);
}
class Connection {
connected;
pluginId;
@@ -30,15 +44,20 @@ class Connection {
if (!this.connected) {
throw new Error('Cannot send data, not connected');
}
assertSerializable(data);
Flipper.send(this.pluginId, method, JSON.stringify(data));
}
reportErrorWithMetadata(reason, stackTrace) {
Flipper.reportErrorWithMetadata(this.pluginId, reason, stackTrace);
Flipper.reportErrorWithMetadata(
this.pluginId,
'' + reason,
'' + stackTrace,
);
}
reportError(error) {
Flipper.reportError(this.pluginId, error);
Flipper.reportError(this.pluginId, '' + error);
}
receive(method, listener) {
@@ -59,6 +78,7 @@ class Responder {
}
success(response) {
assertSerializable(response);
Flipper.respondSuccess(
this.responderId,
response == null ? null : JSON.stringify(response),
@@ -66,15 +86,13 @@ class Responder {
}
error(response) {
assertSerializable(response);
Flipper.respondError(this.responderId, JSON.stringify(response));
}
}
function startEventListeners() {
const emitter = new NativeEventEmitter(Flipper);
emitter.removeAllListeners('react-native-flipper-plugin-connect');
emitter.removeAllListeners('react-native-flipper-plugin-disconnect');
emitter.removeAllListeners('react-native-flipper-receive-event');
emitter.addListener('react-native-flipper-plugin-connect', event => {
const {plugin} = event;
@@ -98,7 +116,8 @@ function startEventListeners() {
const {plugin, method, params, responderId} = event;
const key = plugin + '#' + method;
if (listeners[key]) {
const responder = new Responder(responderId);
const responder =
responderId != null ? new Responder(responderId) : undefined;
listeners[key](JSON.parse(params), responder);
}
});