mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Add exception handling to method invocations
Summary: If you call into a Java method (from C++ using JNI) that raises an exception, the JNI call won't actually raise a C++ error. Instead, the `JNIEnv` will record the pending Java exception and the C++ will continue executing as normal. This is bad because the next time you call into JNI, the app will actually crash, unless you explicitly cleared the exception using `JNIEnv::ExceptionClear()` before the JNI call. With respect to TurboModules, we need to make sure that RedBoxes show up whenever a native methods raise an exception. We also don't want the app to crash when a JNI method call fails because of a raised exception. Therefore, in this diff, I raise a C++ exception if `JNIEnv::ExceptionCheck()` is true. Reviewed By: mdvacca Differential Revision: D14738540 fbshipit-source-id: 4c3063aa93ae7aef025bd2dab6b45059bb8fb409
This commit is contained in:
committed by
Facebook Github Bot
parent
d1c35aaa84
commit
129aeacf48
@@ -143,6 +143,23 @@ jsi::Value JavaTurboModule::get(jsi::Runtime& runtime, const jsi::PropNameID& pr
|
||||
}
|
||||
}
|
||||
|
||||
static void throwIfJNIReportsPendingException() {
|
||||
JNIEnv *env = jni::Environment::current();
|
||||
if (env->ExceptionCheck()) {
|
||||
jthrowable ex = env->ExceptionOccurred();
|
||||
|
||||
// There should be no pending exceptions before we call into JNI
|
||||
env->ExceptionClear();
|
||||
|
||||
auto exception = jni::adopt_local(ex);
|
||||
auto getMessage =
|
||||
exception->getClass()->getMethod<std::string()>("getMessage");
|
||||
auto message = getMessage(exception)->toStdString();
|
||||
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
|
||||
jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
jsi::Runtime &runtime,
|
||||
TurboModuleMethodValueKind valueKind,
|
||||
@@ -166,19 +183,29 @@ jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
switch (valueKind) {
|
||||
case VoidKind: {
|
||||
env->CallVoidMethodA(instance, methodID, jargs.data());
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
return jsi::Value::undefined();
|
||||
}
|
||||
case BooleanKind: {
|
||||
return jsi::Value(
|
||||
(bool)env->CallBooleanMethodA(instance, methodID, jargs.data()));
|
||||
bool returnBoolean =
|
||||
(bool)env->CallBooleanMethodA(instance, methodID, jargs.data());
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
return jsi::Value(returnBoolean);
|
||||
}
|
||||
case NumberKind: {
|
||||
return jsi::Value(
|
||||
(double)env->CallDoubleMethodA(instance, methodID, jargs.data()));
|
||||
double returnDouble =
|
||||
(double)env->CallDoubleMethodA(instance, methodID, jargs.data());
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
return jsi::Value(returnDouble);
|
||||
}
|
||||
case StringKind: {
|
||||
auto returnString =
|
||||
(jstring)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
if (returnString == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
@@ -190,6 +217,8 @@ jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
case ObjectKind: {
|
||||
auto returnObject =
|
||||
(jobject)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
@@ -200,6 +229,8 @@ jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
case ArrayKind: {
|
||||
auto returnObject =
|
||||
(jobject)env->CallObjectMethodA(instance, methodID, jargs.data());
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
if (returnObject == nullptr) {
|
||||
return jsi::Value::null();
|
||||
}
|
||||
@@ -254,6 +285,8 @@ jsi::Value JavaTurboModule::invokeJavaMethod(
|
||||
|
||||
jsi::Value promise =
|
||||
Promise.callAsConstructor(runtime, promiseConstructorArg);
|
||||
throwIfJNIReportsPendingException();
|
||||
|
||||
return promise;
|
||||
}
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user