From d1541f169f9bf42e6a428df79e02c47ef44366d8 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 18 May 2022 09:12:10 -0700 Subject: [PATCH] Use fbjni boxed values for Java turbomodule arg conversion Summary: Simplify argument and result conversion by using existing fbjni helpers (which will cache class and method ID lookups already) Changelog: [internal] Reviewed By: RSNara Differential Revision: D36312751 fbshipit-source-id: 16713642b2c5fb4c2b6447c30652d91ddbd88224 --- .../android/ReactCommon/JavaTurboModule.cpp | 174 ++++++------------ 1 file changed, 59 insertions(+), 115 deletions(-) diff --git a/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp b/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp index dbea5632fac..f74f2227f84 100644 --- a/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp +++ b/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.cpp @@ -280,9 +280,6 @@ JNIArgs convertJSIArgsToJNIArgs( return obj; }; - jclass booleanClass = nullptr; - jclass doubleClass = nullptr; - for (unsigned int argIndex = 0; argIndex < count; argIndex += 1) { const std::string &type = methodArgTypes.at(argIndex); @@ -294,7 +291,6 @@ JNIArgs convertJSIArgsToJNIArgs( throw JavaTurboModuleArgumentConversionException( "number", argIndex, methodName, arg, &rt); } - jarg->d = arg->getNumber(); continue; } @@ -304,108 +300,64 @@ JNIArgs convertJSIArgsToJNIArgs( throw JavaTurboModuleArgumentConversionException( "boolean", argIndex, methodName, arg, &rt); } - jarg->z = (jboolean)arg->getBool(); continue; } - if (!(type == "Ljava/lang/Double;" || type == "Ljava/lang/Boolean;" || - type == "Ljava/lang/String;" || - type == "Lcom/facebook/react/bridge/ReadableArray;" || - type == "Lcom/facebook/react/bridge/Callback;" || - type == "Lcom/facebook/react/bridge/ReadableMap;")) { - throw JavaTurboModuleInvalidArgumentTypeException( - type, argIndex, methodName); - } - if (arg->isNull() || arg->isUndefined()) { jarg->l = nullptr; - continue; - } - - if (type == "Ljava/lang/Double;") { + } else if (type == "Ljava/lang/Double;") { if (!arg->isNumber()) { throw JavaTurboModuleArgumentConversionException( "number", argIndex, methodName, arg, &rt); } - - if (doubleClass == nullptr) { - doubleClass = env->FindClass("java/lang/Double"); - } - - jmethodID doubleConstructor = - env->GetMethodID(doubleClass, "", "(D)V"); jarg->l = makeGlobalIfNecessary( - env->NewObject(doubleClass, doubleConstructor, arg->getNumber())); - continue; - } - - if (type == "Ljava/lang/Boolean;") { + jni::JDouble::valueOf(arg->getNumber()).release()); + } else if (type == "Ljava/lang/Boolean;") { if (!arg->isBool()) { throw JavaTurboModuleArgumentConversionException( "boolean", argIndex, methodName, arg, &rt); } - - if (booleanClass == nullptr) { - booleanClass = env->FindClass("java/lang/Boolean"); - } - - jmethodID booleanConstructor = - env->GetMethodID(booleanClass, "", "(Z)V"); jarg->l = makeGlobalIfNecessary( - env->NewObject(booleanClass, booleanConstructor, arg->getBool())); - continue; - } - - if (type == "Ljava/lang/String;") { + jni::JBoolean::valueOf(arg->getBool()).release()); + } else if (type == "Ljava/lang/String;") { if (!arg->isString()) { throw JavaTurboModuleArgumentConversionException( "string", argIndex, methodName, arg, &rt); } - jarg->l = makeGlobalIfNecessary( env->NewStringUTF(arg->getString(rt).utf8(rt).c_str())); - continue; - } - - if (type == "Lcom/facebook/react/bridge/ReadableArray;") { - if (!(arg->isObject() && arg->getObject(rt).isArray(rt))) { - throw JavaTurboModuleArgumentConversionException( - "Array", argIndex, methodName, arg, &rt); - } - - auto dynamicFromValue = jsi::dynamicFromValue(rt, *arg); - auto jParams = - ReadableNativeArray::newObjectCxxArgs(std::move(dynamicFromValue)); - jarg->l = makeGlobalIfNecessary(jParams.release()); - continue; - } - - if (type == "Lcom/facebook/react/bridge/Callback;") { + } else if (type == "Lcom/facebook/react/bridge/Callback;") { if (!(arg->isObject() && arg->getObject(rt).isFunction(rt))) { throw JavaTurboModuleArgumentConversionException( "Function", argIndex, methodName, arg, &rt); } - jsi::Function fn = arg->getObject(rt).getFunction(rt); jarg->l = makeGlobalIfNecessary( createJavaCallbackFromJSIFunction( retainJSCallback, std::move(fn), rt, jsInvoker) .release()); - continue; - } - - if (type == "Lcom/facebook/react/bridge/ReadableMap;") { + } else if (type == "Lcom/facebook/react/bridge/ReadableArray;") { + if (!(arg->isObject() && arg->getObject(rt).isArray(rt))) { + throw JavaTurboModuleArgumentConversionException( + "Array", argIndex, methodName, arg, &rt); + } + auto dynamicFromValue = jsi::dynamicFromValue(rt, *arg); + auto jParams = + ReadableNativeArray::newObjectCxxArgs(std::move(dynamicFromValue)); + jarg->l = makeGlobalIfNecessary(jParams.release()); + } else if (type == "Lcom/facebook/react/bridge/ReadableMap;") { if (!(arg->isObject())) { throw JavaTurboModuleArgumentConversionException( "Object", argIndex, methodName, arg, &rt); } - auto dynamicFromValue = jsi::dynamicFromValue(rt, *arg); auto jParams = ReadableNativeMap::createWithContents(std::move(dynamicFromValue)); jarg->l = makeGlobalIfNecessary(jParams.release()); - continue; + } else { + throw JavaTurboModuleInvalidArgumentTypeException( + type, argIndex, methodName); } } @@ -556,81 +508,73 @@ jsi::Value JavaTurboModule::invokeJavaMethod( methodSignature.substr(methodSignature.find_last_of(')') + 1); if (returnType == "Ljava/lang/Boolean;") { auto returnObject = - (jobject)env->CallObjectMethodA(instance, methodID, jargs.data()); + env->CallObjectMethodA(instance, methodID, jargs.data()); checkJNIErrorForMethodCall(); TMPL::syncMethodCallExecutionEnd(moduleName, methodName); TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); - jsi::Value returnValue = jsi::Value::null(); - if (returnObject != nullptr) { - jclass booleanClass = env->FindClass("java/lang/Boolean"); - jmethodID booleanValueMethod = - env->GetMethodID(booleanClass, "booleanValue", "()Z"); - bool returnBoolean = - (bool)env->CallBooleanMethod(returnObject, booleanValueMethod); - checkJNIErrorForMethodCall(); - returnValue = jsi::Value(returnBoolean); + auto returnValue = jsi::Value::null(); + if (returnObject) { + auto booleanObj = jni::adopt_local( + static_cast(returnObject)); + returnValue = jsi::Value(static_cast(booleanObj->value())); } TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); TMPL::syncMethodCallEnd(moduleName, methodName); + return returnValue; + } else { + bool returnBoolean = + (bool)env->CallBooleanMethodA(instance, methodID, jargs.data()); + checkJNIErrorForMethodCall(); + + TMPL::syncMethodCallExecutionEnd(moduleName, methodName); + TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); + + jsi::Value returnValue = jsi::Value(returnBoolean); + + TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); + TMPL::syncMethodCallEnd(moduleName, methodName); + return returnValue; } - - bool returnBoolean = - (bool)env->CallBooleanMethodA(instance, methodID, jargs.data()); - checkJNIErrorForMethodCall(); - - TMPL::syncMethodCallExecutionEnd(moduleName, methodName); - TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); - - jsi::Value returnValue = jsi::Value(returnBoolean); - - TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); - TMPL::syncMethodCallEnd(moduleName, methodName); - - return returnValue; } case NumberKind: { std::string returnType = methodSignature.substr(methodSignature.find_last_of(')') + 1); if (returnType == "Ljava/lang/Double;") { auto returnObject = - (jobject)env->CallObjectMethodA(instance, methodID, jargs.data()); + env->CallObjectMethodA(instance, methodID, jargs.data()); checkJNIErrorForMethodCall(); TMPL::syncMethodCallExecutionEnd(moduleName, methodName); TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); - jsi::Value returnValue = jsi::Value::null(); - if (returnObject != nullptr) { - jclass doubleClass = env->FindClass("java/lang/Double"); - jmethodID doubleValueMethod = - env->GetMethodID(doubleClass, "doubleValue", "()D"); - double returnDouble = - (double)env->CallDoubleMethod(returnObject, doubleValueMethod); - checkJNIErrorForMethodCall(); - returnValue = jsi::Value(returnDouble); + auto returnValue = jsi::Value::null(); + if (returnObject) { + auto doubleObj = jni::adopt_local( + static_cast(returnObject)); + returnValue = jsi::Value(doubleObj->value()); } + TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); + TMPL::syncMethodCallEnd(moduleName, methodName); + return returnValue; + } else { + double returnDouble = + (double)env->CallDoubleMethodA(instance, methodID, jargs.data()); + checkJNIErrorForMethodCall(); + + TMPL::syncMethodCallExecutionEnd(moduleName, methodName); + TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); + + jsi::Value returnValue = jsi::Value(returnDouble); + TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); TMPL::syncMethodCallEnd(moduleName, methodName); return returnValue; } - - double returnDouble = - (double)env->CallDoubleMethodA(instance, methodID, jargs.data()); - checkJNIErrorForMethodCall(); - - TMPL::syncMethodCallExecutionEnd(moduleName, methodName); - TMPL::syncMethodCallReturnConversionStart(moduleName, methodName); - - jsi::Value returnValue = jsi::Value(returnDouble); - - TMPL::syncMethodCallReturnConversionEnd(moduleName, methodName); - TMPL::syncMethodCallEnd(moduleName, methodName); - return returnValue; } case StringKind: { auto returnString = @@ -655,7 +599,7 @@ jsi::Value JavaTurboModule::invokeJavaMethod( } case ObjectKind: { auto returnObject = - (jobject)env->CallObjectMethodA(instance, methodID, jargs.data()); + env->CallObjectMethodA(instance, methodID, jargs.data()); checkJNIErrorForMethodCall(); TMPL::syncMethodCallExecutionEnd(moduleName, methodName);