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