expo-modules-core 1.3.2 → 1.5.0
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 +29 -0
- package/ExpoModulesCore.podspec +26 -5
- package/android/CMakeLists.txt +2 -1
- package/android/ExpoModulesCorePlugin.gradle +4 -0
- package/android/build.gradle +24 -31
- package/android/src/main/AndroidManifest.xml +1 -2
- package/android/src/main/cpp/ExpoModulesHostObject.cpp +3 -0
- package/android/src/main/cpp/JNIDeallocator.cpp +17 -0
- package/android/src/main/cpp/JNIDeallocator.h +25 -0
- package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +8 -1
- package/android/src/main/cpp/JSIInteropModuleRegistry.h +6 -1
- package/android/src/main/cpp/JavaCallback.cpp +9 -0
- package/android/src/main/cpp/JavaCallback.h +12 -2
- package/android/src/main/cpp/JavaScriptFunction.cpp +13 -0
- package/android/src/main/cpp/JavaScriptFunction.h +7 -1
- package/android/src/main/cpp/JavaScriptModuleObject.cpp +2 -1
- package/android/src/main/cpp/JavaScriptObject.cpp +17 -2
- package/android/src/main/cpp/JavaScriptObject.h +10 -3
- package/android/src/main/cpp/JavaScriptRuntime.cpp +5 -4
- package/android/src/main/cpp/JavaScriptRuntime.h +5 -3
- package/android/src/main/cpp/JavaScriptTypedArray.cpp +14 -0
- package/android/src/main/cpp/JavaScriptTypedArray.h +6 -0
- package/android/src/main/cpp/JavaScriptValue.cpp +32 -4
- package/android/src/main/cpp/JavaScriptValue.h +10 -3
- package/android/src/main/cpp/MethodMetadata.cpp +1 -1
- package/android/src/main/cpp/types/FrontendConverter.cpp +8 -4
- package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +14 -0
- package/android/src/main/java/expo/modules/kotlin/AppContext.kt +4 -1
- package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +7 -3
- package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +19 -12
- package/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt +70 -0
- package/android/src/main/java/expo/modules/kotlin/devtools/ExpoRequestCdpInterceptor.kt +72 -0
- package/android/src/main/java/expo/modules/kotlin/devtools/OkHttpHeadersExtension.kt +18 -0
- package/android/src/main/java/expo/modules/kotlin/devtools/cdp/CdpNetworkTypes.kt +257 -0
- package/android/src/main/java/expo/modules/kotlin/jni/JNIDeallocator.kt +24 -15
- package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +8 -1
- package/android/src/main/java/expo/modules/kotlin/jni/JavaCallback.kt +0 -4
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptFunction.kt +0 -4
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +5 -2
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +0 -5
- package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +0 -4
- package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +1 -1
- package/android/src/main/java/expo/modules/kotlin/types/ColorTypeConverter.kt +3 -0
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +1 -2
- package/android-annotation/build.gradle +2 -2
- package/android-annotation-processor/build.gradle +2 -2
- package/ios/AppDelegates/ExpoAppDelegate.swift +8 -1
- package/ios/JSI/EXJSIInstaller.h +2 -2
- package/ios/JSI/EXJSIInstaller.mm +6 -6
- package/ios/JSI/EXJavaScriptRuntime.h +0 -6
- package/ios/JSI/EXJavaScriptRuntime.mm +0 -23
- package/ios/RCTComponentData+Privates.h +17 -0
- package/ios/RCTComponentData+Privates.m +15 -0
- package/ios/Swift/AppContext.swift +20 -11
- package/ios/Swift/DevTools/CdpNetworkTypes.swift +163 -0
- package/ios/Swift/DevTools/ExpoRequestCdpInterceptor.swift +71 -0
- package/ios/Swift/DevTools/ExpoRequestInterceptorProtocol.swift +183 -0
- package/ios/Swift/DevTools/URLRequest+httpBodyData.swift +43 -0
- package/ios/Swift/ExpoRuntime.swift +28 -0
- package/ios/Swift/Modules/CoreModule.swift +7 -0
- package/ios/Swift/SharedObjects/SharedRef.swift +12 -0
- package/ios/Swift/Views/ComponentData.swift +1 -1
- package/ios/Tests/CoreModuleSpec.swift +27 -0
- package/ios/Tests/ExpoRequestCdpInterceptorSpec.swift +165 -0
- package/ios/Tests/SharedRefSpec.swift +60 -0
- package/package.json +2 -2
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
#pragma once
|
|
4
4
|
|
|
5
|
+
#include "JNIDeallocator.h"
|
|
6
|
+
|
|
5
7
|
#include <jsi/jsi.h>
|
|
6
8
|
#include <fbjni/fbjni.h>
|
|
7
9
|
#include <ReactCommon/CallInvoker.h>
|
|
@@ -65,19 +67,19 @@ public:
|
|
|
65
67
|
* @throws if the input format is unknown, or evaluation causes an error,
|
|
66
68
|
* a jni::JniException<JavaScriptEvaluateException> will be thrown.
|
|
67
69
|
*/
|
|
68
|
-
jni::local_ref<jni::HybridClass<JavaScriptValue>::javaobject> evaluateScript(
|
|
70
|
+
jni::local_ref<jni::HybridClass<JavaScriptValue, Destructible>::javaobject> evaluateScript(
|
|
69
71
|
const std::string &script
|
|
70
72
|
);
|
|
71
73
|
|
|
72
74
|
/**
|
|
73
75
|
* Returns the runtime global object for use in Kotlin.
|
|
74
76
|
*/
|
|
75
|
-
jni::local_ref<jni::HybridClass<JavaScriptObject>::javaobject> global();
|
|
77
|
+
jni::local_ref<jni::HybridClass<JavaScriptObject, Destructible>::javaobject> global();
|
|
76
78
|
|
|
77
79
|
/**
|
|
78
80
|
* Creates a new object for use in Kotlin.
|
|
79
81
|
*/
|
|
80
|
-
jni::local_ref<jni::HybridClass<JavaScriptObject>::javaobject> createObject();
|
|
82
|
+
jni::local_ref<jni::HybridClass<JavaScriptObject, Destructible>::javaobject> createObject();
|
|
81
83
|
|
|
82
84
|
/**
|
|
83
85
|
* Drains the JavaScript VM internal Microtask (a.k.a. event loop) queue.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#include "JavaScriptTypedArray.h"
|
|
2
2
|
|
|
3
3
|
#include "JavaScriptRuntime.h"
|
|
4
|
+
#include "JSIInteropModuleRegistry.h"
|
|
4
5
|
|
|
5
6
|
namespace expo {
|
|
6
7
|
|
|
@@ -88,4 +89,17 @@ void JavaScriptTypedArray::writeBuffer(
|
|
|
88
89
|
auto region = buffer->getRegion(0, size);
|
|
89
90
|
memcpy(rawPointer + position, region.get(), size);
|
|
90
91
|
}
|
|
92
|
+
|
|
93
|
+
jni::local_ref<JavaScriptTypedArray::javaobject> JavaScriptTypedArray::newInstance(
|
|
94
|
+
JSIInteropModuleRegistry *jsiInteropModuleRegistry,
|
|
95
|
+
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
96
|
+
std::shared_ptr<jsi::Object> jsObject
|
|
97
|
+
) {
|
|
98
|
+
auto object = JavaScriptTypedArray::newObjectCxxArgs(
|
|
99
|
+
std::move(runtime),
|
|
100
|
+
std::move(jsObject)
|
|
101
|
+
);
|
|
102
|
+
jsiInteropModuleRegistry->jniDeallocator->addReference(object);
|
|
103
|
+
return object;
|
|
104
|
+
}
|
|
91
105
|
}
|
|
@@ -25,6 +25,12 @@ public:
|
|
|
25
25
|
|
|
26
26
|
static void registerNatives();
|
|
27
27
|
|
|
28
|
+
static jni::local_ref<JavaScriptTypedArray::javaobject> newInstance(
|
|
29
|
+
JSIInteropModuleRegistry *jsiInteropModuleRegistry,
|
|
30
|
+
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
31
|
+
std::shared_ptr<jsi::Object> jsObject
|
|
32
|
+
);
|
|
33
|
+
|
|
28
34
|
JavaScriptTypedArray(
|
|
29
35
|
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
30
36
|
std::shared_ptr<jsi::Object> jsObject
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include "JavaScriptFunction.h"
|
|
9
9
|
#include "TypedArray.h"
|
|
10
10
|
#include "Exceptions.h"
|
|
11
|
+
#include "JSIInteropModuleRegistry.h"
|
|
11
12
|
|
|
12
13
|
namespace expo {
|
|
13
14
|
void JavaScriptValue::registerNatives() {
|
|
@@ -155,18 +156,27 @@ std::string JavaScriptValue::getString() {
|
|
|
155
156
|
jni::local_ref<JavaScriptObject::javaobject> JavaScriptValue::getObject() {
|
|
156
157
|
auto &jsRuntime = runtimeHolder.getJSRuntime();
|
|
157
158
|
auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(jsRuntime));
|
|
158
|
-
return JavaScriptObject::
|
|
159
|
+
return JavaScriptObject::newInstance(
|
|
160
|
+
runtimeHolder.getModuleRegistry(),
|
|
161
|
+
runtimeHolder,
|
|
162
|
+
jsObject
|
|
163
|
+
);
|
|
159
164
|
}
|
|
160
165
|
|
|
161
166
|
jni::local_ref<JavaScriptFunction::javaobject> JavaScriptValue::jniGetFunction() {
|
|
162
167
|
auto &jsRuntime = runtimeHolder.getJSRuntime();
|
|
163
168
|
auto jsFunction = std::make_shared<jsi::Function>(
|
|
164
169
|
jsValue->getObject(jsRuntime).asFunction(jsRuntime));
|
|
165
|
-
return JavaScriptFunction::
|
|
170
|
+
return JavaScriptFunction::newInstance(
|
|
171
|
+
runtimeHolder.getModuleRegistry(),
|
|
172
|
+
runtimeHolder,
|
|
173
|
+
jsFunction
|
|
174
|
+
);
|
|
166
175
|
}
|
|
167
176
|
|
|
168
177
|
jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> JavaScriptValue::getArray() {
|
|
169
178
|
auto &jsRuntime = runtimeHolder.getJSRuntime();
|
|
179
|
+
auto moduleRegistry = runtimeHolder.getModuleRegistry();
|
|
170
180
|
|
|
171
181
|
auto jsArray = jsValue
|
|
172
182
|
->getObject(jsRuntime)
|
|
@@ -175,7 +185,8 @@ jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> JavaScriptValue::g
|
|
|
175
185
|
|
|
176
186
|
auto result = jni::JArrayClass<JavaScriptValue::javaobject>::newArray(size);
|
|
177
187
|
for (size_t i = 0; i < size; i++) {
|
|
178
|
-
auto element = JavaScriptValue::
|
|
188
|
+
auto element = JavaScriptValue::newInstance(
|
|
189
|
+
moduleRegistry,
|
|
179
190
|
runtimeHolder,
|
|
180
191
|
std::make_shared<jsi::Value>(jsArray.getValueAtIndex(jsRuntime, i))
|
|
181
192
|
);
|
|
@@ -198,6 +209,23 @@ jni::local_ref<jstring> JavaScriptValue::jniGetString() {
|
|
|
198
209
|
jni::local_ref<JavaScriptTypedArray::javaobject> JavaScriptValue::getTypedArray() {
|
|
199
210
|
auto &jsRuntime = runtimeHolder.getJSRuntime();
|
|
200
211
|
auto jsObject = std::make_shared<jsi::Object>(jsValue->getObject(jsRuntime));
|
|
201
|
-
return JavaScriptTypedArray::
|
|
212
|
+
return JavaScriptTypedArray::newInstance(
|
|
213
|
+
runtimeHolder.getModuleRegistry(),
|
|
214
|
+
runtimeHolder,
|
|
215
|
+
jsObject
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
jni::local_ref<JavaScriptValue::javaobject> JavaScriptValue::newInstance(
|
|
220
|
+
JSIInteropModuleRegistry *jsiInteropModuleRegistry,
|
|
221
|
+
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
222
|
+
std::shared_ptr<jsi::Value> jsValue
|
|
223
|
+
) {
|
|
224
|
+
auto value = JavaScriptValue::newObjectCxxArgs(
|
|
225
|
+
std::move(runtime),
|
|
226
|
+
std::move(jsValue)
|
|
227
|
+
);
|
|
228
|
+
jsiInteropModuleRegistry->jniDeallocator->addReference(value);
|
|
229
|
+
return value;
|
|
202
230
|
}
|
|
203
231
|
} // namespace expo
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
#include "JSIObjectWrapper.h"
|
|
6
6
|
#include "WeakRuntimeHolder.h"
|
|
7
7
|
#include "JavaScriptTypedArray.h"
|
|
8
|
+
#include "JNIDeallocator.h"
|
|
8
9
|
|
|
9
10
|
#include <fbjni/fbjni.h>
|
|
10
11
|
#include <jsi/jsi.h>
|
|
@@ -26,7 +27,7 @@ class JavaScriptFunction;
|
|
|
26
27
|
/**
|
|
27
28
|
* Represents any JavaScript value. Its purpose is to expose the `jsi::Value` API back to Kotlin.
|
|
28
29
|
*/
|
|
29
|
-
class JavaScriptValue : public jni::HybridClass<JavaScriptValue>, JSIValueWrapper {
|
|
30
|
+
class JavaScriptValue : public jni::HybridClass<JavaScriptValue, Destructible>, JSIValueWrapper {
|
|
30
31
|
public:
|
|
31
32
|
static auto constexpr
|
|
32
33
|
kJavaDescriptor = "Lexpo/modules/kotlin/jni/JavaScriptValue;";
|
|
@@ -34,6 +35,12 @@ public:
|
|
|
34
35
|
|
|
35
36
|
static void registerNatives();
|
|
36
37
|
|
|
38
|
+
static jni::local_ref<JavaScriptValue::javaobject> newInstance(
|
|
39
|
+
JSIInteropModuleRegistry *jsiInteropModuleRegistry,
|
|
40
|
+
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
41
|
+
std::shared_ptr<jsi::Value> jsValue
|
|
42
|
+
);
|
|
43
|
+
|
|
37
44
|
JavaScriptValue(
|
|
38
45
|
std::weak_ptr<JavaScriptRuntime> runtime,
|
|
39
46
|
std::shared_ptr<jsi::Value> jsValue
|
|
@@ -74,13 +81,13 @@ public:
|
|
|
74
81
|
|
|
75
82
|
std::string getString();
|
|
76
83
|
|
|
77
|
-
jni::local_ref<jni::HybridClass<JavaScriptObject>::javaobject> getObject();
|
|
84
|
+
jni::local_ref<jni::HybridClass<JavaScriptObject, Destructible>::javaobject> getObject();
|
|
78
85
|
|
|
79
86
|
jni::local_ref<jni::JArrayClass<JavaScriptValue::javaobject>> getArray();
|
|
80
87
|
|
|
81
88
|
jni::local_ref<JavaScriptTypedArray::javaobject> getTypedArray();
|
|
82
89
|
|
|
83
|
-
jni::local_ref<jni::HybridClass<JavaScriptFunction>::javaobject> jniGetFunction();
|
|
90
|
+
jni::local_ref<jni::HybridClass<JavaScriptFunction, Destructible>::javaobject> jniGetFunction();
|
|
84
91
|
|
|
85
92
|
private:
|
|
86
93
|
friend HybridBase;
|
|
@@ -102,7 +102,7 @@ jni::local_ref<JavaCallback::JavaPart> createJavaCallbackFromJSIFunction(
|
|
|
102
102
|
wrapperWasCalled = true;
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
return JavaCallback::
|
|
105
|
+
return JavaCallback::newInstance(moduleRegistry, std::move(fn));
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
jobjectArray MethodMetadata::convertJSIArgsToJNI(
|
|
@@ -159,7 +159,8 @@ jobject TypedArrayFrontendConverter::convert(
|
|
|
159
159
|
JSIInteropModuleRegistry *moduleRegistry,
|
|
160
160
|
const jsi::Value &value
|
|
161
161
|
) const {
|
|
162
|
-
return JavaScriptTypedArray::
|
|
162
|
+
return JavaScriptTypedArray::newInstance(
|
|
163
|
+
moduleRegistry,
|
|
163
164
|
moduleRegistry->runtimeHolder->weak_from_this(),
|
|
164
165
|
std::make_shared<jsi::Object>(value.getObject(rt))
|
|
165
166
|
).release();
|
|
@@ -178,7 +179,8 @@ jobject JavaScriptValueFrontendConverter::convert(
|
|
|
178
179
|
JSIInteropModuleRegistry *moduleRegistry,
|
|
179
180
|
const jsi::Value &value
|
|
180
181
|
) const {
|
|
181
|
-
return JavaScriptValue::
|
|
182
|
+
return JavaScriptValue::newInstance(
|
|
183
|
+
moduleRegistry,
|
|
182
184
|
moduleRegistry->runtimeHolder->weak_from_this(),
|
|
183
185
|
// TODO(@lukmccall): make sure that copy here is necessary
|
|
184
186
|
std::make_shared<jsi::Value>(jsi::Value(rt, value))
|
|
@@ -195,7 +197,8 @@ jobject JavaScriptObjectFrontendConverter::convert(
|
|
|
195
197
|
JSIInteropModuleRegistry *moduleRegistry,
|
|
196
198
|
const jsi::Value &value
|
|
197
199
|
) const {
|
|
198
|
-
return JavaScriptObject::
|
|
200
|
+
return JavaScriptObject::newInstance(
|
|
201
|
+
moduleRegistry,
|
|
199
202
|
moduleRegistry->runtimeHolder->weak_from_this(),
|
|
200
203
|
std::make_shared<jsi::Object>(value.getObject(rt))
|
|
201
204
|
).release();
|
|
@@ -214,7 +217,8 @@ jobject JavaScriptFunctionFrontendConverter::convert(
|
|
|
214
217
|
JSIInteropModuleRegistry *moduleRegistry,
|
|
215
218
|
const jsi::Value &value
|
|
216
219
|
) const {
|
|
217
|
-
return JavaScriptFunction::
|
|
220
|
+
return JavaScriptFunction::newInstance(
|
|
221
|
+
moduleRegistry,
|
|
218
222
|
moduleRegistry->runtimeHolder->weak_from_this(),
|
|
219
223
|
std::make_shared<jsi::Function>(value.getObject(rt).asFunction(rt))
|
|
220
224
|
).release();
|
|
@@ -6,6 +6,7 @@ import android.view.ViewGroup;
|
|
|
6
6
|
|
|
7
7
|
import com.facebook.react.ReactActivity;
|
|
8
8
|
import com.facebook.react.ReactActivityDelegate;
|
|
9
|
+
import com.facebook.react.ReactNativeHost;
|
|
9
10
|
import com.facebook.react.ReactRootView;
|
|
10
11
|
|
|
11
12
|
import androidx.annotation.Nullable;
|
|
@@ -54,4 +55,17 @@ public interface ReactActivityHandler {
|
|
|
54
55
|
default ReactActivityDelegate onDidCreateReactActivityDelegate(ReactActivity activity, ReactActivityDelegate delegate) {
|
|
55
56
|
return null;
|
|
56
57
|
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* For modules to delay the call for react-native `loadApp`.
|
|
61
|
+
* This gives modules a chance to do some early and heavy initialization in background thread and avoid ANR.
|
|
62
|
+
* Right now it is for expo-updates only.
|
|
63
|
+
*/
|
|
64
|
+
@Nullable
|
|
65
|
+
default DelayLoadAppHandler getDelayLoadAppHandler(ReactActivity activity, ReactNativeHost reactNativeHost) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
interface DelayLoadAppHandler {
|
|
69
|
+
void whenReady(Runnable runnable);
|
|
70
|
+
}
|
|
57
71
|
}
|
|
@@ -91,6 +91,8 @@ class AppContext(
|
|
|
91
91
|
CoroutineName("expo.modules.MainQueue")
|
|
92
92
|
)
|
|
93
93
|
|
|
94
|
+
val jniDeallocator: JNIDeallocator = JNIDeallocator()
|
|
95
|
+
|
|
94
96
|
internal var legacyModulesProxyHolder: WeakReference<NativeModulesProxy>? = null
|
|
95
97
|
|
|
96
98
|
private val activityResultsManager = ActivityResultsManager(this)
|
|
@@ -130,6 +132,7 @@ class AppContext(
|
|
|
130
132
|
?.let {
|
|
131
133
|
jsiInterop.installJSI(
|
|
132
134
|
it,
|
|
135
|
+
jniDeallocator,
|
|
133
136
|
jsContextProvider.jsCallInvokerHolder,
|
|
134
137
|
catalystInstance.nativeCallInvokerHolder as CallInvokerHolderImpl
|
|
135
138
|
)
|
|
@@ -275,7 +278,7 @@ class AppContext(
|
|
|
275
278
|
modulesQueue.cancel(ContextDestroyedException())
|
|
276
279
|
mainQueue.cancel(ContextDestroyedException())
|
|
277
280
|
backgroundCoroutineScope.cancel(ContextDestroyedException())
|
|
278
|
-
|
|
281
|
+
jniDeallocator.deallocate()
|
|
279
282
|
logger.info("✅ AppContext was destroyed")
|
|
280
283
|
}
|
|
281
284
|
|
|
@@ -24,13 +24,16 @@ class ModuleHolder(val module: Module) {
|
|
|
24
24
|
*/
|
|
25
25
|
val jsObject by lazy {
|
|
26
26
|
val appContext = module.appContext
|
|
27
|
+
val jniDeallocator = appContext.jniDeallocator
|
|
27
28
|
|
|
28
|
-
JavaScriptModuleObject(name).apply {
|
|
29
|
+
JavaScriptModuleObject(jniDeallocator, name).apply {
|
|
29
30
|
initUsingObjectDefinition(appContext, definition.objectDefinition)
|
|
30
31
|
|
|
31
32
|
val viewFunctions = definition.viewManagerDefinition?.asyncFunctions
|
|
32
33
|
if (viewFunctions?.isNotEmpty() == true) {
|
|
33
|
-
val viewPrototype = JavaScriptModuleObject("${name}_${definition.viewManagerDefinition?.viewType?.name}")
|
|
34
|
+
val viewPrototype = JavaScriptModuleObject(jniDeallocator, "${name}_${definition.viewManagerDefinition?.viewType?.name}")
|
|
35
|
+
appContext.jniDeallocator.addReference(viewPrototype)
|
|
36
|
+
|
|
34
37
|
viewFunctions.forEach { function ->
|
|
35
38
|
function.attachToJSObject(appContext, viewPrototype)
|
|
36
39
|
}
|
|
@@ -39,8 +42,9 @@ class ModuleHolder(val module: Module) {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
definition.classData.forEach { clazz ->
|
|
42
|
-
val clazzModuleObject = JavaScriptModuleObject(clazz.name)
|
|
45
|
+
val clazzModuleObject = JavaScriptModuleObject(jniDeallocator, clazz.name)
|
|
43
46
|
.initUsingObjectDefinition(module.appContext, clazz.objectDefinition)
|
|
47
|
+
appContext.jniDeallocator.addReference(clazzModuleObject)
|
|
44
48
|
|
|
45
49
|
val constructor = clazz.constructor
|
|
46
50
|
registerClass(
|
|
@@ -17,8 +17,10 @@ class ModuleRegistry(
|
|
|
17
17
|
internal val registry = mutableMapOf<String, ModuleHolder>()
|
|
18
18
|
|
|
19
19
|
fun register(module: Module) {
|
|
20
|
-
val holder = ModuleHolder(module)
|
|
21
20
|
module._appContext = requireNotNull(appContext.get()) { "Cannot create a module for invalid app context." }
|
|
21
|
+
|
|
22
|
+
val holder = ModuleHolder(module)
|
|
23
|
+
|
|
22
24
|
module.coroutineScopeDelegate = lazy {
|
|
23
25
|
CoroutineScope(
|
|
24
26
|
Dispatchers.Default +
|
|
@@ -26,19 +28,24 @@ class ModuleRegistry(
|
|
|
26
28
|
CoroutineName(holder.definition.name)
|
|
27
29
|
)
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
holder.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
|
|
32
|
+
holder.apply {
|
|
33
|
+
post(EventName.MODULE_CREATE)
|
|
34
|
+
registerContracts()
|
|
35
|
+
|
|
36
|
+
// The initial invocation of `declaredMemberProperties` appears to be slow,
|
|
37
|
+
// as Kotlin must deserialize metadata internally.
|
|
38
|
+
// This is a known issue that may be resolved by the new K2 compiler in the future.
|
|
39
|
+
// However, until then, we must find a way to address this problem.
|
|
40
|
+
// Therefore, we have decided to dispatch a lambda
|
|
41
|
+
// that invokes `declaredMemberProperties` during module creation.
|
|
42
|
+
viewClass()?.let { viewType ->
|
|
43
|
+
appContext.get()?.backgroundCoroutineScope?.launch {
|
|
44
|
+
viewType.declaredMemberProperties
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
47
|
}
|
|
48
|
+
|
|
42
49
|
registry[holder.name] = holder
|
|
43
50
|
}
|
|
44
51
|
|
package/android/src/main/java/expo/modules/kotlin/devtools/ExpoNetworkInspectOkHttpInterceptors.kt
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
package expo.modules.kotlin.devtools
|
|
4
|
+
|
|
5
|
+
import okhttp3.Interceptor
|
|
6
|
+
import okhttp3.Request
|
|
7
|
+
import okhttp3.Response
|
|
8
|
+
|
|
9
|
+
// Currently keeps the delegate fixed for ExpoRequestCdpInterceptor and be thread-safe
|
|
10
|
+
internal val delegate: ExpoNetworkInspectOkHttpInterceptorsDelegate = ExpoRequestCdpInterceptor
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The OkHttp network interceptor to log requests and the CDP events to the delegate
|
|
14
|
+
*/
|
|
15
|
+
@Suppress("unused")
|
|
16
|
+
class ExpoNetworkInspectOkHttpNetworkInterceptor : Interceptor {
|
|
17
|
+
override fun intercept(chain: Interceptor.Chain): Response {
|
|
18
|
+
val request = chain.request()
|
|
19
|
+
val redirectResponse = request.tag(RedirectResponse::class.java)
|
|
20
|
+
val requestId = redirectResponse?.requestId ?: request.hashCode().toString()
|
|
21
|
+
delegate.willSendRequest(requestId, request, redirectResponse?.priorResponse)
|
|
22
|
+
|
|
23
|
+
val response = chain.proceed(request)
|
|
24
|
+
|
|
25
|
+
if (response.isRedirect) {
|
|
26
|
+
response.request.tag(RedirectResponse::class.java)?.let {
|
|
27
|
+
it.requestId = requestId
|
|
28
|
+
it.priorResponse = response
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
delegate.didReceiveResponse(requestId, request, response)
|
|
32
|
+
}
|
|
33
|
+
return response
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
companion object {
|
|
37
|
+
const val MAX_BODY_SIZE = 1048576L
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The OkHttp app interceptor to add custom tag for [RedirectResponse]
|
|
43
|
+
*/
|
|
44
|
+
@Suppress("unused")
|
|
45
|
+
class ExpoNetworkInspectOkHttpAppInterceptor : Interceptor {
|
|
46
|
+
override fun intercept(chain: Interceptor.Chain): Response {
|
|
47
|
+
return chain.proceed(
|
|
48
|
+
chain.request().newBuilder()
|
|
49
|
+
.tag(RedirectResponse::class.java, RedirectResponse())
|
|
50
|
+
.build()
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The delegate to dispatch network request events
|
|
57
|
+
*/
|
|
58
|
+
internal interface ExpoNetworkInspectOkHttpInterceptorsDelegate {
|
|
59
|
+
fun willSendRequest(requestId: String, request: Request, redirectResponse: Response?)
|
|
60
|
+
|
|
61
|
+
fun didReceiveResponse(requestId: String, request: Request, response: Response)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Custom property for redirect requests
|
|
66
|
+
*/
|
|
67
|
+
internal class RedirectResponse {
|
|
68
|
+
var requestId: String? = null
|
|
69
|
+
var priorResponse: Response? = null
|
|
70
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
package expo.modules.kotlin.devtools
|
|
4
|
+
|
|
5
|
+
import expo.modules.kotlin.devtools.cdp.Event
|
|
6
|
+
import expo.modules.kotlin.devtools.cdp.ExpoReceivedResponseBodyParams
|
|
7
|
+
import expo.modules.kotlin.devtools.cdp.LoadingFinishedParams
|
|
8
|
+
import expo.modules.kotlin.devtools.cdp.RequestWillBeSentExtraInfoParams
|
|
9
|
+
import expo.modules.kotlin.devtools.cdp.RequestWillBeSentParams
|
|
10
|
+
import expo.modules.kotlin.devtools.cdp.ResponseReceivedParams
|
|
11
|
+
import kotlinx.coroutines.CoroutineScope
|
|
12
|
+
import kotlinx.coroutines.Dispatchers
|
|
13
|
+
import kotlinx.coroutines.launch
|
|
14
|
+
import okhttp3.Request
|
|
15
|
+
import okhttp3.Response
|
|
16
|
+
import java.math.BigDecimal
|
|
17
|
+
import java.math.RoundingMode
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The `ExpoRequestInterceptorProtocolDelegate` implementation to
|
|
21
|
+
* dispatch CDP (Chrome DevTools Protocol: https://chromedevtools.github.io/devtools-protocol/) events.
|
|
22
|
+
*/
|
|
23
|
+
object ExpoRequestCdpInterceptor : ExpoNetworkInspectOkHttpInterceptorsDelegate {
|
|
24
|
+
private var delegate: Delegate? = null
|
|
25
|
+
internal var coroutineScope = CoroutineScope(Dispatchers.Default)
|
|
26
|
+
|
|
27
|
+
fun setDelegate(delegate: Delegate?) {
|
|
28
|
+
coroutineScope.launch {
|
|
29
|
+
this@ExpoRequestCdpInterceptor.delegate = delegate
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private fun dispatchEvent(event: Event) {
|
|
34
|
+
coroutineScope.launch {
|
|
35
|
+
this@ExpoRequestCdpInterceptor.delegate?.dispatch(event.toJson())
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//region ExpoNetworkInspectOkHttpInterceptorsDelegate implementations
|
|
40
|
+
|
|
41
|
+
override fun willSendRequest(requestId: String, request: Request, redirectResponse: Response?) {
|
|
42
|
+
val now = BigDecimal(System.currentTimeMillis() / 1000.0).setScale(3, RoundingMode.CEILING)
|
|
43
|
+
|
|
44
|
+
val params = RequestWillBeSentParams(now, requestId, request, redirectResponse)
|
|
45
|
+
dispatchEvent(Event("Network.requestWillBeSent", params))
|
|
46
|
+
|
|
47
|
+
val params2 = RequestWillBeSentExtraInfoParams(now, requestId, request)
|
|
48
|
+
dispatchEvent(Event("Network.requestWillBeSentExtraInfo", params2))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override fun didReceiveResponse(requestId: String, request: Request, response: Response) {
|
|
52
|
+
val now = BigDecimal(System.currentTimeMillis() / 1000.0).setScale(3, RoundingMode.CEILING)
|
|
53
|
+
|
|
54
|
+
val params = ResponseReceivedParams(now, requestId, request, response)
|
|
55
|
+
dispatchEvent(Event("Network.responseReceived", params))
|
|
56
|
+
|
|
57
|
+
val params2 = LoadingFinishedParams(now, requestId, request, response)
|
|
58
|
+
dispatchEvent(Event("Network.loadingFinished", params2))
|
|
59
|
+
|
|
60
|
+
val contentLength = response.body?.contentLength() ?: 0
|
|
61
|
+
if (contentLength >= 0 && contentLength <= ExpoNetworkInspectOkHttpNetworkInterceptor.MAX_BODY_SIZE) {
|
|
62
|
+
val params3 = ExpoReceivedResponseBodyParams(now, requestId, request, response)
|
|
63
|
+
dispatchEvent(Event("Expo(Network.receivedResponseBody)", params3))
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
//endregion ExpoNetworkInspectOkHttpInterceptorsDelegate implementations
|
|
68
|
+
|
|
69
|
+
interface Delegate {
|
|
70
|
+
fun dispatch(event: String)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Copyright 2015-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
package expo.modules.kotlin.devtools
|
|
4
|
+
|
|
5
|
+
import androidx.collection.ArrayMap
|
|
6
|
+
import okhttp3.Headers
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* OkHttp `Headers` extension method to generate a simple key-value map
|
|
10
|
+
* which only exposing single value for a key.
|
|
11
|
+
*/
|
|
12
|
+
fun Headers.toSingleMap(): Map<String, String> {
|
|
13
|
+
val result = ArrayMap<String, String>()
|
|
14
|
+
for (key in names()) {
|
|
15
|
+
result[key] = get(key)
|
|
16
|
+
}
|
|
17
|
+
return result
|
|
18
|
+
}
|