expo-modules-core 1.11.0 β†’ 1.11.2

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 CHANGED
@@ -10,6 +10,18 @@
10
10
 
11
11
  ### πŸ’‘ Others
12
12
 
13
+ ## 1.11.2 β€” 2023-12-15
14
+
15
+ ### πŸ’‘ Others
16
+
17
+ - [Android] Bump Kotlin version from `1.8.10` to `1.8.22`. ([#25945](https://github.com/expo/expo/pull/25945) by [@lukmccall](https://github.com/lukmccall))
18
+
19
+ ## 1.11.1 β€” 2023-12-12
20
+
21
+ ### πŸ› Bug fixes
22
+
23
+ - [Android] Fixed `OnCreate` was called before the `React` instance was ready. ([#25866](https://github.com/expo/expo/pull/25866) by [@lukmccall](https://github.com/lukmccall))
24
+
13
25
  ## 1.11.0 β€” 2023-12-12
14
26
 
15
27
  ### πŸŽ‰ New features
@@ -23,14 +23,15 @@ class KotlinExpoModulesCorePlugin implements Plugin<Project> {
23
23
  "1.6.21": "1.6.21-1.0.6",
24
24
  "1.7.22": "1.7.22-1.0.8",
25
25
  "1.8.0": "1.8.0-1.0.9",
26
- "1.8.10": "1.8.10-1.0.9"
26
+ "1.8.10": "1.8.10-1.0.9",
27
+ "1.8.22": "1.8.22-1.0.11"
27
28
  ]
28
29
 
29
30
  project.rootProject.ext.has("kspVersion")
30
31
  ? project.rootProject.ext.get("kspVersion")
31
32
  : kspVersionsMap.containsKey(project.ext.kotlinVersion())
32
33
  ? kspVersionsMap.get(project.ext.kotlinVersion())
33
- : "1.8.10-1.0.9"
34
+ : "1.8.22-1.0.11"
34
35
  }
35
36
  }
36
37
 
@@ -5,7 +5,7 @@ apply plugin: 'kotlin-android'
5
5
  apply plugin: 'maven-publish'
6
6
 
7
7
  group = 'host.exp.exponent'
8
- version = '1.11.0'
8
+ version = '1.11.2'
9
9
 
10
10
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
11
11
  if (expoModulesCorePlugin.exists()) {
@@ -143,7 +143,7 @@ android {
143
143
  defaultConfig {
144
144
  consumerProguardFiles 'proguard-rules.pro'
145
145
  versionCode 1
146
- versionName "1.11.0"
146
+ versionName "1.11.2"
147
147
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
148
148
 
149
149
  testInstrumentationRunner "expo.modules.TestRunner"
@@ -223,46 +223,34 @@ android {
223
223
  }
224
224
  }
225
225
 
226
-
227
226
  dependencies {
228
227
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
229
228
  implementation "org.jetbrains.kotlin:kotlin-reflect:${getKotlinVersion()}"
230
- implementation 'androidx.annotation:annotation:1.3.0'
229
+ implementation 'androidx.annotation:annotation:1.7.1'
231
230
 
232
231
  api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0"
233
- api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0"
234
- api "androidx.core:core-ktx:1.6.0"
232
+ api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
233
+ api "androidx.core:core-ktx:1.12.0"
235
234
  api project(':expo-modules-core$android-annotation')
236
235
 
237
- /**
238
- * ReactActivity (the base activity for every React Native application) is subclassing AndroidX classes.
239
- * Unfortunately until https://github.com/facebook/react-native/pull/33072 is released React Native uses "androidx.appcompat:appcompat:1.0.2".
240
- * Gradle is picking the highest version of the dependency so we enforce higher version here.
241
- * see https://docs.gradle.org/current/userguide/dependency_resolution.html#sec:version-conflict
242
- * We're enforcing the most up-to-date versions of the dependencies here that are used in subclassing chain for ReactActivity.
243
- */
244
- implementation "androidx.appcompat:appcompat:1.4.1"
245
- implementation "androidx.activity:activity-ktx:1.7.1" // androidx.appcompat:appcompat:1.4.1 depends on version 1.2.3, so we enforce higher one here
246
- implementation "androidx.fragment:fragment-ktx:1.5.7" // androidx.appcomapt:appcompat:1.4.1 depends on version 1.3.4, so we enforce higher one here
247
-
248
- implementation("androidx.tracing:tracing-ktx:1.1.0")
236
+ implementation("androidx.tracing:tracing-ktx:1.2.0")
249
237
 
250
238
  //noinspection GradleDynamicVersion
251
239
  implementation 'com.facebook.react:react-native:+'
252
240
 
253
- compileOnly 'com.facebook.fbjni:fbjni:0.3.0'
241
+ compileOnly 'com.facebook.fbjni:fbjni:0.5.1'
254
242
 
255
- testImplementation 'androidx.test:core:1.4.0'
243
+ testImplementation 'androidx.test:core:1.5.0'
256
244
  testImplementation 'junit:junit:4.13.2'
257
- testImplementation 'io.mockk:mockk:1.12.3'
245
+ testImplementation 'io.mockk:mockk:1.13.5'
258
246
  testImplementation "com.google.truth:truth:1.1.2"
259
- testImplementation "org.robolectric:robolectric:4.10"
247
+ testImplementation "org.robolectric:robolectric:4.11.1"
260
248
  testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0"
261
249
  testImplementation "org.json:json:20230227"
262
250
 
263
- androidTestImplementation 'androidx.test:runner:1.4.0'
264
- androidTestImplementation 'androidx.test:core:1.4.0'
265
- androidTestImplementation 'androidx.test:rules:1.4.0'
251
+ androidTestImplementation 'androidx.test:runner:1.5.2'
252
+ androidTestImplementation 'androidx.test:core:1.5.0'
253
+ androidTestImplementation 'androidx.test:rules:1.5.0'
266
254
  androidTestImplementation "io.mockk:mockk-android:1.12.3"
267
255
  androidTestImplementation "com.google.truth:truth:1.1.2"
268
256
  androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0"
@@ -97,7 +97,10 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
97
97
  }
98
98
 
99
99
  mModuleRegistry.ensureIsInitialized();
100
- getKotlinInteropModuleRegistry().installJSIInterop();
100
+
101
+ KotlinInteropModuleRegistry kotlinModuleRegistry = getKotlinInteropModuleRegistry();
102
+ kotlinModuleRegistry.emitOnCreate();
103
+ kotlinModuleRegistry.installJSIInterop();
101
104
 
102
105
  Collection<ExportedModule> exportedModules = mModuleRegistry.getAllExportedModules();
103
106
 
@@ -121,7 +121,7 @@ class AppContext(
121
121
  addActivityEventListener(reactLifecycleDelegate)
122
122
 
123
123
  // Registering modules has to happen at the very end of `AppContext` creation. Some modules need to access
124
- // `AppContext` during their initialisation (or during `OnCreate` method), so we need to ensure all `AppContext`'s
124
+ // `AppContext` during their initialisation, so we need to ensure all `AppContext`'s
125
125
  // properties are initialized first. Not having that would trigger NPE.
126
126
  registry.register(ErrorManagerModule())
127
127
  registry.register(NativeModulesProxyModule())
@@ -131,6 +131,12 @@ class AppContext(
131
131
  }
132
132
  }
133
133
 
134
+ fun onCreate() = trace("AppContext.onCreate") {
135
+ registry.readyForPostingEvents()
136
+ registry.post(EventName.MODULE_CREATE)
137
+ registry.flushTheEventQueue()
138
+ }
139
+
134
140
  /**
135
141
  * Initializes a JSI part of the module registry.
136
142
  * It will be a NOOP if the remote debugging was activated.
@@ -128,6 +128,10 @@ class KotlinInteropModuleRegistry(
128
128
  appContext.installJSIInterop()
129
129
  }
130
130
 
131
+ fun emitOnCreate() {
132
+ appContext.onCreate()
133
+ }
134
+
131
135
  fun setLegacyModulesProxy(proxyModule: NativeModulesProxy) {
132
136
  appContext.legacyModulesProxyHolder = WeakReference(proxyModule)
133
137
  }
@@ -16,6 +16,10 @@ class ModuleRegistry(
16
16
  @PublishedApi
17
17
  internal val registry = mutableMapOf<String, ModuleHolder<*>>()
18
18
 
19
+ private val eventQueue = mutableListOf<PostponedEvent>()
20
+
21
+ private var isReadyForPostingEvents = false
22
+
19
23
  fun <T : Module> register(module: T) = trace("ModuleRegistry.register(${module.javaClass})") {
20
24
  module._appContext = requireNotNull(appContext.get()) { "Cannot create a module for invalid app context." }
21
25
 
@@ -30,7 +34,6 @@ class ModuleRegistry(
30
34
  }
31
35
 
32
36
  holder.apply {
33
- post(EventName.MODULE_CREATE)
34
37
  registerContracts()
35
38
  }
36
39
 
@@ -73,20 +76,30 @@ class ModuleRegistry(
73
76
  }
74
77
 
75
78
  fun post(eventName: EventName) {
79
+ if (addToQueueIfNeeded(eventName)) {
80
+ return
81
+ }
82
+
76
83
  forEach {
77
84
  it.post(eventName)
78
85
  }
79
86
  }
80
87
 
81
- @Suppress("UNCHECKED_CAST")
82
88
  fun <Sender> post(eventName: EventName, sender: Sender) {
89
+ if (addToQueueIfNeeded(eventName, sender)) {
90
+ return
91
+ }
92
+
83
93
  forEach {
84
94
  it.post(eventName, sender)
85
95
  }
86
96
  }
87
97
 
88
- @Suppress("UNCHECKED_CAST")
89
98
  fun <Sender, Payload> post(eventName: EventName, sender: Sender, payload: Payload) {
99
+ if (addToQueueIfNeeded(eventName, sender, payload)) {
100
+ return
101
+ }
102
+
90
103
  forEach {
91
104
  it.post(eventName, sender, payload)
92
105
  }
@@ -98,4 +111,60 @@ class ModuleRegistry(
98
111
  registry.clear()
99
112
  logger.info("βœ… ModuleRegistry was destroyed")
100
113
  }
114
+
115
+ /**
116
+ * Tell the modules registry it can handle events as they come, without adding them to the event queue.
117
+ */
118
+ fun readyForPostingEvents() = synchronized(this) {
119
+ isReadyForPostingEvents = true
120
+ }
121
+
122
+ fun flushTheEventQueue() = synchronized(this) {
123
+ eventQueue.forEach { event ->
124
+ forEach {
125
+ event.post(it)
126
+ }
127
+ }
128
+ eventQueue.clear()
129
+ }
130
+
131
+ /**
132
+ * It’s important that the [EventName.MODULE_CREATE] event is emitted first by the registry.
133
+ * However, some events like [EventName.ACTIVITY_ENTERS_FOREGROUND] are automatically emitted when the catalyst instance is created.
134
+ * To ensure the correct order of events, we capture all events that are emitted
135
+ * during the initialization phase and send them back to the modules later.
136
+ * This way, we can ensure that the order of events is correct.
137
+ */
138
+ private fun addToQueueIfNeeded(
139
+ eventName: EventName,
140
+ sender: Any? = null,
141
+ payload: Any? = null
142
+ ): Boolean = synchronized(this) {
143
+ if (isReadyForPostingEvents) {
144
+ return false
145
+ }
146
+
147
+ eventQueue.add(PostponedEvent(eventName, sender, payload))
148
+ return true
149
+ }
150
+
151
+ data class PostponedEvent(
152
+ val eventName: EventName,
153
+ val sender: Any? = null,
154
+ val payload: Any? = null
155
+ ) {
156
+ fun post(moduleHolder: ModuleHolder<*>) {
157
+ if (sender != null && payload != null) {
158
+ moduleHolder.post(eventName, sender, payload)
159
+ return
160
+ }
161
+
162
+ if (sender != null) {
163
+ moduleHolder.post(eventName, sender)
164
+ return
165
+ }
166
+
167
+ moduleHolder.post(eventName)
168
+ }
169
+ }
101
170
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "1.11.0",
3
+ "version": "1.11.2",
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": "6aca7ce098ddc667776a3d7cf612adbb985e264a"
47
+ "gitHead": "1a7c4e8ffed182e00cf1cf654ca2401441a7377a"
48
48
  }