A PluginCall carries the options object as call.data, a JSObject, with typed getters on top: getString, getInt, getLong, getFloat, getDouble, getBoolean, getObject and getArray. Each returns null (or your default) when the key is missing or holds an unexpected Java type. That second case broke the first version of canFit(), which read call.getLong("bytes"):
> lab.DiskSpace.canFit({ bytes: 25000000 }).catch((e) => e.code + ': ' + e.message)
"BAD_SIZE: canFit needs a non-negative number in 'bytes'"With 3000000000 bytes it worked. org.json parses 25000000 into an Integer and 3000000000 into a Long; getLong() accepts only Long, and getDouble() takes Integer but not Long. Reading call.data.opt() as a Kotlin Number covers both. After the fix, on the emulator:
> lab.DiskSpace.canFit({ bytes: 20e9 })
{
"fits": false,
"freeBytes": 9223254016
}Resolve each call exactly once, with a JSObject (an org.json.JSONObject with a chainable put(); nest another JSObject, or a JSArray for lists). Or reject it with a code, which JavaScript reads as the Error's code, as BAD_SIZE shows. A method that does neither leaves its promise pending forever; only a call marked setKeepAlive(true) may answer more than once.