ionic-team / capacitor

Build cross-platform Native Progressive Web Apps for iOS, Android, and the Web ⚡️
https://capacitorjs.com
MIT License
12.1k stars 1k forks source link

FR: support non JSObject method result and call arguments #1132

Open MarkChrisLevy opened 5 years ago

MarkChrisLevy commented 5 years ago

Currently Capacitor allows to return from native method only JSObject (a map, with string key and any json serializable value). The same goes to method arguments - only one arguments of JSObject is supported (of course, it is a map, where multiple parameters can be passed). That restriction requires additional steps when interacting with native methods and is boilerplate (e.g. StatusBar#setStyle(options: {style: StatusBarStyleOptions}) or Geolocation#getCurrentPosition() => Promise<{coords: any}>).

Calling native method

Arguments of js method call are accessible in js as array (arguments variable) and that array should be passed to PluginCall (instead of a map) as call data/options. Native PluginCall instance should have methods for reading the arguments:

Now, it maybe looks like a problem to support array arguments and JSObject argument in the same time (e.g. what if there is only one argument in a js call and it is JSObject), but it is not. PluginCall data/options should always be (underneath) an array of arguments, that comes from js but in the same time getString(String key), getDouble(String key), get(String key) should work, but will refer to first argument, which should be JSObject (if argument is not a JSObject error should be thrown). That way, we can provide backward compatibility and additional feature, which imho is clean and flexible ;-)

Returning from native method

PluginCall should have a methods for returing from method invocation for each json type, e.g.:

mlynch commented 5 years ago

The work to make this work would be in the bridge (converting plugin call result to JSON/etc.)

One way we could do it fairly easily without changing the bridge at all: add some methods to PluginCall.resolve/success to take primitives, and then wrap them in a JSON object with a key like { "__str": value }. We'd then need to pull these special values out in native-bridge.js.

In this way, the plugin author and the plugin consumer in JS get the primitive value back, but we keep the simplicity of just passing around JSObjects in the bridge.

MarkChrisLevy commented 5 years ago

The one thing is to return non JSON Object values, but same goes to call arguments. But as I understand, you like the idea, so I will work on this and prepare a PR.

romaia commented 2 years ago

Returning other values that are valid json would also be nice: Boolean, float, null, arrays...