expo 50.0.17 → 51.0.0-beta.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.
Files changed (34) hide show
  1. package/android/build.gradle +15 -98
  2. package/android/src/main/java/expo/modules/ExpoReactHostFactory.kt +125 -0
  3. package/android/src/main/java/expo/modules/ReactActivityDelegateWrapper.kt +52 -32
  4. package/android/src/main/java/expo/modules/ReactNativeHostWrapperBase.kt +20 -33
  5. package/android/src/{reactNativeHostWrapper → reactWrappers}/expo/modules/ReactNativeHostWrapper.kt +15 -1
  6. package/build/Expo.fx.js +0 -14
  7. package/build/Expo.fx.js.map +1 -1
  8. package/build/Expo.fx.web.js.map +1 -1
  9. package/build/devtools/DevToolsPluginClient.js.map +1 -1
  10. package/build/devtools/DevToolsPluginClientFactory.js.map +1 -1
  11. package/build/devtools/DevToolsPluginClientImplApp.js.map +1 -1
  12. package/build/devtools/DevToolsPluginClientImplBrowser.js.map +1 -1
  13. package/build/devtools/WebSocketWithReconnect.d.ts.map +1 -1
  14. package/build/devtools/WebSocketWithReconnect.js +0 -1
  15. package/build/devtools/WebSocketWithReconnect.js.map +1 -1
  16. package/build/devtools/index.js.map +1 -1
  17. package/build/devtools/logger.js.map +1 -1
  18. package/build/environment/DevLoadingView.js.map +1 -1
  19. package/build/environment/ExpoGo.js.map +1 -1
  20. package/build/errors/ExpoErrorManager.native.js.map +1 -1
  21. package/build/launch/registerRootComponent.d.ts.map +1 -1
  22. package/build/launch/registerRootComponent.js +10 -14
  23. package/build/launch/registerRootComponent.js.map +1 -1
  24. package/build/launch/withDevTools.ios.js.map +1 -1
  25. package/build/launch/withDevTools.js.map +1 -1
  26. package/build/launch/withDevTools.web.js.map +1 -1
  27. package/build/timer/polyfillNextTick.js.map +1 -1
  28. package/build/winter/url.js.map +1 -1
  29. package/bundledNativeModules.json +92 -93
  30. package/package.json +15 -15
  31. package/scripts/autolinking.gradle +8 -3
  32. package/android/src/reactNativeHostWrapper64/expo/modules/ReactNativeHostWrapper.kt +0 -19
  33. package/android/src/reactNativeHostWrapper67/expo/modules/ReactNativeHostWrapper.kt +0 -42
  34. package/android/src/reactNativeHostWrapper69/expo/modules/ReactNativeHostWrapper.kt +0 -42
@@ -1,34 +1,23 @@
1
1
  apply plugin: 'com.android.library'
2
- apply plugin: 'kotlin-android'
3
- apply plugin: 'maven-publish'
4
2
 
5
3
  // Import autolinking script
6
4
  apply from: "../scripts/autolinking.gradle"
7
5
 
8
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
9
- if (expoModulesCorePlugin.exists()) {
10
- apply from: expoModulesCorePlugin
11
- applyKotlinExpoModulesCorePlugin()
12
-
13
- // Remove this check, but keep the contents after SDK49 support is dropped
14
- if (safeExtGet("expoProvidesDefaultConfig", false)) {
15
- useExpoPublishing()
16
- }
17
- }
7
+ apply from: expoModulesCorePlugin
8
+ applyKotlinExpoModulesCorePlugin()
9
+ useDefaultAndroidSdkVersions()
10
+ useExpoPublishing()
18
11
 
19
12
  static def versionToNumber(major, minor, patch) {
20
13
  return patch * 100 + minor * 10000 + major * 1000000
21
14
  }
22
15
 
23
16
  def getRNVersion() {
24
- def nodeModulesVersion = [
25
- "node",
26
- "-e",
27
- "console.log(require('react-native/package.json').version);"
28
- ]
29
- .execute(null, projectDir)
30
- .text
31
- .trim()
17
+ def nodeModulesVersion = providers.exec {
18
+ workingDir(projectDir)
19
+ commandLine("node", "-e", "console.log(require('react-native/package.json').version);")
20
+ }.standardOutput.asText.get().trim()
32
21
 
33
22
  def version = safeExtGet("reactNativeVersion", nodeModulesVersion)
34
23
  def coreVersion = version.split("-")[0]
@@ -44,87 +33,20 @@ def getRNVersion() {
44
33
  ensureDependeciesWereEvaluated(project)
45
34
 
46
35
  group = 'host.exp.exponent'
47
- version = '50.0.17'
36
+ version = '51.0.0-beta.0'
48
37
 
49
38
  buildscript {
50
39
  // Simple helper that allows the root project to override versions declared by this library.
51
40
  ext.safeExtGet = { prop, fallback ->
52
41
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
53
42
  }
54
-
55
- // Ensures backward compatibility
56
- ext.getKotlinVersion = {
57
- if (ext.has("kotlinVersion")) {
58
- ext.kotlinVersion()
59
- } else {
60
- ext.safeExtGet("kotlinVersion", "1.8.10")
61
- }
62
- }
63
-
64
- repositories {
65
- mavenCentral()
66
- }
67
-
68
- dependencies {
69
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
70
- }
71
- }
72
-
73
- // Remove this if and it's contents, when support for SDK49 is dropped
74
- if (!safeExtGet("expoProvidesDefaultConfig", false)) {
75
- afterEvaluate {
76
- publishing {
77
- publications {
78
- release(MavenPublication) {
79
- from components.release
80
- }
81
- }
82
- repositories {
83
- maven {
84
- url = mavenLocal().url
85
- }
86
- }
87
- }
88
- }
89
43
  }
90
44
 
91
45
  android {
92
- // Remove this if and it's contents, when support for SDK49 is dropped
93
- if (!safeExtGet("expoProvidesDefaultConfig", false)) {
94
- compileSdkVersion safeExtGet("compileSdkVersion", 34)
95
-
96
- defaultConfig {
97
- minSdkVersion safeExtGet("minSdkVersion", 23)
98
- targetSdkVersion safeExtGet("targetSdkVersion", 34)
99
- }
100
-
101
- publishing {
102
- singleVariant("release") {
103
- withSourcesJar()
104
- }
105
- }
106
-
107
- lintOptions {
108
- abortOnError false
109
- }
110
- }
111
-
112
- def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
113
- if (agpVersion.tokenize('.')[0].toInteger() < 8) {
114
- compileOptions {
115
- sourceCompatibility JavaVersion.VERSION_11
116
- targetCompatibility JavaVersion.VERSION_11
117
- }
118
-
119
- kotlinOptions {
120
- jvmTarget = JavaVersion.VERSION_11.majorVersion
121
- }
122
- }
123
-
124
46
  namespace "expo.core"
125
47
  defaultConfig {
126
48
  versionCode 1
127
- versionName "50.0.17"
49
+ versionName "51.0.0-beta.0"
128
50
  consumerProguardFiles("proguard-rules.pro")
129
51
  }
130
52
  testOptions {
@@ -137,14 +59,8 @@ android {
137
59
  srcDirs += new File(project.buildDir, generatedFilesSrcDir)
138
60
 
139
61
  def rnVersion = getRNVersion()
140
- if (rnVersion >= versionToNumber(0, 71, 0)) {
141
- srcDirs += "src/reactNativeHostWrapper"
142
- } else if (rnVersion >= versionToNumber(0, 69, 0)) {
143
- srcDirs += "src/reactNativeHostWrapper69"
144
- } else if (rnVersion >= versionToNumber(0, 67, 0)) {
145
- srcDirs += "src/reactNativeHostWrapper67"
146
- } else {
147
- srcDirs += "src/reactNativeHostWrapper64"
62
+ if (rnVersion >= versionToNumber(0, 74, 0)) {
63
+ srcDirs += "src/reactWrappers"
148
64
  }
149
65
  }
150
66
  }
@@ -165,7 +81,7 @@ dependencies { dependencyHandler ->
165
81
  }
166
82
 
167
83
  // A task generating a package list of expo modules.
168
- task generateExpoModulesPackageList {
84
+ task generateExpoModulesPackageListTask {
169
85
  def modulesConfig = getModulesConfig()
170
86
  def outputPath = getGenerateExpoModulesPackagesListPath()
171
87
  if (modulesConfig) {
@@ -173,10 +89,11 @@ task generateExpoModulesPackageList {
173
89
  inputs.property("modulesConfig", modulesConfig)
174
90
  }
175
91
 
92
+ // TOOD(@lukmccall): fix not working with configuration cache enabled
176
93
  doLast {
177
94
  generateExpoModulesPackageList()
178
95
  }
179
96
  }
180
97
 
181
98
  // Run that task during prebuilding phase.
182
- preBuild.dependsOn "generateExpoModulesPackageList"
99
+ preBuild.dependsOn "generateExpoModulesPackageListTask"
@@ -0,0 +1,125 @@
1
+ // Copyright 2015-present 650 Industries. All rights reserved.
2
+
3
+ package expo.modules
4
+
5
+ import android.content.Context
6
+ import com.facebook.react.JSEngineResolutionAlgorithm
7
+ import com.facebook.react.ReactHost
8
+ import com.facebook.react.ReactInstanceEventListener
9
+ import com.facebook.react.ReactNativeHost
10
+ import com.facebook.react.ReactPackage
11
+ import com.facebook.react.ReactPackageTurboModuleManagerDelegate
12
+ import com.facebook.react.bridge.JSBundleLoader
13
+ import com.facebook.react.bridge.ReactContext
14
+ import com.facebook.react.common.annotations.UnstableReactNativeAPI
15
+ import com.facebook.react.defaults.DefaultComponentsRegistry
16
+ import com.facebook.react.defaults.DefaultTurboModuleManagerDelegate
17
+ import com.facebook.react.fabric.ComponentFactory
18
+ import com.facebook.react.fabric.ReactNativeConfig
19
+ import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler
20
+ import com.facebook.react.runtime.BindingsInstaller
21
+ import com.facebook.react.runtime.JSCInstance
22
+ import com.facebook.react.runtime.JSRuntimeFactory
23
+ import com.facebook.react.runtime.ReactHostDelegate
24
+ import com.facebook.react.runtime.ReactHostImpl
25
+ import com.facebook.react.runtime.hermes.HermesInstance
26
+ import java.lang.ref.WeakReference
27
+
28
+ object ExpoReactHostFactory {
29
+ private var reactHost: ReactHost? = null
30
+
31
+ @UnstableReactNativeAPI
32
+ private class ExpoReactHostDelegate(
33
+ private val weakContext: WeakReference<Context>,
34
+ private val reactNativeHostWrapper: ReactNativeHostWrapper,
35
+ override val bindingsInstaller: BindingsInstaller? = null,
36
+ private val reactNativeConfig: ReactNativeConfig = ReactNativeConfig.DEFAULT_CONFIG,
37
+ override val turboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder =
38
+ DefaultTurboModuleManagerDelegate.Builder()
39
+ ) : ReactHostDelegate {
40
+ override val jsBundleLoader: JSBundleLoader
41
+ get() {
42
+ val context = weakContext.get() ?: throw IllegalStateException("Unable to get concrete Context")
43
+ reactNativeHostWrapper.jsBundleFile?.let { jsBundleFile ->
44
+ if (jsBundleFile.startsWith("assets://")) {
45
+ return JSBundleLoader.createAssetLoader(context, jsBundleFile, true)
46
+ }
47
+ return JSBundleLoader.createFileLoader(jsBundleFile)
48
+ }
49
+ val jsBundleAssetPath = reactNativeHostWrapper.bundleAssetName
50
+ return JSBundleLoader.createAssetLoader(context, "assets://$jsBundleAssetPath", true)
51
+ }
52
+
53
+ override val jsMainModulePath: String
54
+ get() = reactNativeHostWrapper.jsMainModuleName
55
+
56
+ override val jsRuntimeFactory: JSRuntimeFactory
57
+ get() = if (reactNativeHostWrapper.jsEngineResolutionAlgorithm == JSEngineResolutionAlgorithm.HERMES) {
58
+ HermesInstance()
59
+ } else {
60
+ JSCInstance()
61
+ }
62
+
63
+ override val reactPackages: List<ReactPackage>
64
+ get() = reactNativeHostWrapper.packages
65
+
66
+ override fun getReactNativeConfig(): ReactNativeConfig = reactNativeConfig
67
+
68
+ override fun handleInstanceException(error: Exception) {
69
+ val useDeveloperSupport = reactNativeHostWrapper.useDeveloperSupport
70
+ reactNativeHostWrapper.reactNativeHostHandlers.forEach { handler ->
71
+ handler.onReactInstanceException(useDeveloperSupport, error)
72
+ }
73
+ }
74
+ }
75
+
76
+ @OptIn(UnstableReactNativeAPI::class)
77
+ @JvmStatic
78
+ fun createFromReactNativeHost(
79
+ context: Context,
80
+ reactNativeHost: ReactNativeHost
81
+ ): ReactHost {
82
+ require(reactNativeHost is ReactNativeHostWrapper) {
83
+ "You can call createFromReactNativeHost only with instances of ReactNativeHostWrapper"
84
+ }
85
+ if (reactHost == null) {
86
+ val useDeveloperSupport = reactNativeHost.useDeveloperSupport
87
+ val reactHostDelegate = ExpoReactHostDelegate(WeakReference(context), reactNativeHost)
88
+ val reactJsExceptionHandler = ReactJsExceptionHandler { _ -> }
89
+ val componentFactory = ComponentFactory()
90
+ DefaultComponentsRegistry.register(componentFactory)
91
+
92
+ reactNativeHost.reactNativeHostHandlers.forEach { handler ->
93
+ handler.onWillCreateReactInstance(useDeveloperSupport)
94
+ }
95
+
96
+ val reactHostImpl =
97
+ ReactHostImpl(
98
+ context,
99
+ reactHostDelegate,
100
+ componentFactory,
101
+ true,
102
+ reactJsExceptionHandler,
103
+ useDeveloperSupport
104
+ )
105
+ .apply {
106
+ jsEngineResolutionAlgorithm = reactNativeHost.jsEngineResolutionAlgorithm
107
+ }
108
+
109
+ reactNativeHost.reactNativeHostHandlers.forEach { handler ->
110
+ handler.onDidCreateDevSupportManager(reactHostImpl.devSupportManager)
111
+ }
112
+
113
+ reactHostImpl.addReactInstanceEventListener(object : ReactInstanceEventListener {
114
+ override fun onReactContextInitialized(context: ReactContext) {
115
+ reactNativeHost.reactNativeHostHandlers.forEach { handler ->
116
+ handler.onDidCreateReactInstance(useDeveloperSupport, context)
117
+ }
118
+ }
119
+ })
120
+
121
+ reactHost = reactHostImpl
122
+ }
123
+ return reactHost as ReactHost
124
+ }
125
+ }
@@ -3,6 +3,7 @@ package expo.modules
3
3
  import android.app.Activity
4
4
  import android.content.Context
5
5
  import android.content.Intent
6
+ import android.content.res.Configuration
6
7
  import android.os.Bundle
7
8
  import android.view.KeyEvent
8
9
  import android.view.ViewGroup
@@ -10,11 +11,13 @@ import androidx.collection.ArrayMap
10
11
  import com.facebook.react.ReactActivity
11
12
  import com.facebook.react.ReactActivityDelegate
12
13
  import com.facebook.react.ReactDelegate
14
+ import com.facebook.react.ReactHost
13
15
  import com.facebook.react.ReactInstanceEventListener
14
16
  import com.facebook.react.ReactInstanceManager
15
17
  import com.facebook.react.ReactNativeHost
16
18
  import com.facebook.react.ReactRootView
17
19
  import com.facebook.react.bridge.ReactContext
20
+ import com.facebook.react.config.ReactFeatureFlags
18
21
  import com.facebook.react.modules.core.PermissionListener
19
22
  import expo.modules.core.interfaces.ReactActivityLifecycleListener
20
23
  import expo.modules.kotlin.Utils
@@ -35,9 +38,12 @@ class ReactActivityDelegateWrapper(
35
38
  private val reactActivityHandlers = ExpoModulesPackage.packageList
36
39
  .flatMap { it.createReactActivityHandlers(activity) }
37
40
  private val methodMap: ArrayMap<String, Method> = ArrayMap()
38
- private val host: ReactNativeHost by lazy {
41
+ private val _reactNativeHost: ReactNativeHost by lazy {
39
42
  invokeDelegateMethod("getReactNativeHost")
40
43
  }
44
+ private val _reactHost: ReactHost? by lazy {
45
+ delegate.reactHost
46
+ }
41
47
 
42
48
  /**
43
49
  * When the app delay for `loadApp`, the ReactInstanceManager's lifecycle will be disrupted.
@@ -51,16 +57,16 @@ class ReactActivityDelegateWrapper(
51
57
  return invokeDelegateMethod("getLaunchOptions")
52
58
  }
53
59
 
54
- override fun createRootView(): ReactRootView {
55
- val rootView = reactActivityHandlers.asSequence()
56
- .mapNotNull { it.createReactRootView(activity) }
57
- .firstOrNull() ?: invokeDelegateMethod("createRootView")
58
- rootView.setIsFabric(isNewArchitectureEnabled)
59
- return rootView
60
+ override fun createRootView(): ReactRootView? {
61
+ return invokeDelegateMethod("createRootView")
60
62
  }
61
63
 
62
64
  override fun getReactNativeHost(): ReactNativeHost {
63
- return host
65
+ return _reactNativeHost
66
+ }
67
+
68
+ override fun getReactHost(): ReactHost? {
69
+ return _reactHost
64
70
  }
65
71
 
66
72
  override fun getReactInstanceManager(): ReactInstanceManager {
@@ -93,18 +99,18 @@ class ReactActivityDelegateWrapper(
93
99
  }
94
100
 
95
101
  val delayLoadAppHandler = reactActivityHandlers.asSequence()
96
- .mapNotNull { it.getDelayLoadAppHandler(activity, host) }
102
+ .mapNotNull { it.getDelayLoadAppHandler(activity, reactNativeHost) }
97
103
  .firstOrNull()
98
104
  if (delayLoadAppHandler != null) {
105
+ shouldEmitPendingResume = true
99
106
  delayLoadAppHandler.whenReady {
100
107
  Utils.assertMainThread()
101
108
  invokeDelegateMethod<Unit, String?>("loadApp", arrayOf(String::class.java), arrayOf(appKey))
102
109
  reactActivityLifecycleListeners.forEach { listener ->
103
110
  listener.onContentChanged(activity)
104
111
  }
105
- if (shouldEmitPendingResume) {
106
- onResume()
107
- }
112
+ shouldEmitPendingResume = false
113
+ onResume()
108
114
  }
109
115
  return
110
116
  }
@@ -136,15 +142,25 @@ class ReactActivityDelegateWrapper(
136
142
  // the calls to `createRootView()` or `getMainComponentName()` have no chances to be our wrapped methods.
137
143
  // Instead we intercept `ReactActivityDelegate.onCreate` and replace the `mReactDelegate` with our version.
138
144
  // That's not ideal but works.
139
- val launchOptions = composeLaunchOptions() as Bundle? // composeLaunchOptions() is nullable but older react-native declares as nonnull.
140
- val reactDelegate = object : ReactDelegate(
141
- plainActivity,
142
- reactNativeHost,
143
- mainComponentName,
144
- launchOptions
145
- ) {
146
- override fun createRootView(): ReactRootView {
147
- return this@ReactActivityDelegateWrapper.createRootView()
145
+ val launchOptions = composeLaunchOptions()
146
+ val reactDelegate: ReactDelegate
147
+ if (ReactFeatureFlags.enableBridgelessArchitecture) {
148
+ reactDelegate = ReactDelegate(
149
+ plainActivity,
150
+ reactHost,
151
+ mainComponentName,
152
+ launchOptions
153
+ )
154
+ } else {
155
+ reactDelegate = object : ReactDelegate(
156
+ plainActivity,
157
+ reactNativeHost,
158
+ mainComponentName,
159
+ launchOptions
160
+ ) {
161
+ override fun createRootView(): ReactRootView {
162
+ return this@ReactActivityDelegateWrapper.createRootView() ?: super.createRootView()
163
+ }
148
164
  }
149
165
  }
150
166
  val mReactDelegate = ReactActivityDelegate::class.java.getDeclaredField("mReactDelegate")
@@ -161,22 +177,19 @@ class ReactActivityDelegateWrapper(
161
177
  }
162
178
 
163
179
  override fun onResume() {
164
- if (!host.hasInstance()) {
165
- shouldEmitPendingResume = true
180
+ if (shouldEmitPendingResume) {
166
181
  return
167
182
  }
168
183
  invokeDelegateMethod<Unit>("onResume")
169
184
  reactActivityLifecycleListeners.forEach { listener ->
170
185
  listener.onResume(activity)
171
186
  }
172
- shouldEmitPendingResume = false
173
187
  }
174
188
 
175
189
  override fun onPause() {
176
190
  // If app is stopped before delayed `loadApp`, we should cancel the pending resume
177
- shouldEmitPendingResume = false
178
- if (!host.hasInstance()) {
179
- return
191
+ if (shouldEmitPendingResume) {
192
+ shouldEmitPendingResume = false
180
193
  }
181
194
  reactActivityLifecycleListeners.forEach { listener ->
182
195
  listener.onPause(activity)
@@ -186,9 +199,8 @@ class ReactActivityDelegateWrapper(
186
199
 
187
200
  override fun onDestroy() {
188
201
  // If app is stopped before delayed `loadApp`, we should cancel the pending resume
189
- shouldEmitPendingResume = false
190
- if (!host.hasInstance()) {
191
- return
202
+ if (shouldEmitPendingResume) {
203
+ shouldEmitPendingResume = false
192
204
  }
193
205
  reactActivityLifecycleListeners.forEach { listener ->
194
206
  listener.onDestroy(activity)
@@ -210,9 +222,9 @@ class ReactActivityDelegateWrapper(
210
222
  *
211
223
  * TODO (@bbarthec): fix it upstream?
212
224
  */
213
- if (delegate.reactInstanceManager.currentReactContext == null) {
225
+ if (!ReactFeatureFlags.enableBridgelessArchitecture && delegate.reactInstanceManager.currentReactContext == null) {
214
226
  val reactContextListener = object : ReactInstanceEventListener {
215
- override fun onReactContextInitialized(context: ReactContext?) {
227
+ override fun onReactContextInitialized(context: ReactContext) {
216
228
  delegate.reactInstanceManager.removeReactInstanceEventListener(this)
217
229
  delegate.onActivityResult(requestCode, resultCode, data)
218
230
  }
@@ -279,6 +291,14 @@ class ReactActivityDelegateWrapper(
279
291
  return invokeDelegateMethod("isFabricEnabled")
280
292
  }
281
293
 
294
+ override fun composeLaunchOptions(): Bundle? {
295
+ return invokeDelegateMethod("composeLaunchOptions")
296
+ }
297
+
298
+ override fun onConfigurationChanged(newConfig: Configuration?) {
299
+ delegate.onConfigurationChanged(newConfig)
300
+ }
301
+
282
302
  //endregion
283
303
 
284
304
  //region Internals
@@ -2,21 +2,20 @@ package expo.modules
2
2
 
3
3
  import android.app.Application
4
4
  import androidx.collection.ArrayMap
5
+ import com.facebook.react.ReactInstanceEventListener
5
6
  import com.facebook.react.ReactInstanceManager
6
7
  import com.facebook.react.ReactNativeHost
7
8
  import com.facebook.react.ReactPackage
8
- import com.facebook.react.bridge.JSIModule
9
- import com.facebook.react.bridge.JSIModulePackage
10
- import com.facebook.react.bridge.JSIModuleSpec
11
- import com.facebook.react.bridge.JavaScriptContextHolder
12
9
  import com.facebook.react.bridge.JavaScriptExecutorFactory
13
- import com.facebook.react.bridge.ReactApplicationContext
10
+ import com.facebook.react.bridge.ReactContext
14
11
  import java.lang.reflect.Method
15
12
 
16
13
  open class ReactNativeHostWrapperBase(
17
14
  application: Application,
18
15
  protected val host: ReactNativeHost
19
16
  ) : ReactNativeHost(application) {
17
+ // TODO: Inherit from DefaultReactNativeHost when we drop SDK 49 support
18
+
20
19
  internal val reactNativeHostHandlers = ExpoModulesPackage.packageList
21
20
  .flatMap { it.createReactNativeHostHandlers(application) }
22
21
  private val methodMap: ArrayMap<String, Method> = ArrayMap()
@@ -24,17 +23,23 @@ open class ReactNativeHostWrapperBase(
24
23
  override fun createReactInstanceManager(): ReactInstanceManager {
25
24
  val developerSupport = useDeveloperSupport
26
25
  reactNativeHostHandlers.forEach { handler ->
27
- handler.onWillCreateReactInstanceManager(developerSupport)
26
+ handler.onWillCreateReactInstance(developerSupport)
28
27
  }
29
28
 
30
- val result = reactNativeHostHandlers.asSequence()
31
- .mapNotNull { it.createReactInstanceManager(developerSupport) }
32
- .firstOrNull() ?: super.createReactInstanceManager()
29
+ val result = super.createReactInstanceManager()
33
30
 
34
31
  reactNativeHostHandlers.forEach { handler ->
35
- handler.onDidCreateReactInstanceManager(result, developerSupport)
32
+ handler.onDidCreateDevSupportManager(result.devSupportManager)
36
33
  }
37
34
 
35
+ result.addReactInstanceEventListener(object : ReactInstanceEventListener {
36
+ override fun onReactContextInitialized(context: ReactContext) {
37
+ reactNativeHostHandlers.forEach { handler ->
38
+ handler.onDidCreateReactInstance(developerSupport, context)
39
+ }
40
+ }
41
+ })
42
+
38
43
  injectHostReactInstanceManager(result)
39
44
 
40
45
  return result
@@ -46,22 +51,17 @@ open class ReactNativeHostWrapperBase(
46
51
  .firstOrNull() ?: invokeDelegateMethod("getJavaScriptExecutorFactory")
47
52
  }
48
53
 
49
- override fun getJSIModulePackage(): JSIModulePackage? {
50
- val userJSIModulePackage = invokeDelegateMethod<JSIModulePackage?>("getJSIModulePackage")
51
- return JSIModuleContainerPackage(userJSIModulePackage)
52
- }
53
-
54
- override fun getJSMainModuleName(): String {
54
+ public override fun getJSMainModuleName(): String {
55
55
  return invokeDelegateMethod("getJSMainModuleName")
56
56
  }
57
57
 
58
- override fun getJSBundleFile(): String? {
58
+ public override fun getJSBundleFile(): String? {
59
59
  return reactNativeHostHandlers.asSequence()
60
60
  .mapNotNull { it.getJSBundleFile(useDeveloperSupport) }
61
61
  .firstOrNull() ?: invokeDelegateMethod<String?>("getJSBundleFile")
62
62
  }
63
63
 
64
- override fun getBundleAssetName(): String? {
64
+ public override fun getBundleAssetName(): String? {
65
65
  return reactNativeHostHandlers.asSequence()
66
66
  .mapNotNull { it.getBundleAssetName(useDeveloperSupport) }
67
67
  .firstOrNull() ?: invokeDelegateMethod<String?>("getBundleAssetName")
@@ -73,7 +73,7 @@ open class ReactNativeHostWrapperBase(
73
73
  .firstOrNull() ?: host.useDeveloperSupport
74
74
  }
75
75
 
76
- override fun getPackages(): MutableList<ReactPackage> {
76
+ public override fun getPackages(): MutableList<ReactPackage> {
77
77
  return invokeDelegateMethod("getPackages")
78
78
  }
79
79
 
@@ -81,19 +81,6 @@ open class ReactNativeHostWrapperBase(
81
81
 
82
82
  //region Internals
83
83
 
84
- inner class JSIModuleContainerPackage(userJSIModulePackage: JSIModulePackage?) : JSIModulePackage {
85
- private val userJSIModulePackage = userJSIModulePackage
86
- override fun getJSIModules(
87
- reactApplicationContext: ReactApplicationContext,
88
- jsContext: JavaScriptContextHolder
89
- ): List<JSIModuleSpec<JSIModule>> {
90
- reactNativeHostHandlers.forEach { handler ->
91
- handler.onRegisterJSIModules(reactApplicationContext, jsContext, useDeveloperSupport)
92
- }
93
- return userJSIModulePackage?.getJSIModules(reactApplicationContext, jsContext)?.toList() ?: emptyList()
94
- }
95
- }
96
-
97
84
  @Suppress("UNCHECKED_CAST")
98
85
  internal fun <T> invokeDelegateMethod(name: String): T {
99
86
  var method = methodMap[name]
@@ -109,7 +96,7 @@ open class ReactNativeHostWrapperBase(
109
96
  * Inject the @{ReactInstanceManager} from the wrapper to the wrapped host.
110
97
  * In case the wrapped host to call `getReactInstanceManager` inside its methods.
111
98
  */
112
- fun injectHostReactInstanceManager(reactInstanceManager: ReactInstanceManager) {
99
+ private fun injectHostReactInstanceManager(reactInstanceManager: ReactInstanceManager) {
113
100
  val mReactInstanceManagerField = ReactNativeHost::class.java.getDeclaredField("mReactInstanceManager")
114
101
  mReactInstanceManagerField.isAccessible = true
115
102
  mReactInstanceManagerField.set(host, reactInstanceManager)
@@ -1,9 +1,12 @@
1
1
  package expo.modules
2
2
 
3
3
  import android.app.Application
4
+ import android.content.Context
4
5
  import com.facebook.react.JSEngineResolutionAlgorithm
6
+ import com.facebook.react.ReactHost
5
7
  import com.facebook.react.ReactNativeHost
6
8
  import com.facebook.react.ReactPackageTurboModuleManagerDelegate
9
+ import com.facebook.react.bridge.UIManagerProvider
7
10
  import com.facebook.react.common.SurfaceDelegateFactory
8
11
  import com.facebook.react.devsupport.DevSupportManagerFactory
9
12
  import com.facebook.react.devsupport.interfaces.RedBoxHandler
@@ -24,7 +27,11 @@ class ReactNativeHostWrapper(
24
27
  return invokeDelegateMethod("getReactPackageTurboModuleManagerDelegateBuilder")
25
28
  }
26
29
 
27
- override fun getJSEngineResolutionAlgorithm(): JSEngineResolutionAlgorithm? {
30
+ override fun getUIManagerProvider(): UIManagerProvider? {
31
+ return invokeDelegateMethod("getUIManagerProvider")
32
+ }
33
+
34
+ public override fun getJSEngineResolutionAlgorithm(): JSEngineResolutionAlgorithm? {
28
35
  return invokeDelegateMethod("getJSEngineResolutionAlgorithm")
29
36
  }
30
37
 
@@ -39,4 +46,11 @@ class ReactNativeHostWrapper(
39
46
  override fun getRedBoxHandler(): RedBoxHandler? {
40
47
  return invokeDelegateMethod("getRedBoxHandler")
41
48
  }
49
+
50
+ companion object {
51
+ @JvmStatic
52
+ fun createReactHost(context: Context, reactNativeHost: ReactNativeHost): ReactHost {
53
+ return ExpoReactHostFactory.createFromReactNativeHost(context, reactNativeHost)
54
+ }
55
+ }
42
56
  }
package/build/Expo.fx.js CHANGED
@@ -2,7 +2,6 @@
2
2
  import './winter';
3
3
  import 'expo-asset';
4
4
  import * as Font from 'expo-font';
5
- import { NativeModulesProxy, Platform } from 'expo-modules-core';
6
5
  import { StyleSheet } from 'react-native';
7
6
  import { isRunningInExpoGo } from './environment/ExpoGo';
8
7
  import { createErrorHandler } from './errors/ExpoErrorManager';
@@ -10,19 +9,6 @@ import { createErrorHandler } from './errors/ExpoErrorManager';
10
9
  if (StyleSheet.setStyleAttributePreprocessor) {
11
10
  StyleSheet.setStyleAttributePreprocessor('fontFamily', Font.processFontFamily);
12
11
  }
13
- // Asserts if bare workflow isn't setup correctly.
14
- if (NativeModulesProxy.ExpoUpdates?.isMissingRuntimeVersion) {
15
- const message = 'expo-updates is installed but there is no runtime or SDK version configured. ' +
16
- "You'll need to configure one of these two properties in " +
17
- Platform.select({ ios: 'Expo.plist', android: 'AndroidManifest.xml' }) +
18
- ' before OTA updates will work properly.';
19
- if (__DEV__) {
20
- console.warn(message);
21
- }
22
- else {
23
- throw new Error(message);
24
- }
25
- }
26
12
  if (isRunningInExpoGo()) {
27
13
  // set up some improvements to commonly logged error messages stemming from react-native
28
14
  const globalHandler = ErrorUtils.getGlobalHandler();
@@ -1 +1 @@
1
- {"version":3,"file":"Expo.fx.js","sourceRoot":"","sources":["../src/Expo.fx.tsx"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,UAAU,CAAC;AAClB,OAAO,YAAY,CAAC;AAEpB,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,4FAA4F;AAC5F,IAAI,UAAU,CAAC,6BAA6B,EAAE;IAC5C,UAAU,CAAC,6BAA6B,CAAC,YAAY,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;CAChF;AAED,kDAAkD;AAClD,IAAI,kBAAkB,CAAC,WAAW,EAAE,uBAAuB,EAAE;IAC3D,MAAM,OAAO,GACX,+EAA+E;QAC/E,0DAA0D;QAC1D,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;QACtE,yCAAyC,CAAC;IAC5C,IAAI,OAAO,EAAE;QACX,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;KACvB;SAAM;QACL,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;KAC1B;CACF;AAED,IAAI,iBAAiB,EAAE,EAAE;IACvB,wFAAwF;IACxF,MAAM,aAAa,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;IACpD,UAAU,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC;CAChE","sourcesContent":["// load expo-asset immediately to set a custom `source` transformer in React Native\nimport './winter';\nimport 'expo-asset';\n\nimport * as Font from 'expo-font';\nimport { NativeModulesProxy, Platform } from 'expo-modules-core';\nimport { StyleSheet } from 'react-native';\n\nimport { isRunningInExpoGo } from './environment/ExpoGo';\nimport { createErrorHandler } from './errors/ExpoErrorManager';\n\n// If expo-font is installed and the style preprocessor is available, use it to parse fonts.\nif (StyleSheet.setStyleAttributePreprocessor) {\n StyleSheet.setStyleAttributePreprocessor('fontFamily', Font.processFontFamily);\n}\n\n// Asserts if bare workflow isn't setup correctly.\nif (NativeModulesProxy.ExpoUpdates?.isMissingRuntimeVersion) {\n const message =\n 'expo-updates is installed but there is no runtime or SDK version configured. ' +\n \"You'll need to configure one of these two properties in \" +\n Platform.select({ ios: 'Expo.plist', android: 'AndroidManifest.xml' }) +\n ' before OTA updates will work properly.';\n if (__DEV__) {\n console.warn(message);\n } else {\n throw new Error(message);\n }\n}\n\nif (isRunningInExpoGo()) {\n // set up some improvements to commonly logged error messages stemming from react-native\n const globalHandler = ErrorUtils.getGlobalHandler();\n ErrorUtils.setGlobalHandler(createErrorHandler(globalHandler));\n}\n"]}
1
+ {"version":3,"file":"Expo.fx.js","sourceRoot":"","sources":["../src/Expo.fx.tsx"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,UAAU,CAAC;AAClB,OAAO,YAAY,CAAC;AAEpB,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,4FAA4F;AAC5F,IAAI,UAAU,CAAC,6BAA6B,EAAE,CAAC;IAC7C,UAAU,CAAC,6BAA6B,CAAC,YAAY,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;AACjF,CAAC;AAED,IAAI,iBAAiB,EAAE,EAAE,CAAC;IACxB,wFAAwF;IACxF,MAAM,aAAa,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;IACpD,UAAU,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,CAAC;AACjE,CAAC","sourcesContent":["// load expo-asset immediately to set a custom `source` transformer in React Native\nimport './winter';\nimport 'expo-asset';\n\nimport * as Font from 'expo-font';\nimport { StyleSheet } from 'react-native';\n\nimport { isRunningInExpoGo } from './environment/ExpoGo';\nimport { createErrorHandler } from './errors/ExpoErrorManager';\n\n// If expo-font is installed and the style preprocessor is available, use it to parse fonts.\nif (StyleSheet.setStyleAttributePreprocessor) {\n StyleSheet.setStyleAttributePreprocessor('fontFamily', Font.processFontFamily);\n}\n\nif (isRunningInExpoGo()) {\n // set up some improvements to commonly logged error messages stemming from react-native\n const globalHandler = ErrorUtils.getGlobalHandler();\n ErrorUtils.setGlobalHandler(createErrorHandler(globalHandler));\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Expo.fx.web.js","sourceRoot":"","sources":["../src/Expo.fx.web.tsx"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,+EAA+E;AAC/E,oFAAoF;AACpF,qEAAqE;AACrE,IAAI,OAAO,EAAE;IACX;IACE,sDAAsD;IACtD,CAAC,CAAC,yBAAyB,IAAI,MAAM,CAAC,EACtC;QACA,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,yBAAyB,EAAE;YACvD,GAAG;gBACD,MAAM,IAAI,KAAK,CACb,qJAAqJ,CACtJ,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;KACJ;CACF","sourcesContent":["// When users dangerously import a file inside of react-native, it breaks the web alias.\n// This is one of the most common, and cryptic web errors that users encounter.\n// This conditional side-effect provides a more helpful error message for debugging.\n// Use a wrapper `__DEV__` to remove this entire block in production.\nif (__DEV__) {\n if (\n // Skip mocking if someone is shimming this value out.\n !('__fbBatchedBridgeConfig' in global)\n ) {\n Object.defineProperty(global, '__fbBatchedBridgeConfig', {\n get() {\n throw new Error(\n \"Your web project is importing a module from 'react-native' instead of 'react-native-web'. Learn more: https://expo.fyi/fb-batched-bridge-config-web\"\n );\n },\n });\n }\n}\n"]}
1
+ {"version":3,"file":"Expo.fx.web.js","sourceRoot":"","sources":["../src/Expo.fx.web.tsx"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,+EAA+E;AAC/E,oFAAoF;AACpF,qEAAqE;AACrE,IAAI,OAAO,EAAE,CAAC;IACZ;IACE,sDAAsD;IACtD,CAAC,CAAC,yBAAyB,IAAI,MAAM,CAAC,EACtC,CAAC;QACD,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,yBAAyB,EAAE;YACvD,GAAG;gBACD,MAAM,IAAI,KAAK,CACb,qJAAqJ,CACtJ,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC","sourcesContent":["// When users dangerously import a file inside of react-native, it breaks the web alias.\n// This is one of the most common, and cryptic web errors that users encounter.\n// This conditional side-effect provides a more helpful error message for debugging.\n// Use a wrapper `__DEV__` to remove this entire block in production.\nif (__DEV__) {\n if (\n // Skip mocking if someone is shimming this value out.\n !('__fbBatchedBridgeConfig' in global)\n ) {\n Object.defineProperty(global, '__fbBatchedBridgeConfig', {\n get() {\n throw new Error(\n \"Your web project is importing a module from 'react-native' instead of 'react-native-web'. Learn more: https://expo.fyi/fb-batched-bridge-config-web\"\n );\n },\n });\n }\n}\n"]}