expo-modules-core 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/android/CMakeLists.txt +1 -1
- package/android/build.gradle +54 -24
- package/android/proguard-rules.pro +7 -0
- package/android/src/main/cpp/Exceptions.cpp +49 -16
- package/android/src/main/cpp/Exceptions.h +17 -1
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +8 -0
- package/android/src/main/cpp/ExpoModulesHostObject.h +2 -0
- package/android/src/main/cpp/JNIFunctionBody.cpp +8 -2
- package/android/src/main/cpp/JSReferencesCache.cpp +0 -10
- package/android/src/main/cpp/JSReferencesCache.h +1 -2
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +23 -0
- package/android/src/main/cpp/JavaScriptModuleObject.h +11 -2
- package/android/src/main/cpp/JavaScriptValue.cpp +1 -1
- package/android/src/main/cpp/MethodMetadata.cpp +96 -22
- package/android/src/main/cpp/MethodMetadata.h +5 -0
- package/android/src/main/cpp/types/FrontendConverter.cpp +2 -2
- package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +2 -1
- package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +4 -0
- package/android/src/main/java/expo/modules/interfaces/barcodescanner/BarCodeScannerResult.java +52 -0
- package/android/src/main/java/expo/modules/interfaces/filesystem/AppDirectoriesModuleInterface.kt +8 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +33 -13
- package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +0 -7
- package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt +1 -1
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +3 -4
- package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +8 -0
- package/android/src/main/java/expo/modules/kotlin/types/Enumerable.kt +9 -0
- package/android/src/main/java/expo/modules/kotlin/{callbacks/ViewCallback.kt → viewevent/ViewEvent.kt} +7 -3
- package/android/src/main/java/expo/modules/kotlin/{callbacks/ViewCallbackDelegate.kt → viewevent/ViewEventDelegate.kt} +13 -6
- package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +17 -6
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +2 -1
- package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +3 -2
- package/build/EventEmitter.d.ts +1 -0
- package/build/EventEmitter.d.ts.map +1 -1
- package/build/EventEmitter.js +9 -1
- package/build/EventEmitter.js.map +1 -1
- package/ios/Fabric/ExpoFabricView.swift +10 -0
- package/ios/Fabric/ExpoFabricViewObjC.h +2 -0
- package/ios/Fabric/ExpoFabricViewObjC.mm +6 -0
- package/ios/JSI/EXJSIUtils.h +4 -0
- package/ios/JSI/EXJSIUtils.mm +21 -4
- package/ios/Swift/Arguments/{ConvertibleArgument.swift → Convertible.swift} +4 -1
- package/ios/Swift/Arguments/Convertibles.swift +6 -6
- package/ios/Swift/Arguments/{EnumArgument.swift → Enumerable.swift} +7 -4
- package/ios/Swift/Conversions.swift +12 -3
- package/ios/Swift/Convertibles/Convertibles+Color.swift +2 -2
- package/ios/Swift/Convertibles/Either.swift +1 -1
- package/ios/Swift/DynamicTypes/AnyDynamicType.swift +1 -1
- package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +2 -2
- package/ios/Swift/DynamicTypes/DynamicEnumType.swift +2 -2
- package/ios/Swift/DynamicTypes/DynamicType.swift +2 -2
- package/ios/Swift/Events/EventDispatcher.swift +65 -8
- package/ios/Swift/Exceptions/CodedError.swift +13 -8
- package/ios/Swift/Exceptions/Exception.swift +17 -4
- package/ios/Swift/Modules/ModuleDefinition.swift +9 -0
- package/ios/Swift/Promise.swift +1 -1
- package/ios/Swift/Records/Record.swift +2 -2
- package/ios/Swift/Views/ViewDefinition.swift +8 -0
- package/ios/Swift/Views/ViewLifecycleMethod.swift +48 -0
- package/ios/Swift/Views/ViewManagerDefinition.swift +17 -0
- package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +11 -0
- package/ios/Swift/Views/ViewModuleWrapper.swift +4 -2
- package/ios/Tests/DynamicTypeSpec.swift +2 -2
- package/ios/Tests/{EnumArgumentSpec.swift → EnumerableSpec.swift} +2 -2
- package/package.json +3 -3
- package/src/EventEmitter.ts +19 -1
- package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +0 -5
- package/ios/Swift/Events/Event.swift +0 -43
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,36 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 0.13.1 — 2022-10-27
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fixed `~CallbackWrapper()` dangling pointer crashes when reloading the app on Android. ([#19699](https://github.com/expo/expo/pull/19699) by [@kudo](https://github.com/kudo), [@kudo](https://github.com/kudo))
|
|
18
|
+
|
|
19
|
+
## 0.13.0 — 2022-10-25
|
|
20
|
+
|
|
21
|
+
### 🛠 Breaking changes
|
|
22
|
+
|
|
23
|
+
- Convertible enums must inherit from `expo.modules.kotlin.types.Enumerable` on Android. ([#19551](https://github.com/expo/expo/pull/19551) by [@lukmccall](https://github.com/lukmccall))
|
|
24
|
+
- `AppContext.currentActivity` is not longer returning `AppCompatActivity`, but an instance of `android.app.Activity` class. ([#19573](https://github.com/expo/expo/pull/19573) by [@lukmccall](https://github.com/lukmccall))
|
|
25
|
+
|
|
26
|
+
### ⚠️ Notices
|
|
27
|
+
|
|
28
|
+
- Deprecated `ConvertibleArgument` in favor of `Convertible` and `EnumArgument` in favor of `Enumerable`. ([#19612](https://github.com/expo/expo/pull/19612) by [@tsapeta](https://github.com/tsapeta))
|
|
29
|
+
|
|
30
|
+
### 🎉 New features
|
|
31
|
+
|
|
32
|
+
- Implemented a mechanism for hooking into to the view lifecycle events (introduces new `OnViewDidUpdateProps` definition component). ([#19549](https://github.com/expo/expo/pull/19549) by [@tsapeta](https://github.com/tsapeta))
|
|
33
|
+
|
|
34
|
+
### 🐛 Bug fixes
|
|
35
|
+
|
|
36
|
+
- Fixed records aren't correctly converted to JS objects in the release builds on Android. ([#19551](https://github.com/expo/expo/pull/19551) by [@lukmccall](https://github.com/lukmccall))
|
|
37
|
+
- Reject promises with a `CodedError` instead of a plain object. ([#19605](https://github.com/expo/expo/pull/19605) by [@tsapeta](https://github.com/tsapeta))
|
|
38
|
+
|
|
39
|
+
### 💡 Others
|
|
40
|
+
|
|
41
|
+
- Simplified dispatching view events. ([#19537](https://github.com/expo/expo/pull/19537) by [@tsapeta](https://github.com/tsapeta))
|
|
42
|
+
|
|
13
43
|
## 0.12.0 — 2022-10-06
|
|
14
44
|
|
|
15
45
|
### 🛠 Breaking changes
|
|
@@ -43,6 +73,7 @@
|
|
|
43
73
|
- Add the `RegisterActivityContracts` component to register all of activity result contracts on Android. ([#19180](https://github.com/expo/expo/pull/19180) by [@lukmccall](https://github.com/lukmccall))
|
|
44
74
|
- Improves JSI/JNI type conversion to support complex function arguments on Android. ([#19120](https://github.com/expo/expo/pull/19120) & [#19094](https://github.com/expo/expo/pull/19094) by [@lukmccall](https://github.com/lukmccall))
|
|
45
75
|
- Using JSI instead of the bridge to call native methods also on legacy modules on iOS. ([#19209](https://github.com/expo/expo/pull/19209) by [@lukmccall](https://github.com/lukmccall))
|
|
76
|
+
- Added `cacheDirectory` and `persistentFilesDirectory` to `AppContext` on Android to fix cache directories being incorrect in new Sweet API modules. It uses a new `AppDirectoriesModule` to get correct scoped directories from old module API. ([#19205](https://github.com/expo/expo/pull/19205) by [@aleqsio](https://github.com/aleqsio))
|
|
46
77
|
|
|
47
78
|
### 🐛 Bug fixes
|
|
48
79
|
|
|
@@ -51,6 +82,7 @@
|
|
|
51
82
|
- Update gradle excludes to fix detox tests. ([#19254](https://github.com/expo/expo/pull/19254) by [@esamelson](https://github.com/esamelson))
|
|
52
83
|
- Fixed event listeners do not work when running with remote debugging mode on iOS. ([#19211](https://github.com/expo/expo/pull/19211) by [@kudo](https://github.com/kudo))
|
|
53
84
|
- Use shared C++ runtime to reduce library size on Android. ([#19372](https://github.com/expo/expo/pull/19372) by [@kudo](https://github.com/kudo))
|
|
85
|
+
- Fixed `JSCRuntime destroyed with a dangling API object` on Android. ([#19487](https://github.com/expo/expo/pull/19487) by [@lukmccall](https://github.com/lukmccall))
|
|
54
86
|
|
|
55
87
|
### 💡 Others
|
|
56
88
|
|
package/android/CMakeLists.txt
CHANGED
|
@@ -85,7 +85,7 @@ if(${UNIT_TEST})
|
|
|
85
85
|
PATHS ${HERMES_SO_DIR}
|
|
86
86
|
NO_CMAKE_FIND_ROOT_PATH
|
|
87
87
|
)
|
|
88
|
-
set(JSEXECUTOR_INCLUDE
|
|
88
|
+
set(JSEXECUTOR_INCLUDE ${HERMES_HEADER_DIR} ${HERMES_HEADER_DIR}/API ${HERMES_HEADER_DIR}/public)
|
|
89
89
|
else()
|
|
90
90
|
find_library(
|
|
91
91
|
JSEXECUTOR_LIB
|
package/android/build.gradle
CHANGED
|
@@ -6,7 +6,7 @@ apply plugin: 'maven-publish'
|
|
|
6
6
|
apply plugin: "de.undercouch.download"
|
|
7
7
|
|
|
8
8
|
group = 'host.exp.exponent'
|
|
9
|
-
version = '0.
|
|
9
|
+
version = '0.13.1'
|
|
10
10
|
|
|
11
11
|
buildscript {
|
|
12
12
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -39,12 +39,6 @@ buildscript {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
def isAndroidTest = {
|
|
43
|
-
Gradle gradle = getGradle()
|
|
44
|
-
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
|
|
45
|
-
return tskReqStr.contains("AndroidTest")
|
|
46
|
-
}.call()
|
|
47
|
-
|
|
48
42
|
def isExpoModulesCoreTests = {
|
|
49
43
|
Gradle gradle = getGradle()
|
|
50
44
|
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
|
|
@@ -89,7 +83,12 @@ def currentHermesVersion = file("${REACT_NATIVE_DIR}/sdks/.hermesversion").exist
|
|
|
89
83
|
def hasHermesProject = findProject(":ReactAndroid:hermes-engine") != null
|
|
90
84
|
def prebuiltHermesCacheHit = hasHermesProject && currentHermesVersion == prebuiltHermesVersion
|
|
91
85
|
|
|
86
|
+
// By default we are going to download and unzip hermes inside the /sdks/hermes folder
|
|
87
|
+
// but you can provide an override for where the hermes source code is located.
|
|
88
|
+
def hermesDir = System.getenv("REACT_NATIVE_OVERRIDE_HERMES_DIR") ?: file("${REACT_NATIVE_DIR}/sdks/hermes")
|
|
89
|
+
|
|
92
90
|
def USE_HERMES = false
|
|
91
|
+
def NEED_DOWNLOAD_HERMES = false
|
|
93
92
|
def HERMES_HEADER_DIR = null
|
|
94
93
|
def HERMES_AAR = null
|
|
95
94
|
if (findProject(":app")) {
|
|
@@ -114,19 +113,14 @@ if (USE_HERMES) {
|
|
|
114
113
|
HERMES_HEADER_DIR = file("${thirdPartyNdkDir}/hermes/prefab/modules/libhermes/include")
|
|
115
114
|
HERMES_AAR = file("${REACT_NATIVE_DIR}/ReactAndroid/hermes-engine/build/outputs/aar/hermes-engine-debug.aar")
|
|
116
115
|
} else {
|
|
117
|
-
// The `hermes-engine` package doesn't contain the correct version of the Hermes.
|
|
118
|
-
// The AAR we need to import is located in the React Native package.
|
|
119
|
-
// However, the version from RN doesn't include header files.
|
|
120
|
-
// To get those, we must fall back to the `hermes-engine` package.
|
|
121
|
-
def hermesEngineDir = new File(["node", "--print", "require.resolve('hermes-engine/package.json')"].execute(null, rootDir).text.trim()).parent
|
|
122
|
-
|
|
123
116
|
def prebuiltAAR = fileTree(REACT_NATIVE_DIR).matching { include "**/hermes-engine/**/hermes-engine-*-debug.aar" }
|
|
124
117
|
if (prebuiltAAR.any()) {
|
|
125
118
|
HERMES_AAR = prebuiltAAR.singleFile
|
|
126
119
|
} else {
|
|
127
120
|
HERMES_AAR = file("${hermesEngineDir}/android/hermes-debug.aar")
|
|
128
121
|
}
|
|
129
|
-
HERMES_HEADER_DIR = file("${
|
|
122
|
+
HERMES_HEADER_DIR = file("${hermesDir}")
|
|
123
|
+
NEED_DOWNLOAD_HERMES = true
|
|
130
124
|
}
|
|
131
125
|
}
|
|
132
126
|
// END HERMES
|
|
@@ -160,6 +154,24 @@ afterEvaluate {
|
|
|
160
154
|
android {
|
|
161
155
|
compileSdkVersion safeExtGet("compileSdkVersion", 31)
|
|
162
156
|
|
|
157
|
+
if (REACT_NATIVE_BUILD_FROM_SOURCE) {
|
|
158
|
+
if (rootProject.hasProperty("ndkPath")) {
|
|
159
|
+
ndkPath rootProject.ext.ndkPath
|
|
160
|
+
}
|
|
161
|
+
if (rootProject.hasProperty("ndkVersion")) {
|
|
162
|
+
ndkVersion rootProject.ext.ndkVersion
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
// This ndkVersion should align to prebuilt react-native building ndkVersion.
|
|
166
|
+
// Because the unwind library is different before NDK r23 and after,
|
|
167
|
+
// if we build this library with newer NDK, C++ exceptions are incompatible between these libraries.
|
|
168
|
+
// For example, C++ exceptions throwing from hermes are not catchable from this library.
|
|
169
|
+
// Ref: https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#unwinding
|
|
170
|
+
//
|
|
171
|
+
// TODO: Revisit this version when upgrade react-native 0.71 (Expo SDK 48)
|
|
172
|
+
ndkVersion = "21.4.7075529"
|
|
173
|
+
}
|
|
174
|
+
|
|
163
175
|
compileOptions {
|
|
164
176
|
sourceCompatibility JavaVersion.VERSION_11
|
|
165
177
|
targetCompatibility JavaVersion.VERSION_11
|
|
@@ -174,7 +186,7 @@ android {
|
|
|
174
186
|
targetSdkVersion safeExtGet("targetSdkVersion", 31)
|
|
175
187
|
consumerProguardFiles 'proguard-rules.pro'
|
|
176
188
|
versionCode 1
|
|
177
|
-
versionName "0.
|
|
189
|
+
versionName "0.13.1"
|
|
178
190
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
|
|
179
191
|
|
|
180
192
|
testInstrumentationRunner "expo.modules.TestRunner"
|
|
@@ -237,15 +249,9 @@ android {
|
|
|
237
249
|
// In android (instrumental) tests, we want to package all so files to enable our JSI functionality.
|
|
238
250
|
// Otherwise, those files should be excluded, because will be loaded by the application.
|
|
239
251
|
if (isExpoModulesCoreTests) {
|
|
240
|
-
|
|
241
|
-
pickFirsts = sharedLibraries
|
|
252
|
+
pickFirsts += sharedLibraries
|
|
242
253
|
} else {
|
|
243
|
-
excludes
|
|
244
|
-
}
|
|
245
|
-
if (isExpoModulesCoreTests || isAndroidTest) {
|
|
246
|
-
excludes.add("META-INF/MANIFEST.MF")
|
|
247
|
-
excludes.add("META-INF/com.android.tools/proguard/coroutines.pro")
|
|
248
|
-
excludes.add("META-INF/proguard/coroutines.pro")
|
|
254
|
+
excludes += sharedLibraries
|
|
249
255
|
}
|
|
250
256
|
}
|
|
251
257
|
|
|
@@ -469,12 +475,36 @@ task prepareFolly(dependsOn: [downloadFolly], type: Copy) {
|
|
|
469
475
|
includeEmptyDirs = false
|
|
470
476
|
into("$thirdPartyNdkDir/folly")
|
|
471
477
|
}
|
|
472
|
-
// END
|
|
478
|
+
// END FOLLY
|
|
479
|
+
|
|
480
|
+
task downloadHermes(type: Download) {
|
|
481
|
+
def hermesVersion = currentHermesVersion ?: "main"
|
|
482
|
+
src("https://github.com/facebook/hermes/tarball/${hermesVersion}")
|
|
483
|
+
onlyIfNewer(true)
|
|
484
|
+
overwrite(false)
|
|
485
|
+
dest(new File(downloadsDir, "hermes-${hermesVersion}.tar.gz"))
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
task unzipHermes(dependsOn: downloadHermes, type: Copy) {
|
|
489
|
+
from(tarTree(downloadHermes.dest)) {
|
|
490
|
+
eachFile { file ->
|
|
491
|
+
// We flatten the unzip as the tarball contains a `facebook-hermes-<SHA>`
|
|
492
|
+
// folder at the top level.
|
|
493
|
+
if (file.relativePath.segments.size() > 1) {
|
|
494
|
+
file.relativePath = new org.gradle.api.file.RelativePath(!file.isDirectory(), file.relativePath.segments.drop(1))
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
into(hermesDir)
|
|
499
|
+
}
|
|
473
500
|
|
|
474
501
|
task prepareHermes(dependsOn: createNativeDepsDirectories) {
|
|
475
502
|
if (!USE_HERMES) {
|
|
476
503
|
return
|
|
477
504
|
}
|
|
505
|
+
if (NEED_DOWNLOAD_HERMES) {
|
|
506
|
+
dependsOn(unzipHermes)
|
|
507
|
+
}
|
|
478
508
|
|
|
479
509
|
doLast {
|
|
480
510
|
def files = zipTree(HERMES_AAR).matching({ it.include "**/*.so", "prefab/modules/libhermes/include/**/*" })
|
|
@@ -46,9 +46,27 @@ jni::local_ref<UnexpectedException> UnexpectedException::create(const std::strin
|
|
|
46
46
|
);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
jsi::Value makeCodedError(
|
|
50
|
+
jsi::Runtime &rt,
|
|
51
|
+
jsi::String code,
|
|
52
|
+
jsi::String message
|
|
53
|
+
) {
|
|
54
|
+
auto codedErrorConstructor = rt
|
|
55
|
+
.global()
|
|
56
|
+
.getProperty(rt, "ExpoModulesCore_CodedError")
|
|
57
|
+
.asObject(rt)
|
|
58
|
+
.asFunction(rt);
|
|
59
|
+
|
|
60
|
+
return codedErrorConstructor.callAsConstructor(
|
|
61
|
+
rt, {
|
|
62
|
+
jsi::Value(rt, code),
|
|
63
|
+
jsi::Value(rt, message)
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
49
68
|
void rethrowAsCodedError(
|
|
50
69
|
jsi::Runtime &rt,
|
|
51
|
-
JSIInteropModuleRegistry *registry,
|
|
52
70
|
jni::JniException &jniException
|
|
53
71
|
) {
|
|
54
72
|
jni::local_ref<jni::JThrowable> unboxedThrowable = jniException.getThrowable();
|
|
@@ -57,25 +75,40 @@ void rethrowAsCodedError(
|
|
|
57
75
|
auto code = codedException->getCode();
|
|
58
76
|
auto message = codedException->getLocalizedMessage();
|
|
59
77
|
|
|
60
|
-
auto
|
|
61
|
-
|
|
78
|
+
auto codedError = makeCodedError(
|
|
79
|
+
rt,
|
|
80
|
+
jsi::String::createFromUtf8(rt, code),
|
|
81
|
+
jsi::String::createFromUtf8(rt, message.value_or(""))
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
throw jsi::JSError(
|
|
85
|
+
message.value_or(""),
|
|
86
|
+
rt,
|
|
87
|
+
std::move(codedError)
|
|
62
88
|
);
|
|
63
|
-
if (codedErrorPointer != nullptr) {
|
|
64
|
-
auto &jsCodedError = *codedErrorPointer;
|
|
65
|
-
|
|
66
|
-
throw jsi::JSError(
|
|
67
|
-
message.value_or(""),
|
|
68
|
-
rt,
|
|
69
|
-
jsCodedError.callAsConstructor(
|
|
70
|
-
rt,
|
|
71
|
-
jsi::String::createFromUtf8(rt, code),
|
|
72
|
-
jsi::String::createFromUtf8(rt, message.value_or(""))
|
|
73
|
-
)
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
89
|
}
|
|
77
90
|
|
|
78
91
|
// Rethrow error if we can't wrap it.
|
|
79
92
|
throw;
|
|
80
93
|
}
|
|
94
|
+
|
|
95
|
+
void throwPendingJniExceptionAsCppException() {
|
|
96
|
+
JNIEnv* env = jni::Environment::current();
|
|
97
|
+
if (env->ExceptionCheck() == JNI_FALSE) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
auto throwable = env->ExceptionOccurred();
|
|
102
|
+
if (!throwable) {
|
|
103
|
+
throw std::runtime_error("Unable to get pending JNI exception.");
|
|
104
|
+
}
|
|
105
|
+
env->ExceptionClear();
|
|
106
|
+
|
|
107
|
+
throw jni::JniException(jni::adopt_local(throwable));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void throwNewJavaException(jthrowable throwable) {
|
|
111
|
+
throw jni::JniException(jni::wrap_alias(throwable));
|
|
112
|
+
}
|
|
113
|
+
|
|
81
114
|
} // namespace expo
|
|
@@ -65,7 +65,23 @@ public:
|
|
|
65
65
|
*/
|
|
66
66
|
[[noreturn]] void rethrowAsCodedError(
|
|
67
67
|
jsi::Runtime &rt,
|
|
68
|
-
JSIInteropModuleRegistry *registry,
|
|
69
68
|
jni::JniException &jniException
|
|
70
69
|
);
|
|
70
|
+
|
|
71
|
+
jsi::Value makeCodedError(
|
|
72
|
+
jsi::Runtime &runtime,
|
|
73
|
+
jsi::String code,
|
|
74
|
+
jsi::String message
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* fbjni@0.2.2 is built by ndk r21, its exceptions are not catchable by expo-modules-core built by ndk r23+.
|
|
79
|
+
* To catch these excetptions, we copy the `facebook::jni::throwPendingJniExceptionAsCppException` here and throw exceptions on our own.
|
|
80
|
+
*/
|
|
81
|
+
void throwPendingJniExceptionAsCppException();
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Same as `facebook::jni::throwNewJavaException` but throwing exceptions on our own.
|
|
85
|
+
*/
|
|
86
|
+
[[noreturn]] void throwNewJavaException(jthrowable throwable);
|
|
71
87
|
} // namespace expo
|
|
@@ -12,6 +12,14 @@ namespace expo {
|
|
|
12
12
|
ExpoModulesHostObject::ExpoModulesHostObject(JSIInteropModuleRegistry *installer)
|
|
13
13
|
: installer(installer) {}
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Clears jsi references held by JSRegistry and JavaScriptRuntime.
|
|
17
|
+
*/
|
|
18
|
+
ExpoModulesHostObject::~ExpoModulesHostObject() {
|
|
19
|
+
installer->jsRegistry.reset();
|
|
20
|
+
installer->runtimeHolder.reset();
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
jsi::Value ExpoModulesHostObject::get(jsi::Runtime &runtime, const jsi::PropNameID &name) {
|
|
16
24
|
auto cName = name.utf8(runtime);
|
|
17
25
|
auto module = installer->getModule(cName);
|
|
@@ -20,6 +20,8 @@ class ExpoModulesHostObject : public jsi::HostObject {
|
|
|
20
20
|
public:
|
|
21
21
|
ExpoModulesHostObject(JSIInteropModuleRegistry *installer);
|
|
22
22
|
|
|
23
|
+
~ExpoModulesHostObject() override;
|
|
24
|
+
|
|
23
25
|
jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) override;
|
|
24
26
|
|
|
25
27
|
void set(jsi::Runtime &, const jsi::PropNameID &name, const jsi::Value &value) override;
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// Copyright © 2021-present 650 Industries, Inc. (aka Expo)
|
|
2
2
|
|
|
3
3
|
#include "JNIFunctionBody.h"
|
|
4
|
+
#include "Exceptions.h"
|
|
4
5
|
#include "JavaReferencesCache.h"
|
|
5
6
|
|
|
6
7
|
namespace jni = facebook::jni;
|
|
7
8
|
namespace react = facebook::react;
|
|
8
9
|
|
|
9
10
|
namespace expo {
|
|
11
|
+
|
|
10
12
|
jni::local_ref<jni::JObject>
|
|
11
13
|
JNIFunctionBody::invoke(jobjectArray args) {
|
|
12
14
|
// Do NOT use getClass here!
|
|
@@ -20,7 +22,9 @@ JNIFunctionBody::invoke(jobjectArray args) {
|
|
|
20
22
|
"([Ljava/lang/Object;)Ljava/lang/Object;"
|
|
21
23
|
);
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
auto result = jni::Environment::current()->CallObjectMethod(this->self(), method.getId(), args);
|
|
26
|
+
throwPendingJniExceptionAsCppException();
|
|
27
|
+
return jni::adopt_local(static_cast<jni::JniType<jni::JObject>>(result));
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
void JNIAsyncFunctionBody::invoke(
|
|
@@ -40,6 +44,8 @@ void JNIAsyncFunctionBody::invoke(
|
|
|
40
44
|
"([Ljava/lang/Object;Lexpo/modules/kotlin/jni/PromiseImpl;)V"
|
|
41
45
|
);
|
|
42
46
|
|
|
43
|
-
|
|
47
|
+
jni::Environment::current()->CallVoidMethod(this->self(), method.getId(), args, promise);
|
|
48
|
+
throwPendingJniExceptionAsCppException();
|
|
44
49
|
}
|
|
50
|
+
|
|
45
51
|
} // namespace expo
|
|
@@ -8,16 +8,6 @@ JSReferencesCache::JSReferencesCache(jsi::Runtime &runtime) {
|
|
|
8
8
|
runtime.global().getPropertyAsFunction(runtime, "Promise")
|
|
9
9
|
)
|
|
10
10
|
);
|
|
11
|
-
|
|
12
|
-
if (runtime.global().hasProperty(runtime, "ExpoModulesCore_CodedError")) {
|
|
13
|
-
auto jsCodedError = runtime.global()
|
|
14
|
-
.getPropertyAsFunction(runtime, "ExpoModulesCore_CodedError");
|
|
15
|
-
|
|
16
|
-
jsObjectRegistry.emplace(
|
|
17
|
-
JSKeys::CODED_ERROR,
|
|
18
|
-
std::make_unique<jsi::Object>(std::move(jsCodedError))
|
|
19
|
-
);
|
|
20
|
-
}
|
|
21
11
|
}
|
|
22
12
|
|
|
23
13
|
jsi::PropNameID &JSReferencesCache::getPropNameID(
|
|
@@ -72,6 +72,7 @@ void JavaScriptModuleObject::registerSyncFunction(
|
|
|
72
72
|
|
|
73
73
|
methodsMetadata.try_emplace(
|
|
74
74
|
cName,
|
|
75
|
+
longLivedObjectCollection_,
|
|
75
76
|
cName,
|
|
76
77
|
args,
|
|
77
78
|
false,
|
|
@@ -90,6 +91,7 @@ void JavaScriptModuleObject::registerAsyncFunction(
|
|
|
90
91
|
|
|
91
92
|
methodsMetadata.try_emplace(
|
|
92
93
|
cName,
|
|
94
|
+
longLivedObjectCollection_,
|
|
93
95
|
cName,
|
|
94
96
|
args,
|
|
95
97
|
true,
|
|
@@ -107,6 +109,7 @@ void JavaScriptModuleObject::registerProperty(
|
|
|
107
109
|
auto cName = name->toStdString();
|
|
108
110
|
|
|
109
111
|
auto getterMetadata = MethodMetadata(
|
|
112
|
+
longLivedObjectCollection_,
|
|
110
113
|
cName,
|
|
111
114
|
0,
|
|
112
115
|
false,
|
|
@@ -117,6 +120,7 @@ void JavaScriptModuleObject::registerProperty(
|
|
|
117
120
|
auto types = std::vector<std::unique_ptr<AnyType>>();
|
|
118
121
|
types.push_back(std::make_unique<AnyType>(jni::make_local(expectedArgType)));
|
|
119
122
|
auto setterMetadata = MethodMetadata(
|
|
123
|
+
longLivedObjectCollection_,
|
|
120
124
|
cName,
|
|
121
125
|
1,
|
|
122
126
|
false,
|
|
@@ -135,6 +139,19 @@ void JavaScriptModuleObject::registerProperty(
|
|
|
135
139
|
JavaScriptModuleObject::HostObject::HostObject(
|
|
136
140
|
JavaScriptModuleObject *jsModule) : jsModule(jsModule) {}
|
|
137
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Clears all the JSI references held by the `JavaScriptModuleObject`.
|
|
144
|
+
*/
|
|
145
|
+
JavaScriptModuleObject::HostObject::~HostObject() {
|
|
146
|
+
if (jsModule->jsiObject != nullptr) {
|
|
147
|
+
jsModule->jsiObject.reset();
|
|
148
|
+
}
|
|
149
|
+
jsModule->methodsMetadata.clear();
|
|
150
|
+
jsModule->constants.clear();
|
|
151
|
+
jsModule->properties.clear();
|
|
152
|
+
jsModule->longLivedObjectCollection_->clear();
|
|
153
|
+
}
|
|
154
|
+
|
|
138
155
|
jsi::Value JavaScriptModuleObject::HostObject::get(jsi::Runtime &runtime,
|
|
139
156
|
const jsi::PropNameID &name) {
|
|
140
157
|
auto cName = name.utf8(runtime);
|
|
@@ -214,4 +231,10 @@ std::vector<jsi::PropNameID> JavaScriptModuleObject::HostObject::getPropertyName
|
|
|
214
231
|
|
|
215
232
|
return result;
|
|
216
233
|
}
|
|
234
|
+
|
|
235
|
+
JavaScriptModuleObject::JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis)
|
|
236
|
+
: javaPart_(jni::make_global(jThis)) {
|
|
237
|
+
longLivedObjectCollection_ = std::make_shared<react::LongLivedObjectCollection>();
|
|
238
|
+
}
|
|
239
|
+
|
|
217
240
|
} // namespace expo
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
#include <fbjni/fbjni.h>
|
|
6
6
|
#include <jsi/jsi.h>
|
|
7
|
+
#include <react/bridging/LongLivedObject.h>
|
|
7
8
|
#include <react/jni/ReadableNativeArray.h>
|
|
8
9
|
#include <jni/JCallback.h>
|
|
9
10
|
|
|
@@ -104,6 +105,8 @@ public:
|
|
|
104
105
|
public:
|
|
105
106
|
HostObject(JavaScriptModuleObject *);
|
|
106
107
|
|
|
108
|
+
~HostObject() override;
|
|
109
|
+
|
|
107
110
|
jsi::Value get(jsi::Runtime &, const jsi::PropNameID &name) override;
|
|
108
111
|
|
|
109
112
|
void set(jsi::Runtime &, const jsi::PropNameID &name, const jsi::Value &value) override;
|
|
@@ -114,6 +117,9 @@ public:
|
|
|
114
117
|
JavaScriptModuleObject *jsModule;
|
|
115
118
|
};
|
|
116
119
|
|
|
120
|
+
private:
|
|
121
|
+
explicit JavaScriptModuleObject(jni::alias_ref<jhybridobject> jThis);
|
|
122
|
+
|
|
117
123
|
private:
|
|
118
124
|
friend HybridBase;
|
|
119
125
|
/**
|
|
@@ -139,7 +145,10 @@ private:
|
|
|
139
145
|
*/
|
|
140
146
|
std::map<std::string, std::pair<MethodMetadata, MethodMetadata>> properties;
|
|
141
147
|
|
|
142
|
-
|
|
143
|
-
|
|
148
|
+
/**
|
|
149
|
+
* The `LongLivedObjectCollection` to hold `LongLivedObject` (callbacks or promises) for this module.
|
|
150
|
+
*/
|
|
151
|
+
std::shared_ptr<react::LongLivedObjectCollection> longLivedObjectCollection_;
|
|
152
|
+
|
|
144
153
|
};
|
|
145
154
|
} // namespace expo
|