expo-modules-core 0.11.0 → 0.11.3
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 +18 -0
- package/android/build.gradle +2 -2
- package/android/src/main/cpp/CachedReferencesRegistry.cpp +2 -0
- package/android/src/main/cpp/JNIFunctionBody.cpp +9 -8
- package/android/src/main/cpp/JNIFunctionBody.h +2 -2
- package/android/src/main/cpp/JavaScriptRuntime.cpp +3 -5
- package/android/src/main/cpp/MethodMetadata.cpp +61 -30
- package/android/src/main/cpp/MethodMetadata.h +3 -2
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +15 -7
- package/ios/JSI/EXJSIInstaller.mm +2 -0
- package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +5 -4
- package/ios/Swift/AppContext.swift +2 -4
- package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +2 -2
- package/ios/Swift/ExpoBridgeModule.swift +16 -2
- package/ios/Swift/Logging/LogType.swift +1 -1
- package/ios/Swift/Logging/Logger.swift +6 -3
- package/ios/Swift/Promise.swift +5 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,24 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 0.11.3 — 2022-07-18
|
|
14
|
+
|
|
15
|
+
### 💡 Others
|
|
16
|
+
|
|
17
|
+
- Changed access levels in the Logger and fixed the timer to log milliseconds instead of seconds. ([#18271](https://github.com/expo/expo/pull/18271) by [@douglowder](https://github.com/douglowder))
|
|
18
|
+
|
|
19
|
+
## 0.11.2 — 2022-07-16
|
|
20
|
+
|
|
21
|
+
### 🐛 Bug fixes
|
|
22
|
+
|
|
23
|
+
- Fix dangling pointer in the fbjni from the MethodMetadata::createPromiseBody on Android. ([#18206](https://github.com/expo/expo/pull/18206) by [@lukmccall](https://github.com/lukmccall))
|
|
24
|
+
|
|
25
|
+
## 0.11.1 — 2022-07-11
|
|
26
|
+
|
|
27
|
+
### 🐛 Bug fixes
|
|
28
|
+
|
|
29
|
+
- Fixed a crash when remote debugging is enabled on Android. ([#18165](https://github.com/expo/expo/pull/18165) by [@kudo](https://github.com/kudo))
|
|
30
|
+
|
|
13
31
|
## 0.11.0 — 2022-07-07
|
|
14
32
|
|
|
15
33
|
### 🎉 New features
|
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.11.
|
|
9
|
+
version = '0.11.3'
|
|
10
10
|
|
|
11
11
|
buildscript {
|
|
12
12
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -144,7 +144,7 @@ android {
|
|
|
144
144
|
targetSdkVersion safeExtGet("targetSdkVersion", 31)
|
|
145
145
|
consumerProguardFiles 'proguard-rules.pro'
|
|
146
146
|
versionCode 1
|
|
147
|
-
versionName "0.11.
|
|
147
|
+
versionName "0.11.3"
|
|
148
148
|
|
|
149
149
|
testInstrumentationRunner "expo.modules.TestRunner"
|
|
150
150
|
|
|
@@ -22,6 +22,8 @@ void CachedReferencesRegistry::loadJClasses(JNIEnv *env) {
|
|
|
22
22
|
loadJClass(env, "com/facebook/react/bridge/PromiseImpl", {
|
|
23
23
|
{"<init>", "(Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V"}
|
|
24
24
|
});
|
|
25
|
+
|
|
26
|
+
loadJClass(env, "java/lang/Object", {});
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
void CachedReferencesRegistry::loadJClass(
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
// Copyright © 2021-present 650 Industries, Inc. (aka Expo)
|
|
2
2
|
|
|
3
3
|
#include "JNIFunctionBody.h"
|
|
4
|
+
#include "CachedReferencesRegistry.h"
|
|
4
5
|
|
|
5
6
|
namespace jni = facebook::jni;
|
|
6
7
|
namespace react = facebook::react;
|
|
7
8
|
|
|
8
9
|
namespace expo {
|
|
9
10
|
jni::local_ref<react::ReadableNativeArray::javaobject>
|
|
10
|
-
JNIFunctionBody::invoke(
|
|
11
|
+
JNIFunctionBody::invoke(jobjectArray args) {
|
|
11
12
|
// Do NOT use getClass here!
|
|
12
13
|
// Method obtained from `getClass` will point to the overridden version of the method.
|
|
13
14
|
// Because of that, it can't be cached - we will try to invoke the nonexistent method
|
|
14
15
|
// if we receive an object of a different class than the one used to obtain the method id.
|
|
15
16
|
// The only cacheable method id can be obtain from the base class.
|
|
16
17
|
static const auto method = jni::findClassLocal("expo/modules/kotlin/jni/JNIFunctionBody")
|
|
17
|
-
->getMethod<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"invoke"
|
|
18
|
+
->getMethod<jni::local_ref<react::ReadableNativeArray::javaobject>(jobjectArray)>(
|
|
19
|
+
"invoke",
|
|
20
|
+
"([Ljava/lang/Object;)Lcom/facebook/react/bridge/ReadableNativeArray;"
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
return method(this->self(), args);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
void JNIAsyncFunctionBody::invoke(
|
|
27
|
-
|
|
27
|
+
jobjectArray args,
|
|
28
28
|
jobject promise
|
|
29
29
|
) {
|
|
30
30
|
// Do NOT use getClass here!
|
|
@@ -34,9 +34,10 @@ void JNIAsyncFunctionBody::invoke(
|
|
|
34
34
|
// The only cacheable method id can be obtain from the base class.
|
|
35
35
|
static const auto method = jni::findClassLocal("expo/modules/kotlin/jni/JNIAsyncFunctionBody")
|
|
36
36
|
->getMethod<
|
|
37
|
-
void(
|
|
37
|
+
void(jobjectArray , jobject)
|
|
38
38
|
>(
|
|
39
|
-
"invoke"
|
|
39
|
+
"invoke",
|
|
40
|
+
"([Ljava/lang/Object;Ljava/lang/Object;)V"
|
|
40
41
|
);
|
|
41
42
|
|
|
42
43
|
method(this->self(), args, promise);
|
|
@@ -24,7 +24,7 @@ public:
|
|
|
24
24
|
* @return result of the Kotlin function
|
|
25
25
|
*/
|
|
26
26
|
jni::local_ref<react::ReadableNativeArray::javaobject> invoke(
|
|
27
|
-
|
|
27
|
+
jobjectArray args
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
30
|
|
|
@@ -43,7 +43,7 @@ public:
|
|
|
43
43
|
* @param promise that will be resolve or rejected in the Kotlin's implementation
|
|
44
44
|
*/
|
|
45
45
|
void invoke(
|
|
46
|
-
|
|
46
|
+
jobjectArray args,
|
|
47
47
|
jobject promise
|
|
48
48
|
);
|
|
49
49
|
};
|
|
@@ -87,10 +87,10 @@ jsi::Runtime *JavaScriptRuntime::get() {
|
|
|
87
87
|
jni::local_ref<JavaScriptValue::javaobject>
|
|
88
88
|
JavaScriptRuntime::evaluateScript(const std::string &script) {
|
|
89
89
|
auto scriptBuffer = std::make_shared<jsi::StringBuffer>(script);
|
|
90
|
-
std::shared_ptr<jsi::Value> result;
|
|
91
90
|
try {
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
return JavaScriptValue::newObjectCxxArgs(
|
|
92
|
+
weak_from_this(),
|
|
93
|
+
std::make_shared<jsi::Value>(runtime->evaluateJavaScript(scriptBuffer, "<<evaluated>>"))
|
|
94
94
|
);
|
|
95
95
|
} catch (const jsi::JSError &error) {
|
|
96
96
|
jni::throwNewJavaException(
|
|
@@ -107,8 +107,6 @@ JavaScriptRuntime::evaluateScript(const std::string &script) {
|
|
|
107
107
|
).get()
|
|
108
108
|
);
|
|
109
109
|
}
|
|
110
|
-
|
|
111
|
-
return JavaScriptValue::newObjectCxxArgs(weak_from_this(), result);
|
|
112
110
|
}
|
|
113
111
|
|
|
114
112
|
jni::local_ref<JavaScriptObject::javaobject> JavaScriptRuntime::global() {
|
|
@@ -80,49 +80,65 @@ std::vector<jvalue> MethodMetadata::convertJSIArgsToJNI(
|
|
|
80
80
|
JNIEnv *env,
|
|
81
81
|
jsi::Runtime &rt,
|
|
82
82
|
const jsi::Value *args,
|
|
83
|
-
size_t count
|
|
83
|
+
size_t count,
|
|
84
|
+
bool returnGlobalReferences
|
|
84
85
|
) {
|
|
85
86
|
std::vector<jvalue> result(count);
|
|
86
87
|
|
|
88
|
+
auto makeGlobalIfNecessary = [env, returnGlobalReferences](jobject obj) -> jobject {
|
|
89
|
+
if (returnGlobalReferences) {
|
|
90
|
+
return env->NewGlobalRef(obj);
|
|
91
|
+
}
|
|
92
|
+
return obj;
|
|
93
|
+
};
|
|
94
|
+
|
|
87
95
|
for (unsigned int argIndex = 0; argIndex < count; argIndex++) {
|
|
88
96
|
const jsi::Value *arg = &args[argIndex];
|
|
89
97
|
jvalue *jarg = &result[argIndex];
|
|
90
98
|
int desiredType = desiredTypes[argIndex];
|
|
91
99
|
|
|
92
100
|
if (desiredType & CppType::JS_VALUE) {
|
|
93
|
-
jarg->l =
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
101
|
+
jarg->l = makeGlobalIfNecessary(
|
|
102
|
+
JavaScriptValue::newObjectCxxArgs(
|
|
103
|
+
moduleRegistry->runtimeHolder->weak_from_this(),
|
|
104
|
+
// TODO(@lukmccall): make sure that copy here is necessary
|
|
105
|
+
std::make_shared<jsi::Value>(jsi::Value(rt, *arg))
|
|
106
|
+
).release()
|
|
107
|
+
);
|
|
98
108
|
} else if (desiredType & CppType::JS_OBJECT) {
|
|
99
|
-
jarg->l =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
109
|
+
jarg->l = makeGlobalIfNecessary(
|
|
110
|
+
JavaScriptObject::newObjectCxxArgs(
|
|
111
|
+
moduleRegistry->runtimeHolder->weak_from_this(),
|
|
112
|
+
std::make_shared<jsi::Object>(arg->getObject(rt))
|
|
113
|
+
).release()
|
|
114
|
+
);
|
|
103
115
|
} else if (arg->isNull() || arg->isUndefined()) {
|
|
104
116
|
jarg->l = nullptr;
|
|
105
117
|
} else if (arg->isNumber()) {
|
|
106
118
|
auto &doubleClass = CachedReferencesRegistry::instance()
|
|
107
119
|
->getJClass("java/lang/Double");
|
|
108
120
|
jmethodID doubleConstructor = doubleClass.getMethod("<init>", "(D)V");
|
|
109
|
-
jarg->l =
|
|
121
|
+
jarg->l = makeGlobalIfNecessary(
|
|
122
|
+
env->NewObject(doubleClass.clazz, doubleConstructor, arg->getNumber()));
|
|
110
123
|
} else if (arg->isBool()) {
|
|
111
124
|
auto &booleanClass = CachedReferencesRegistry::instance()
|
|
112
125
|
->getJClass("java/lang/Boolean");
|
|
113
126
|
jmethodID booleanConstructor = booleanClass.getMethod("<init>", "(Z)V");
|
|
114
|
-
jarg->l =
|
|
127
|
+
jarg->l = makeGlobalIfNecessary(
|
|
128
|
+
env->NewObject(booleanClass.clazz, booleanConstructor, arg->getBool()));
|
|
115
129
|
} else if (arg->isString()) {
|
|
116
|
-
jarg->l = env->NewStringUTF(arg->getString(rt).utf8(rt).c_str());
|
|
130
|
+
jarg->l = makeGlobalIfNecessary(env->NewStringUTF(arg->getString(rt).utf8(rt).c_str()));
|
|
117
131
|
} else if (arg->isObject()) {
|
|
118
132
|
const jsi::Object object = arg->getObject(rt);
|
|
119
133
|
|
|
120
134
|
// TODO(@lukmccall): stop using dynamic
|
|
121
135
|
auto dynamic = jsi::dynamicFromValue(rt, *arg);
|
|
122
136
|
if (arg->getObject(rt).isArray(rt)) {
|
|
123
|
-
jarg->l =
|
|
137
|
+
jarg->l = makeGlobalIfNecessary(
|
|
138
|
+
react::ReadableNativeArray::newObjectCxxArgs(std::move(dynamic)).release());
|
|
124
139
|
} else {
|
|
125
|
-
jarg->l =
|
|
140
|
+
jarg->l = makeGlobalIfNecessary(
|
|
141
|
+
react::ReadableNativeMap::createWithContents(std::move(dynamic)).release());
|
|
126
142
|
}
|
|
127
143
|
} else {
|
|
128
144
|
// TODO(@lukmccall): throw an exception
|
|
@@ -202,18 +218,23 @@ jsi::Value MethodMetadata::callSync(
|
|
|
202
218
|
*/
|
|
203
219
|
jni::JniLocalScope scope(env, (int) count);
|
|
204
220
|
|
|
205
|
-
std::vector<jvalue> convertedArgs = convertJSIArgsToJNI(moduleRegistry, env, rt, args, count
|
|
221
|
+
std::vector<jvalue> convertedArgs = convertJSIArgsToJNI(moduleRegistry, env, rt, args, count,
|
|
222
|
+
false);
|
|
206
223
|
|
|
207
224
|
// TODO(@lukmccall): Remove this temp array
|
|
208
|
-
auto tempArray =
|
|
225
|
+
auto tempArray = env->NewObjectArray(
|
|
226
|
+
convertedArgs.size(),
|
|
227
|
+
CachedReferencesRegistry::instance()->getJClass("java/lang/Object").clazz,
|
|
228
|
+
nullptr
|
|
229
|
+
);
|
|
209
230
|
for (size_t i = 0; i < convertedArgs.size(); i++) {
|
|
210
|
-
|
|
231
|
+
env->SetObjectArrayElement(tempArray, i, convertedArgs[i].l);
|
|
211
232
|
}
|
|
212
233
|
|
|
213
234
|
// Cast in this place is safe, cause we know that this function is promise-less.
|
|
214
235
|
auto syncFunction = jni::static_ref_cast<JNIFunctionBody>(this->jBodyReference);
|
|
215
236
|
auto result = syncFunction->invoke(
|
|
216
|
-
|
|
237
|
+
tempArray
|
|
217
238
|
);
|
|
218
239
|
|
|
219
240
|
if (result == nullptr) {
|
|
@@ -248,20 +269,14 @@ jsi::Function MethodMetadata::toAsyncFunction(
|
|
|
248
269
|
* all LocalReferences are deleted.
|
|
249
270
|
*/
|
|
250
271
|
jni::JniLocalScope scope(env, (int) count);
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
// TODO(@lukmccall): Remove this temp array
|
|
255
|
-
auto tempArray = jni::JArrayClass<jobject>::newArray(count);
|
|
256
|
-
for (size_t i = 0; i < convertedArgs.size(); i++) {
|
|
257
|
-
tempArray->setElement(i, convertedArgs[i].l);
|
|
258
|
-
}
|
|
272
|
+
std::vector<jvalue> convertedArgs = convertJSIArgsToJNI(moduleRegistry, env, rt, args, count,
|
|
273
|
+
true);
|
|
259
274
|
|
|
260
275
|
auto Promise = rt.global().getPropertyAsFunction(rt, "Promise");
|
|
261
276
|
// Creates a JSI promise
|
|
262
277
|
jsi::Value promise = Promise.callAsConstructor(
|
|
263
278
|
rt,
|
|
264
|
-
createPromiseBody(rt, moduleRegistry, std::move(
|
|
279
|
+
createPromiseBody(rt, moduleRegistry, std::move(convertedArgs))
|
|
265
280
|
);
|
|
266
281
|
return promise;
|
|
267
282
|
}
|
|
@@ -271,7 +286,7 @@ jsi::Function MethodMetadata::toAsyncFunction(
|
|
|
271
286
|
jsi::Function MethodMetadata::createPromiseBody(
|
|
272
287
|
jsi::Runtime &runtime,
|
|
273
288
|
JSIInteropModuleRegistry *moduleRegistry,
|
|
274
|
-
|
|
289
|
+
std::vector<jvalue> &&args
|
|
275
290
|
) {
|
|
276
291
|
return jsi::Function::createFromHostFunction(
|
|
277
292
|
runtime,
|
|
@@ -320,10 +335,21 @@ jsi::Function MethodMetadata::createPromiseBody(
|
|
|
320
335
|
reject
|
|
321
336
|
);
|
|
322
337
|
|
|
338
|
+
auto argsSize = args.size();
|
|
339
|
+
// TODO(@lukmccall): Remove this temp array
|
|
340
|
+
auto tempArray = env->NewObjectArray(
|
|
341
|
+
argsSize,
|
|
342
|
+
CachedReferencesRegistry::instance()->getJClass("java/lang/Object").clazz,
|
|
343
|
+
nullptr
|
|
344
|
+
);
|
|
345
|
+
for (size_t i = 0; i < argsSize; i++) {
|
|
346
|
+
env->SetObjectArrayElement(tempArray, i, args[i].l);
|
|
347
|
+
}
|
|
348
|
+
|
|
323
349
|
// Cast in this place is safe, cause we know that this function expects promise.
|
|
324
350
|
auto asyncFunction = jni::static_ref_cast<JNIAsyncFunctionBody>(this->jBodyReference);
|
|
325
351
|
asyncFunction->invoke(
|
|
326
|
-
|
|
352
|
+
tempArray,
|
|
327
353
|
promise
|
|
328
354
|
);
|
|
329
355
|
|
|
@@ -332,6 +358,11 @@ jsi::Function MethodMetadata::createPromiseBody(
|
|
|
332
358
|
// the ownership to the `JNIAsyncFunctionBody`.
|
|
333
359
|
env->DeleteLocalRef(promise);
|
|
334
360
|
|
|
361
|
+
for (const auto &arg: args) {
|
|
362
|
+
env->DeleteGlobalRef(arg.l);
|
|
363
|
+
}
|
|
364
|
+
env->DeleteLocalRef(tempArray);
|
|
365
|
+
|
|
335
366
|
return jsi::Value::undefined();
|
|
336
367
|
}
|
|
337
368
|
);
|
|
@@ -117,7 +117,7 @@ private:
|
|
|
117
117
|
jsi::Function createPromiseBody(
|
|
118
118
|
jsi::Runtime &runtime,
|
|
119
119
|
JSIInteropModuleRegistry *moduleRegistry,
|
|
120
|
-
|
|
120
|
+
std::vector<jvalue> &&args
|
|
121
121
|
);
|
|
122
122
|
|
|
123
123
|
std::vector<jvalue> convertJSIArgsToJNI(
|
|
@@ -125,7 +125,8 @@ private:
|
|
|
125
125
|
JNIEnv *env,
|
|
126
126
|
jsi::Runtime &rt,
|
|
127
127
|
const jsi::Value *args,
|
|
128
|
-
size_t count
|
|
128
|
+
size_t count,
|
|
129
|
+
bool returnGlobalReferences
|
|
129
130
|
);
|
|
130
131
|
};
|
|
131
132
|
} // namespace expo
|
|
@@ -89,13 +89,15 @@ class AppContext(
|
|
|
89
89
|
fun installJSIInterop() {
|
|
90
90
|
jsiInterop = JSIInteropModuleRegistry(this)
|
|
91
91
|
val reactContext = reactContextHolder.get() ?: return
|
|
92
|
-
reactContext.javaScriptContextHolder?.get()
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
92
|
+
reactContext.javaScriptContextHolder?.get()
|
|
93
|
+
?.takeIf { it != 0L }
|
|
94
|
+
?.let {
|
|
95
|
+
jsiInterop.installJSI(
|
|
96
|
+
it,
|
|
97
|
+
reactContext.catalystInstance.jsCallInvokerHolder as CallInvokerHolderImpl,
|
|
98
|
+
reactContext.catalystInstance.nativeCallInvokerHolder as CallInvokerHolderImpl
|
|
99
|
+
)
|
|
100
|
+
}
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
/**
|
|
@@ -266,6 +268,12 @@ class AppContext(
|
|
|
266
268
|
|
|
267
269
|
// region AppContextActivityResultCaller
|
|
268
270
|
|
|
271
|
+
/**
|
|
272
|
+
* For the time being [fallbackCallback] is not working.
|
|
273
|
+
* There are some problems with saving and restoring the state of [activityResultsManager]
|
|
274
|
+
* connected with [Activity]'s lifecycle and [AppContext] lifespan. So far, we've failed with identifying
|
|
275
|
+
* what parts of the application outlives the Activity destruction (especially [AppContext] and other [Bridge]-related parts).
|
|
276
|
+
*/
|
|
269
277
|
@MainThread
|
|
270
278
|
override suspend fun <I : Serializable, O> registerForActivityResult(
|
|
271
279
|
contract: AppContextActivityResultContract<I, O>,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright 2018-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
3
|
#import <ExpoModulesCore/EXJSIInstaller.h>
|
|
4
|
+
#import <ExpoModulesCore/EXJavaScriptRuntime.h>
|
|
4
5
|
#import <ExpoModulesCore/ExpoModulesHostObject.h>
|
|
5
6
|
#import <ExpoModulesCore/Swift.h>
|
|
6
7
|
|
|
@@ -14,6 +15,7 @@ static NSString *expoModulesHostObjectPropertyName = @"ExpoModules";
|
|
|
14
15
|
@interface RCTBridge (ExpoBridgeWithRuntime)
|
|
15
16
|
|
|
16
17
|
- (void *)runtime;
|
|
18
|
+
- (std::shared_ptr<facebook::react::CallInvoker>)jsCallInvoker;
|
|
17
19
|
|
|
18
20
|
@end
|
|
19
21
|
|
|
@@ -201,9 +201,10 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
|
|
|
201
201
|
|
|
202
202
|
- (void)setBridge:(RCTBridge *)bridge
|
|
203
203
|
{
|
|
204
|
-
|
|
205
|
-
[
|
|
206
|
-
|
|
204
|
+
ExpoBridgeModule* expoBridgeModule = [bridge moduleForClass:ExpoBridgeModule.class];
|
|
205
|
+
[expoBridgeModule legacyProxyDidSetBridgeWithLegacyModulesProxy:self
|
|
206
|
+
legacyModuleRegistry:_exModuleRegistry];
|
|
207
|
+
_appContext = [expoBridgeModule appContext];
|
|
207
208
|
|
|
208
209
|
if (!_bridge) {
|
|
209
210
|
// The `setBridge` can be called during module setup or after. Registering more modules
|
|
@@ -389,7 +390,7 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
|
|
|
389
390
|
{
|
|
390
391
|
// Hacky way to get a dictionary with `RCTComponentData` from UIManager.
|
|
391
392
|
NSMutableDictionary<NSString *, RCTComponentData *> *componentDataByName = [bridge.uiManager valueForKey:@"_componentDataByName"];
|
|
392
|
-
NSString *className = NSStringFromClass(moduleClass);
|
|
393
|
+
NSString *className = [moduleClass moduleName] ?: NSStringFromClass(moduleClass);
|
|
393
394
|
|
|
394
395
|
if ([moduleClass isSubclassOfClass:[RCTViewManager class]] && !componentDataByName[className]) {
|
|
395
396
|
RCTComponentData *componentData = [[RCTComponentData alloc] initWithManagerClass:moduleClass bridge:bridge eventDispatcher:bridge.eventDispatcher];
|
|
@@ -28,11 +28,9 @@ public final class AppContext: NSObject {
|
|
|
28
28
|
/**
|
|
29
29
|
The legacy module registry with modules written in the old-fashioned way.
|
|
30
30
|
*/
|
|
31
|
-
|
|
32
|
-
public weak var legacyModuleRegistry: EXModuleRegistry?
|
|
31
|
+
internal weak var legacyModuleRegistry: EXModuleRegistry?
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
public weak var legacyModulesProxy: LegacyNativeModulesProxy?
|
|
33
|
+
internal weak var legacyModulesProxy: LegacyNativeModulesProxy?
|
|
36
34
|
|
|
37
35
|
/**
|
|
38
36
|
React bridge of the context's app. Can be `nil` when the bridge
|
|
@@ -12,7 +12,7 @@ public struct ClassComponentElementsBuilder<OwnerType> {
|
|
|
12
12
|
/**
|
|
13
13
|
Default implementation without any constraints that just returns type-erased element.
|
|
14
14
|
*/
|
|
15
|
-
static func buildExpression<ElementType: ClassComponentElement>(
|
|
15
|
+
public static func buildExpression<ElementType: ClassComponentElement>(
|
|
16
16
|
_ element: ElementType
|
|
17
17
|
) -> AnyClassComponentElement {
|
|
18
18
|
return element
|
|
@@ -23,7 +23,7 @@ public struct ClassComponentElementsBuilder<OwnerType> {
|
|
|
23
23
|
we need to instruct the function to pass `this` to the closure
|
|
24
24
|
as the first argument and deduct it from `argumentsCount`.
|
|
25
25
|
*/
|
|
26
|
-
static func buildExpression<ElementType: ClassComponentElement>(
|
|
26
|
+
public static func buildExpression<ElementType: ClassComponentElement>(
|
|
27
27
|
_ element: ElementType
|
|
28
28
|
) -> AnyClassComponentElement where ElementType.OwnerType == OwnerType {
|
|
29
29
|
if var function = element as? AnyFunction {
|
|
@@ -20,8 +20,7 @@ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
|
|
|
20
20
|
architecture of Expo modules and the app itself.
|
|
21
21
|
*/
|
|
22
22
|
override init() {
|
|
23
|
-
appContext = AppContext()
|
|
24
|
-
appContext.moduleRegistry.register(moduleType: NativeModulesProxyModule.self)
|
|
23
|
+
appContext = AppContext()
|
|
25
24
|
super.init()
|
|
26
25
|
|
|
27
26
|
// Listen to React Native notifications posted just before the JS is executed.
|
|
@@ -50,6 +49,21 @@ public final class ExpoBridgeModule: NSObject, RCTBridgeModule {
|
|
|
50
49
|
appContext.reactBridge = bridge
|
|
51
50
|
}
|
|
52
51
|
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
This should be called inside EXNativeModulesProxy.setBridge()
|
|
55
|
+
*/
|
|
56
|
+
@objc
|
|
57
|
+
public func legacyProxyDidSetBridge(legacyModulesProxy: LegacyNativeModulesProxy,
|
|
58
|
+
legacyModuleRegistry: EXModuleRegistry) {
|
|
59
|
+
appContext.legacyModuleRegistry = legacyModuleRegistry
|
|
60
|
+
appContext.legacyModulesProxy = legacyModulesProxy
|
|
61
|
+
|
|
62
|
+
// we need to register all the modules after the legacy module registry is set
|
|
63
|
+
// otherwise legacy modules (e.g. permissions) won't be available in OnCreate { }
|
|
64
|
+
appContext.useModulesProvider("ExpoModulesProvider")
|
|
65
|
+
appContext.moduleRegistry.register(moduleType: NativeModulesProxyModule.self)
|
|
66
|
+
}
|
|
53
67
|
|
|
54
68
|
// MARK: - Notifications
|
|
55
69
|
|
|
@@ -45,7 +45,7 @@ public enum LogType: Int {
|
|
|
45
45
|
Maps the log types to the log types used by the `os.log` logger.
|
|
46
46
|
*/
|
|
47
47
|
@available(macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0, *)
|
|
48
|
-
func toOSLogType() -> OSLogType {
|
|
48
|
+
public func toOSLogType() -> OSLogType {
|
|
49
49
|
switch self {
|
|
50
50
|
case .trace, .timer, .stacktrace, .debug:
|
|
51
51
|
return .debug
|
|
@@ -139,7 +139,7 @@ public class Logger {
|
|
|
139
139
|
}
|
|
140
140
|
let endTime = DispatchTime.now()
|
|
141
141
|
let diff = Double(endTime.uptimeNanoseconds - startTime.uptimeNanoseconds) / 1_000_000
|
|
142
|
-
log(type: .timer, "Timer '\(id)' has finished in: \(diff)
|
|
142
|
+
log(type: .timer, "Timer '\(id)' has finished in: \(diff) ms")
|
|
143
143
|
timers.removeValue(forKey: id)
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -183,11 +183,14 @@ public class Logger {
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
private func reformatStackSymbol(_ symbol: String) -> String {
|
|
187
187
|
return symbol.replacingOccurrences(of: #"^\d+\s+"#, with: "", options: .regularExpression)
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
private func describe(value: Any) -> String {
|
|
191
|
+
if let value = value as? String {
|
|
192
|
+
return value
|
|
193
|
+
}
|
|
191
194
|
if let value = value as? CustomDebugStringConvertible {
|
|
192
195
|
return value.debugDescription
|
|
193
196
|
}
|
package/ios/Swift/Promise.swift
CHANGED
|
@@ -22,7 +22,11 @@ public struct Promise: AnyArgument {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
public func reject(_ error: Error) {
|
|
25
|
-
|
|
25
|
+
if let exception = error as? Exception {
|
|
26
|
+
rejecter(exception)
|
|
27
|
+
} else {
|
|
28
|
+
rejecter(UnexpectedException(error))
|
|
29
|
+
}
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
public func reject(_ error: Exception) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"@testing-library/react-hooks": "^7.0.1",
|
|
43
43
|
"expo-module-scripts": "^2.0.0"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "5d900179d047d9f4d89c0b9953b7121a1f1df8a2"
|
|
46
46
|
}
|