1a416e6dbSŁukasz Kosmaty // Copyright © 2021-present 650 Industries, Inc. (aka Expo) 2a416e6dbSŁukasz Kosmaty 3a416e6dbSŁukasz Kosmaty #pragma once 4a416e6dbSŁukasz Kosmaty 5a416e6dbSŁukasz Kosmaty #include <fbjni/fbjni.h> 6b7d1787dSŁukasz Kosmaty #include <jsi/jsi.h> 7a416e6dbSŁukasz Kosmaty 88bd57a9aSŁukasz Kosmaty #include <optional> 98bd57a9aSŁukasz Kosmaty 10a416e6dbSŁukasz Kosmaty namespace jni = facebook::jni; 11b7d1787dSŁukasz Kosmaty namespace jsi = facebook::jsi; 12a416e6dbSŁukasz Kosmaty 13a416e6dbSŁukasz Kosmaty namespace expo { 14b7d1787dSŁukasz Kosmaty 15b7d1787dSŁukasz Kosmaty class JSIInteropModuleRegistry; 16b7d1787dSŁukasz Kosmaty 17a416e6dbSŁukasz Kosmaty /** 18a416e6dbSŁukasz Kosmaty * A convenient wrapper for the Kotlin CodedException. 19a416e6dbSŁukasz Kosmaty * It can be used with the `jni::throwNewJavaException` function to throw a cpp exception that 20a416e6dbSŁukasz Kosmaty * will be automatically changed to the corresponding Java/Kotlin exception. 21a416e6dbSŁukasz Kosmaty * `jni::throwNewJavaException` creates and throws a C++ exception which wraps a Java exception, 22a416e6dbSŁukasz Kosmaty * so the C++ flow is interrupted. Then, when translatePendingCppExceptionToJavaException 23a416e6dbSŁukasz Kosmaty * is called at the topmost level of the native stack, the wrapped Java exception is thrown to the java caller. 24a416e6dbSŁukasz Kosmaty */ 25a416e6dbSŁukasz Kosmaty class CodedException : public jni::JavaClass<CodedException, jni::JThrowable> { 26a416e6dbSŁukasz Kosmaty public: 27a416e6dbSŁukasz Kosmaty static auto constexpr kJavaDescriptor = "Lexpo/modules/kotlin/exception/CodedException;"; 28a416e6dbSŁukasz Kosmaty 29a416e6dbSŁukasz Kosmaty static jni::local_ref<CodedException> create(const std::string &message); 308bd57a9aSŁukasz Kosmaty 318bd57a9aSŁukasz Kosmaty std::string getCode(); 328bd57a9aSŁukasz Kosmaty 338bd57a9aSŁukasz Kosmaty std::optional<std::string> getLocalizedMessage(); 34a416e6dbSŁukasz Kosmaty }; 35a416e6dbSŁukasz Kosmaty 36a416e6dbSŁukasz Kosmaty /** 37a416e6dbSŁukasz Kosmaty * A convenient wrapper for the Kotlin JavaScriptEvaluateException. 38a416e6dbSŁukasz Kosmaty */ 39a416e6dbSŁukasz Kosmaty class JavaScriptEvaluateException 40a416e6dbSŁukasz Kosmaty : public jni::JavaClass<JavaScriptEvaluateException, CodedException> { 41a416e6dbSŁukasz Kosmaty public: 42a416e6dbSŁukasz Kosmaty static auto constexpr kJavaDescriptor = "Lexpo/modules/kotlin/exception/JavaScriptEvaluateException;"; 43a416e6dbSŁukasz Kosmaty 44a416e6dbSŁukasz Kosmaty static jni::local_ref<JavaScriptEvaluateException> create( 45a416e6dbSŁukasz Kosmaty const std::string &message, 46a416e6dbSŁukasz Kosmaty const std::string &jsStack 47a416e6dbSŁukasz Kosmaty ); 48a416e6dbSŁukasz Kosmaty }; 49ce6f2823SŁukasz Kosmaty 50ce6f2823SŁukasz Kosmaty /** 51ce6f2823SŁukasz Kosmaty * A convenient wrapper for the Kotlin UnexpectedException. 52ce6f2823SŁukasz Kosmaty */ 53ce6f2823SŁukasz Kosmaty class UnexpectedException 54ce6f2823SŁukasz Kosmaty : public jni::JavaClass<UnexpectedException, CodedException> { 55ce6f2823SŁukasz Kosmaty public: 56ce6f2823SŁukasz Kosmaty static auto constexpr kJavaDescriptor = "Lexpo/modules/kotlin/exception/UnexpectedException;"; 57ce6f2823SŁukasz Kosmaty 58ce6f2823SŁukasz Kosmaty static jni::local_ref<UnexpectedException> create( 59ce6f2823SŁukasz Kosmaty const std::string &message 60ce6f2823SŁukasz Kosmaty ); 61ce6f2823SŁukasz Kosmaty }; 62b7d1787dSŁukasz Kosmaty 63*732f0c04SŁukasz Kosmaty class InvalidArgsNumberException 64*732f0c04SŁukasz Kosmaty : public jni::JavaClass<InvalidArgsNumberException, CodedException> { 65*732f0c04SŁukasz Kosmaty public: 66*732f0c04SŁukasz Kosmaty static auto constexpr kJavaDescriptor = "Lexpo/modules/kotlin/exception/InvalidArgsNumberException;"; 67*732f0c04SŁukasz Kosmaty 68*732f0c04SŁukasz Kosmaty static jni::local_ref<InvalidArgsNumberException> create( 69*732f0c04SŁukasz Kosmaty int received, 70*732f0c04SŁukasz Kosmaty int expected 71*732f0c04SŁukasz Kosmaty ); 72*732f0c04SŁukasz Kosmaty }; 73*732f0c04SŁukasz Kosmaty 74b7d1787dSŁukasz Kosmaty /** 75b7d1787dSŁukasz Kosmaty * Tries to rethrow an jni::JniException as a js version of the CodedException 76b7d1787dSŁukasz Kosmaty */ 77b7d1787dSŁukasz Kosmaty [[noreturn]] void rethrowAsCodedError( 78b7d1787dSŁukasz Kosmaty jsi::Runtime &rt, 79b7d1787dSŁukasz Kosmaty jni::JniException &jniException 80b7d1787dSŁukasz Kosmaty ); 81e0f520f5SKudo Chien 82d8bd928cSŁukasz Kosmaty jsi::Value makeCodedError( 83d8bd928cSŁukasz Kosmaty jsi::Runtime &runtime, 84d8bd928cSŁukasz Kosmaty jsi::String code, 85d8bd928cSŁukasz Kosmaty jsi::String message 86d8bd928cSŁukasz Kosmaty ); 87d8bd928cSŁukasz Kosmaty 88e0f520f5SKudo Chien /** 89e0f520f5SKudo Chien * [email protected] is built by ndk r21, its exceptions are not catchable by expo-modules-core built by ndk r23+. 90e0f520f5SKudo Chien * To catch these excetptions, we copy the `facebook::jni::throwPendingJniExceptionAsCppException` here and throw exceptions on our own. 91e0f520f5SKudo Chien */ 92e0f520f5SKudo Chien void throwPendingJniExceptionAsCppException(); 93e0f520f5SKudo Chien 94e0f520f5SKudo Chien /** 95e0f520f5SKudo Chien * Same as `facebook::jni::throwNewJavaException` but throwing exceptions on our own. 96e0f520f5SKudo Chien */ 97e0f520f5SKudo Chien [[noreturn]] void throwNewJavaException(jthrowable throwable); 98a416e6dbSŁukasz Kosmaty } // namespace expo 99