From bb9b9a8b9d5868c7ab5034117b785943496f6405 Mon Sep 17 00:00:00 2001 From: Marc Horowitz Date: Fri, 5 Oct 2018 16:06:35 -0700 Subject: [PATCH] When converting arguments JS->Java, handle integers correctly Summary: If a folly::dynamic contains a double when a Java method is declared to take an int, getInt() will be called, and a C++ exception will be thrown. This change uses similar logic to NativeReadableMap.getInt() to convert a folly::dynamic double to a jint. This will still throw an exception if the JS value cannot be represented as a jint without loss. Reviewed By: fromcelticpark Differential Revision: D10209492 fbshipit-source-id: fd96416200c6b283ce5c8f8fa4c227ceb8f43054 --- .../src/main/jni/react/jni/MethodInvoker.cpp | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ReactAndroid/src/main/jni/react/jni/MethodInvoker.cpp b/ReactAndroid/src/main/jni/react/jni/MethodInvoker.cpp index e12355e208ff9e..9be87fc9957c05 100644 --- a/ReactAndroid/src/main/jni/react/jni/MethodInvoker.cpp +++ b/ReactAndroid/src/main/jni/react/jni/MethodInvoker.cpp @@ -49,6 +49,22 @@ jdouble extractDouble(const folly::dynamic& value) { } } +jint extractInteger(const folly::dynamic& value) { + // The logic here is taken from convertDynamicIfIntegral, but the + // return type and exception are different. + if (value.isInt()) { + return value.getInt(); + } + double dbl = value.getDouble(); + jint result = static_cast(dbl); + if (dbl != result) { + throw std::invalid_argument( + folly::to( + "Tried to convert jint argument, but got a non-integral double: ", dbl)); + } + return result; +} + local_ref extractCallback(std::weak_ptr& instance, const folly::dynamic& value) { if (value.isNull()) { return local_ref(nullptr); @@ -101,10 +117,10 @@ jvalue extract(std::weak_ptr& instance, char type, dynamic_iterator& i value.l = JBoolean::valueOf(static_cast(arg.getBool())).release(); break; case 'i': - value.i = static_cast(arg.getInt()); + value.i = extractInteger(arg); break; case 'I': - value.l = JInteger::valueOf(static_cast(arg.getInt())).release(); + value.l = JInteger::valueOf(extractInteger(arg)).release(); break; case 'f': value.f = static_cast(extractDouble(arg));