expo-modules-core 1.12.14 → 1.12.16
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 +13 -0
- package/android/build.gradle +2 -2
- package/android/src/main/cpp/JSIContext.cpp +7 -5
- package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +3 -3
- package/ios/DevTools/ExpoRequestCdpInterceptor.swift +1 -1
- package/ios/DevTools/ExpoRequestInterceptorProtocol.swift +131 -28
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,19 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 1.12.16 — 2024-06-20
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fixed resource leakage from `ExpoRequestInterceptorProtocol`. ([#29798](https://github.com/expo/expo/pull/29798) by [@kudo](https://github.com/kudo))
|
|
18
|
+
|
|
19
|
+
## 1.12.15 — 2024-06-13
|
|
20
|
+
|
|
21
|
+
### 🐛 Bug fixes
|
|
22
|
+
|
|
23
|
+
- Fixed reload crash on Android. ([#29593](https://github.com/expo/expo/pull/29593) by [@kudo](https://github.com/kudo))
|
|
24
|
+
- [Android] Fixed converting from `null` to `Record` sometimes didn't work as expected. ([#29508](https://github.com/expo/expo/pull/29508) by [@lukmccall](https://github.com/lukmccall))
|
|
25
|
+
|
|
13
26
|
## 1.12.14 — 2024-06-06
|
|
14
27
|
|
|
15
28
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'host.exp.exponent'
|
|
4
|
-
version = '1.12.
|
|
4
|
+
version = '1.12.16'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -63,7 +63,7 @@ android {
|
|
|
63
63
|
defaultConfig {
|
|
64
64
|
consumerProguardFiles 'proguard-rules.pro'
|
|
65
65
|
versionCode 1
|
|
66
|
-
versionName "1.12.
|
|
66
|
+
versionName "1.12.16"
|
|
67
67
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
|
|
68
68
|
|
|
69
69
|
testInstrumentationRunner "expo.modules.TestRunner"
|
|
@@ -93,11 +93,13 @@ JSIContext::JSIContext(jni::alias_ref<jhybridobject> jThis)
|
|
|
93
93
|
: javaPart_(jni::make_global(jThis)) {}
|
|
94
94
|
|
|
95
95
|
JSIContext::~JSIContext() {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
if (runtimeHolder) {
|
|
97
|
+
unbindJSIContext(runtimeHolder->get());
|
|
98
|
+
// The runtime would be deallocated automatically.
|
|
99
|
+
// However, we need to enforce the order of deallocations.
|
|
100
|
+
// The runtime has to be deallocated before the JNI part.
|
|
101
|
+
runtimeHolder.reset();
|
|
102
|
+
}
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
void JSIContext::installJSI(
|
|
@@ -73,7 +73,7 @@ object TypeConverterProviderImpl : TypeConverterProvider {
|
|
|
73
73
|
private val cachedConverters = createCachedConverters(false)
|
|
74
74
|
private val nullableCachedConverters = createCachedConverters(true)
|
|
75
75
|
|
|
76
|
-
private val cachedRecordConverters = mutableMapOf<
|
|
76
|
+
private val cachedRecordConverters = mutableMapOf<KType, TypeConverter<*>>()
|
|
77
77
|
|
|
78
78
|
private fun getCachedConverter(inputType: KType): TypeConverter<*>? {
|
|
79
79
|
return if (inputType.isMarkedNullable) {
|
|
@@ -116,14 +116,14 @@ object TypeConverterProviderImpl : TypeConverterProvider {
|
|
|
116
116
|
return EnumTypeConverter(kClass as KClass<Enum<*>>, type.isMarkedNullable)
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
val cachedConverter = cachedRecordConverters[
|
|
119
|
+
val cachedConverter = cachedRecordConverters[type]
|
|
120
120
|
if (cachedConverter != null) {
|
|
121
121
|
return cachedConverter
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
if (Record::class.java.isAssignableFrom(jClass)) {
|
|
125
125
|
val converter = RecordTypeConverter<Record>(this, type)
|
|
126
|
-
cachedRecordConverters[
|
|
126
|
+
cachedRecordConverters[type] = converter
|
|
127
127
|
return converter
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -9,7 +9,7 @@ import Foundation
|
|
|
9
9
|
@objc(EXRequestCdpInterceptor)
|
|
10
10
|
public final class ExpoRequestCdpInterceptor: NSObject, ExpoRequestInterceptorProtocolDelegate {
|
|
11
11
|
private var delegate: ExpoRequestCdpInterceptorDelegate?
|
|
12
|
-
|
|
12
|
+
public var dispatchQueue = DispatchQueue(label: "expo.requestCdpInterceptor")
|
|
13
13
|
|
|
14
14
|
override private init() {}
|
|
15
15
|
|
|
@@ -7,13 +7,13 @@ import Foundation
|
|
|
7
7
|
*/
|
|
8
8
|
@objc(EXRequestInterceptorProtocol)
|
|
9
9
|
public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDelegate {
|
|
10
|
-
private static let
|
|
11
|
-
private static
|
|
12
|
-
private lazy var urlSession = URLSession(
|
|
10
|
+
private static let sessionDelegateProxy = URLSessionSessionDelegateProxy()
|
|
11
|
+
private static let urlSession = URLSession(
|
|
13
12
|
configuration: URLSessionConfiguration.default,
|
|
14
|
-
delegate:
|
|
13
|
+
delegate: sessionDelegateProxy,
|
|
15
14
|
delegateQueue: nil
|
|
16
15
|
)
|
|
16
|
+
private var requestId: String?
|
|
17
17
|
private var dataTask_: URLSessionDataTask?
|
|
18
18
|
private let responseBody = NSMutableData()
|
|
19
19
|
private var responseBodyExceedsLimit = false
|
|
@@ -32,11 +32,10 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
32
32
|
if !["http", "https"].contains(scheme) {
|
|
33
33
|
return false
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
forKey:
|
|
35
|
+
return URLProtocol.property(
|
|
36
|
+
forKey: REQUEST_ID,
|
|
37
37
|
in: request
|
|
38
38
|
) == nil
|
|
39
|
-
return isNewRequest
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
override init(
|
|
@@ -48,13 +47,16 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
48
47
|
// swiftlint:disable force_cast
|
|
49
48
|
let mutableRequest = request as! NSMutableURLRequest
|
|
50
49
|
// swiftlint:enable force_cast
|
|
51
|
-
|
|
50
|
+
self.requestId = Self.sessionDelegateProxy.addDelegate(delegate: self)
|
|
51
|
+
guard let requestId else {
|
|
52
|
+
fatalError("requestId should not be nil.")
|
|
53
|
+
}
|
|
52
54
|
URLProtocol.setProperty(
|
|
53
55
|
requestId,
|
|
54
|
-
forKey:
|
|
56
|
+
forKey: REQUEST_ID,
|
|
55
57
|
in: mutableRequest
|
|
56
58
|
)
|
|
57
|
-
let dataTask = urlSession.dataTask(with: mutableRequest as URLRequest)
|
|
59
|
+
let dataTask = Self.urlSession.dataTask(with: mutableRequest as URLRequest)
|
|
58
60
|
Self.delegate.willSendRequest(
|
|
59
61
|
requestId: requestId,
|
|
60
62
|
task: dataTask,
|
|
@@ -74,6 +76,9 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
74
76
|
|
|
75
77
|
public override func stopLoading() {
|
|
76
78
|
dataTask_?.cancel()
|
|
79
|
+
if let requestId {
|
|
80
|
+
Self.sessionDelegateProxy.removeDelegate(requestId: requestId)
|
|
81
|
+
}
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
// MARK: URLSessionDataDelegate implementations
|
|
@@ -91,12 +96,8 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
91
96
|
if let error = error {
|
|
92
97
|
client?.urlProtocol(self, didFailWithError: error)
|
|
93
98
|
} else {
|
|
94
|
-
if let
|
|
95
|
-
let
|
|
96
|
-
let requestId = URLProtocol.property(
|
|
97
|
-
forKey: Self.REQUEST_ID,
|
|
98
|
-
in: currentRequest
|
|
99
|
-
) as? String {
|
|
99
|
+
if let response = task.response as? HTTPURLResponse,
|
|
100
|
+
let requestId {
|
|
100
101
|
let contentType = response.value(forHTTPHeaderField: "Content-Type")
|
|
101
102
|
let isText = (contentType?.starts(with: "text/") ?? false) || contentType == "application/json"
|
|
102
103
|
Self.delegate.didReceiveResponse(
|
|
@@ -123,7 +124,7 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
123
124
|
newRequest request: URLRequest,
|
|
124
125
|
completionHandler: @escaping (URLRequest?) -> Void
|
|
125
126
|
) {
|
|
126
|
-
if let requestId
|
|
127
|
+
if let requestId {
|
|
127
128
|
Self.delegate.willSendRequest(
|
|
128
129
|
requestId: requestId,
|
|
129
130
|
task: task,
|
|
@@ -141,6 +142,118 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
141
142
|
let requestId: String
|
|
142
143
|
let redirectResponse: HTTPURLResponse
|
|
143
144
|
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
The delegate to dispatch network request events
|
|
149
|
+
*/
|
|
150
|
+
@objc(EXRequestInterceptorProtocolDelegate)
|
|
151
|
+
protocol ExpoRequestInterceptorProtocolDelegate {
|
|
152
|
+
@objc
|
|
153
|
+
func willSendRequest(requestId: String, task: URLSessionTask, request: URLRequest, redirectResponse: HTTPURLResponse?)
|
|
154
|
+
|
|
155
|
+
@objc
|
|
156
|
+
func didReceiveResponse(requestId: String, task: URLSessionTask, responseBody: Data, isText: Bool, responseBodyExceedsLimit: Bool)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
Shared URLSessionDataDelegate instance and delete calls back to ExpoRequestInterceptorProtocol instances.
|
|
161
|
+
*/
|
|
162
|
+
private class URLSessionSessionDelegateProxy: NSObject, URLSessionDataDelegate {
|
|
163
|
+
private var requestIdProvider = RequestIdProvider()
|
|
164
|
+
private var delegateMap: [String: URLSessionDataDelegate] = [:]
|
|
165
|
+
private let dispatchQueue = ExpoRequestCdpInterceptor.shared.dispatchQueue
|
|
166
|
+
|
|
167
|
+
func addDelegate(delegate: URLSessionDataDelegate) -> String {
|
|
168
|
+
let requestId = self.requestIdProvider.create()
|
|
169
|
+
self.dispatchQueue.async {
|
|
170
|
+
self.delegateMap[requestId] = delegate
|
|
171
|
+
}
|
|
172
|
+
return requestId
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
func removeDelegate(requestId: String) {
|
|
176
|
+
self.dispatchQueue.async {
|
|
177
|
+
self.delegateMap.removeValue(forKey: requestId)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private func getRequestId(task: URLSessionTask) -> String? {
|
|
182
|
+
if let currentRequest = task.currentRequest,
|
|
183
|
+
let requestId = URLProtocol.property(
|
|
184
|
+
forKey: REQUEST_ID,
|
|
185
|
+
in: currentRequest
|
|
186
|
+
) as? String {
|
|
187
|
+
return requestId
|
|
188
|
+
}
|
|
189
|
+
return nil
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private func getDelegate(requestId: String) -> URLSessionDataDelegate? {
|
|
193
|
+
return self.dispatchQueue.sync {
|
|
194
|
+
return self.delegateMap[requestId]
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private func getDelegate(task: URLSessionTask) -> URLSessionDataDelegate? {
|
|
199
|
+
guard let requestId = self.getRequestId(task: task) else {
|
|
200
|
+
return nil
|
|
201
|
+
}
|
|
202
|
+
return self.getDelegate(requestId: requestId)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// MARK: URLSessionDataDelegate implementations
|
|
206
|
+
|
|
207
|
+
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive: Data) {
|
|
208
|
+
if let delegate = getDelegate(task: dataTask) {
|
|
209
|
+
delegate.urlSession?(
|
|
210
|
+
session,
|
|
211
|
+
dataTask: dataTask,
|
|
212
|
+
didReceive: didReceive)
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError: Error?) {
|
|
217
|
+
if let requestId = self.getRequestId(task: task), let delegate = getDelegate(requestId: requestId) {
|
|
218
|
+
delegate.urlSession?(
|
|
219
|
+
session,
|
|
220
|
+
task: task,
|
|
221
|
+
didCompleteWithError: didCompleteWithError)
|
|
222
|
+
self.removeDelegate(requestId: requestId)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
func urlSession(
|
|
227
|
+
_ session: URLSession,
|
|
228
|
+
dataTask: URLSessionDataTask,
|
|
229
|
+
didReceive: URLResponse,
|
|
230
|
+
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void
|
|
231
|
+
) {
|
|
232
|
+
if let delegate = getDelegate(task: dataTask) {
|
|
233
|
+
delegate.urlSession?(
|
|
234
|
+
session,
|
|
235
|
+
dataTask: dataTask,
|
|
236
|
+
didReceive: didReceive,
|
|
237
|
+
completionHandler: completionHandler)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
func urlSession(
|
|
242
|
+
_ session: URLSession,
|
|
243
|
+
task: URLSessionTask,
|
|
244
|
+
willPerformHTTPRedirection: HTTPURLResponse,
|
|
245
|
+
newRequest: URLRequest,
|
|
246
|
+
completionHandler: @escaping (URLRequest?) -> Void
|
|
247
|
+
) {
|
|
248
|
+
if let delegate = getDelegate(task: task) {
|
|
249
|
+
delegate.urlSession?(
|
|
250
|
+
session,
|
|
251
|
+
task: task,
|
|
252
|
+
willPerformHTTPRedirection: willPerformHTTPRedirection,
|
|
253
|
+
newRequest: newRequest,
|
|
254
|
+
completionHandler: completionHandler)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
144
257
|
|
|
145
258
|
/**
|
|
146
259
|
A helper class to create a unique request ID
|
|
@@ -157,14 +270,4 @@ public final class ExpoRequestInterceptorProtocol: URLProtocol, URLSessionDataDe
|
|
|
157
270
|
}
|
|
158
271
|
}
|
|
159
272
|
|
|
160
|
-
|
|
161
|
-
The delegate to dispatch network request events
|
|
162
|
-
*/
|
|
163
|
-
@objc(EXRequestInterceptorProtocolDelegate)
|
|
164
|
-
protocol ExpoRequestInterceptorProtocolDelegate {
|
|
165
|
-
@objc
|
|
166
|
-
func willSendRequest(requestId: String, task: URLSessionTask, request: URLRequest, redirectResponse: HTTPURLResponse?)
|
|
167
|
-
|
|
168
|
-
@objc
|
|
169
|
-
func didReceiveResponse(requestId: String, task: URLSessionTask, responseBody: Data, isText: Bool, responseBodyExceedsLimit: Bool)
|
|
170
|
-
}
|
|
273
|
+
private let REQUEST_ID = "ExpoRequestInterceptorProtocol.requestId"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-modules-core",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.16",
|
|
4
4
|
"description": "The core of Expo Modules architecture",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"@testing-library/react-hooks": "^7.0.1",
|
|
45
45
|
"expo-module-scripts": "^3.0.0"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "0d1a3567cb0fce9c54e1185654be88bd0c7842d4"
|
|
48
48
|
}
|