expo 55.0.0-canary-20250930-9dc59d3 → 55.0.0-canary-20251008-6acbc1c

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/Expo.podspec CHANGED
@@ -87,6 +87,7 @@ Pod::Spec.new do |s|
87
87
  # [end] transitive dependencies of React-RCTAppDelegate that are not defined modules
88
88
  ])
89
89
  end
90
+
90
91
  s.pod_target_xcconfig = {
91
92
  'HEADER_SEARCH_PATHS' => header_search_paths.join(' '),
92
93
  }
@@ -32,7 +32,7 @@ buildscript {
32
32
  def reactNativeVersion = project.extensions.getByType(ExpoModuleExtension).reactNativeVersion
33
33
 
34
34
  group = 'host.exp.exponent'
35
- version = '55.0.0-canary-20250930-9dc59d3'
35
+ version = '55.0.0-canary-20251008-6acbc1c'
36
36
 
37
37
  expoModule {
38
38
  // We can't prebuild the module because it depends on the generated files.
@@ -43,7 +43,7 @@ android {
43
43
  namespace "expo.core"
44
44
  defaultConfig {
45
45
  versionCode 1
46
- versionName "55.0.0-canary-20250930-9dc59d3"
46
+ versionName "55.0.0-canary-20251008-6acbc1c"
47
47
  consumerProguardFiles("proguard-rules.pro")
48
48
  }
49
49
  testOptions {
@@ -0,0 +1,135 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package expo.modules
9
+
10
+ import android.content.Context
11
+ import com.facebook.react.bridge.ReadableArray
12
+ import com.facebook.react.bridge.UiThreadUtil
13
+ import com.facebook.react.common.SurfaceDelegate
14
+ import com.facebook.react.common.SurfaceDelegateFactory
15
+ import com.facebook.react.devsupport.DevSupportManagerBase
16
+ import com.facebook.react.devsupport.ReactInstanceDevHelper
17
+ import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
18
+ import com.facebook.react.devsupport.interfaces.DevLoadingViewManager
19
+ import com.facebook.react.devsupport.interfaces.DevSupportManager
20
+ import com.facebook.react.devsupport.interfaces.PausedInDebuggerOverlayManager
21
+ import com.facebook.react.devsupport.interfaces.RedBoxHandler
22
+ import com.facebook.react.packagerconnection.RequestHandler
23
+ import expo.modules.logbox.ExpoLogBoxSurfaceDelegate
24
+ import com.facebook.react.devsupport.StackTraceHelper.convertJavaStackTrace
25
+ import com.facebook.react.devsupport.StackTraceHelper.convertJsStackTrace
26
+ import com.facebook.react.devsupport.interfaces.StackFrame
27
+
28
+ /**
29
+ * An implementation of [DevSupportManager] that extends the functionality in
30
+ * [DevSupportManagerBase] with some additional, more flexible APIs for asynchronously loading the
31
+ * JS bundle.
32
+ *
33
+ * @constructor The primary constructor mirrors the same constructor we have for
34
+ * [BridgeDevSupportManager] and
35
+ * * is kept for backward compatibility.
36
+ */
37
+ internal open class ExpoBridgelessDevSupportManager(
38
+ applicationContext: Context,
39
+ reactInstanceManagerHelper: ReactInstanceDevHelper,
40
+ packagerPathForJSBundleName: String?,
41
+ enableOnCreate: Boolean,
42
+ redBoxHandler: RedBoxHandler?,
43
+ devBundleDownloadListener: DevBundleDownloadListener?,
44
+ minNumShakes: Int,
45
+ customPackagerCommandHandlers: Map<String, RequestHandler>?,
46
+ surfaceDelegateFactory: SurfaceDelegateFactory?,
47
+ devLoadingViewManager: DevLoadingViewManager?,
48
+ pausedInDebuggerOverlayManager: PausedInDebuggerOverlayManager?
49
+ ) :
50
+ DevSupportManagerBase(
51
+ applicationContext,
52
+ reactInstanceManagerHelper,
53
+ packagerPathForJSBundleName,
54
+ enableOnCreate,
55
+ redBoxHandler,
56
+ devBundleDownloadListener,
57
+ minNumShakes,
58
+ customPackagerCommandHandlers,
59
+ surfaceDelegateFactory,
60
+ devLoadingViewManager,
61
+ pausedInDebuggerOverlayManager) {
62
+
63
+ override val uniqueTag: String
64
+ get() = "Bridgeless"
65
+
66
+ override fun handleReloadJS() {
67
+ UiThreadUtil.assertOnUiThread()
68
+ // dismiss redbox if exists
69
+ hideRedboxDialog()
70
+ reactInstanceDevHelper.reload("BridgelessDevSupportManager.handleReloadJS()")
71
+ }
72
+ }
73
+
74
+ internal class ExpoDevSupportManagerWithLogBoxOverride(
75
+ applicationContext: Context,
76
+ reactInstanceManagerHelper: ReactInstanceDevHelper,
77
+ packagerPathForJSBundleName: String?,
78
+ enableOnCreate: Boolean,
79
+ redBoxHandler: RedBoxHandler?,
80
+ devBundleDownloadListener: DevBundleDownloadListener?,
81
+ minNumShakes: Int,
82
+ customPackagerCommandHandlers: Map<String, RequestHandler>?,
83
+ surfaceDelegateFactory: SurfaceDelegateFactory?,
84
+ devLoadingViewManager: DevLoadingViewManager?,
85
+ pausedInDebuggerOverlayManager: PausedInDebuggerOverlayManager?
86
+ ) :
87
+ ExpoBridgelessDevSupportManager(
88
+ applicationContext,
89
+ reactInstanceManagerHelper,
90
+ packagerPathForJSBundleName,
91
+ enableOnCreate,
92
+ redBoxHandler,
93
+ devBundleDownloadListener,
94
+ minNumShakes,
95
+ customPackagerCommandHandlers,
96
+ surfaceDelegateFactory,
97
+ devLoadingViewManager,
98
+ pausedInDebuggerOverlayManager) {
99
+
100
+ private var redBoxSurfaceDelegate: SurfaceDelegate? = null
101
+
102
+ override fun hideRedboxDialog() {
103
+ redBoxSurfaceDelegate?.hide()
104
+ }
105
+
106
+ override fun showNewJavaError(message: String?, e: Throwable) {
107
+ showNewError(message, convertJavaStackTrace(e))
108
+ }
109
+
110
+ override fun showNewJSError(message: String?, details: ReadableArray?, errorCookie: Int) {
111
+ showNewError(message, convertJsStackTrace(details))
112
+ }
113
+
114
+ private fun showNewError(message: String?, stack: Array<StackFrame>) {
115
+ UiThreadUtil.runOnUiThread {
116
+ lastErrorTitle = message
117
+ lastErrorStack = stack
118
+
119
+ if (redBoxSurfaceDelegate == null) {
120
+ this.redBoxSurfaceDelegate =
121
+ createSurfaceDelegate("RedBox")
122
+ ?: ExpoLogBoxSurfaceDelegate(this@ExpoDevSupportManagerWithLogBoxOverride).apply {
123
+ createContentView("RedBox")
124
+ }
125
+ }
126
+
127
+ if (redBoxSurfaceDelegate?.isShowing() == true) {
128
+ // Sometimes errors cause multiple errors to be thrown in JS in quick succession. Only
129
+ // show the first and most actionable one.
130
+ return@runOnUiThread
131
+ }
132
+ redBoxSurfaceDelegate?.show()
133
+ }
134
+ }
135
+ }
@@ -0,0 +1,145 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package expo.modules
9
+
10
+ import android.content.Context
11
+ import com.facebook.react.common.SurfaceDelegateFactory
12
+ import com.facebook.react.common.build.ReactBuildConfig
13
+ import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener
14
+ import com.facebook.react.devsupport.interfaces.DevLoadingViewManager
15
+ import com.facebook.react.devsupport.interfaces.DevSupportManager
16
+ import com.facebook.react.devsupport.interfaces.PausedInDebuggerOverlayManager
17
+ import com.facebook.react.devsupport.interfaces.RedBoxHandler
18
+ import com.facebook.react.packagerconnection.RequestHandler
19
+ import java.lang.StringBuilder
20
+ import com.facebook.react.devsupport.DevSupportManagerFactory
21
+ import com.facebook.react.devsupport.ReactInstanceDevHelper
22
+ import com.facebook.react.devsupport.ReleaseDevSupportManager
23
+
24
+ /**
25
+ * A simple factory that creates instances of [DevSupportManager] implementations. Uses reflection
26
+ * to create BridgeDevSupportManager if it exists. This allows ProGuard to strip that class and its
27
+ * dependencies in release builds. If the class isn't found, [PerftestDevSupportManager] is returned
28
+ * instead.
29
+ */
30
+ internal class ExpoDefaultDevSupportManagerFactory : DevSupportManagerFactory {
31
+
32
+ override fun create(
33
+ applicationContext: Context,
34
+ reactInstanceManagerHelper: ReactInstanceDevHelper,
35
+ packagerPathForJSBundleName: String?,
36
+ enableOnCreate: Boolean,
37
+ redBoxHandler: RedBoxHandler?,
38
+ devBundleDownloadListener: DevBundleDownloadListener?,
39
+ minNumShakes: Int,
40
+ customPackagerCommandHandlers: Map<String, RequestHandler>?,
41
+ surfaceDelegateFactory: SurfaceDelegateFactory?,
42
+ devLoadingViewManager: DevLoadingViewManager?,
43
+ pausedInDebuggerOverlayManager: PausedInDebuggerOverlayManager?
44
+ ): DevSupportManager {
45
+ return if (!enableOnCreate) {
46
+ ReleaseDevSupportManager()
47
+ } else
48
+ try {
49
+ // Developer support is enabled, we now must choose whether to return a DevSupportManager,
50
+ // or a more lean profiling-only PerftestDevSupportManager. We make the choice by first
51
+ // trying to return the full support DevSupportManager and if it fails, then just
52
+ // return PerftestDevSupportManager.
53
+
54
+ // ProGuard is surprisingly smart in this case and will keep a class if it detects a call
55
+ // to
56
+ // Class.forName() with a static string. So instead we generate a quasi-dynamic string to
57
+ // confuse it.
58
+ val className =
59
+ StringBuilder(DEVSUPPORT_IMPL_PACKAGE)
60
+ .append(".")
61
+ .append(DEVSUPPORT_IMPL_CLASS)
62
+ .toString()
63
+ val devSupportManagerClass = Class.forName(className)
64
+ val constructor =
65
+ devSupportManagerClass.getConstructor(
66
+ Context::class.java,
67
+ ReactInstanceDevHelper::class.java,
68
+ String::class.java,
69
+ Boolean::class.javaPrimitiveType,
70
+ RedBoxHandler::class.java,
71
+ DevBundleDownloadListener::class.java,
72
+ Int::class.javaPrimitiveType,
73
+ MutableMap::class.java,
74
+ SurfaceDelegateFactory::class.java,
75
+ DevLoadingViewManager::class.java,
76
+ PausedInDebuggerOverlayManager::class.java)
77
+ constructor.newInstance(
78
+ applicationContext,
79
+ reactInstanceManagerHelper,
80
+ packagerPathForJSBundleName,
81
+ true,
82
+ redBoxHandler,
83
+ devBundleDownloadListener,
84
+ minNumShakes,
85
+ customPackagerCommandHandlers,
86
+ surfaceDelegateFactory,
87
+ devLoadingViewManager,
88
+ pausedInDebuggerOverlayManager) as DevSupportManager
89
+ } catch (e: Exception) {
90
+ throw e
91
+ // Original implementation
92
+ // https://github.com/facebook/react-native/blob/50273758510a6d756494d05dc91055516c2a6aca/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.kt#L95
93
+
94
+ // React Native implementation fallback is PerftestDevSupportManager(applicationContext)
95
+ // but that's internal class we would have to vendor, so this impl re-throws.
96
+ // https://github.com/facebook/react-native/blob/50273758510a6d756494d05dc91055516c2a6aca/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PerftestDevSupportManager.kt#L17
97
+ }
98
+ }
99
+
100
+ override fun create(
101
+ applicationContext: Context,
102
+ reactInstanceManagerHelper: ReactInstanceDevHelper,
103
+ packagerPathForJSBundleName: String?,
104
+ enableOnCreate: Boolean,
105
+ redBoxHandler: RedBoxHandler?,
106
+ devBundleDownloadListener: DevBundleDownloadListener?,
107
+ minNumShakes: Int,
108
+ customPackagerCommandHandlers: Map<String, RequestHandler>?,
109
+ surfaceDelegateFactory: SurfaceDelegateFactory?,
110
+ devLoadingViewManager: DevLoadingViewManager?,
111
+ pausedInDebuggerOverlayManager: PausedInDebuggerOverlayManager?,
112
+ useDevSupport: Boolean
113
+ ): DevSupportManager =
114
+ if (ReactBuildConfig.UNSTABLE_ENABLE_FUSEBOX_RELEASE) {
115
+ // Should never happen as ExpoDefaultDevSupportManagerFactory is only used if useDevSupport = true
116
+ throw Error("ExpoDefaultDevSupportManagerFactory supports debug builds only. ReactBuildConfig.UNSTABLE_ENABLE_FUSEBOX_RELEASE is unsupported.")
117
+
118
+ // Original implementation
119
+ // https://github.com/facebook/react-native/blob/50273758510a6d756494d05dc91055516c2a6aca/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DefaultDevSupportManagerFactory.kt#L114
120
+
121
+ // React Native implementation uses PerftestDevSupportManager(applicationContext)
122
+ // but that's internal class we would have to vendor, so this impl re-throws.
123
+ // https://github.com/facebook/react-native/blob/50273758510a6d756494d05dc91055516c2a6aca/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/PerftestDevSupportManager.kt#L17
124
+ } else if (useDevSupport) {
125
+ ExpoDevSupportManagerWithLogBoxOverride(
126
+ applicationContext,
127
+ reactInstanceManagerHelper,
128
+ packagerPathForJSBundleName,
129
+ enableOnCreate,
130
+ redBoxHandler,
131
+ devBundleDownloadListener,
132
+ minNumShakes,
133
+ customPackagerCommandHandlers,
134
+ surfaceDelegateFactory,
135
+ devLoadingViewManager,
136
+ pausedInDebuggerOverlayManager)
137
+ } else {
138
+ ReleaseDevSupportManager()
139
+ }
140
+
141
+ private companion object {
142
+ private const val DEVSUPPORT_IMPL_PACKAGE = "com.facebook.react.devsupport"
143
+ private const val DEVSUPPORT_IMPL_CLASS = "BridgeDevSupportManager"
144
+ }
145
+ }
@@ -11,6 +11,7 @@ import com.facebook.react.ReactPackageTurboModuleManagerDelegate
11
11
  import com.facebook.react.bridge.JSBundleLoader
12
12
  import com.facebook.react.bridge.ReactContext
13
13
  import com.facebook.react.common.annotations.UnstableReactNativeAPI
14
+ import com.facebook.react.common.build.ReactBuildConfig
14
15
  import com.facebook.react.defaults.DefaultComponentsRegistry
15
16
  import com.facebook.react.defaults.DefaultTurboModuleManagerDelegate
16
17
  import com.facebook.react.fabric.ComponentFactory
@@ -19,7 +20,11 @@ import com.facebook.react.runtime.JSRuntimeFactory
19
20
  import com.facebook.react.runtime.ReactHostDelegate
20
21
  import com.facebook.react.runtime.ReactHostImpl
21
22
  import com.facebook.react.runtime.hermes.HermesInstance
23
+ import expo.modules.core.interfaces.ReactNativeHostHandler
24
+ import com.facebook.react.runtime.internal.bolts.Task
22
25
  import java.lang.ref.WeakReference
26
+ import java.util.concurrent.Executors
27
+ import expo.modules.logbox.ExpoLogBoxBuildConfig
23
28
 
24
29
  object ExpoReactHostFactory {
25
30
  private var reactHost: ReactHost? = null
@@ -27,10 +32,15 @@ object ExpoReactHostFactory {
27
32
  @UnstableReactNativeAPI
28
33
  private class ExpoReactHostDelegate(
29
34
  private val weakContext: WeakReference<Context>,
30
- private val reactNativeHostWrapper: ReactNativeHostWrapper,
35
+ private val packageList: List<ReactPackage>,
36
+ override val jsMainModulePath: String,
37
+ private val jsBundleAssetPath: String?,
38
+ private val jsBundleFilePath: String? = null,
39
+ private val useDevSupport: Boolean,
31
40
  override val bindingsInstaller: BindingsInstaller? = null,
32
41
  override val turboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder =
33
- DefaultTurboModuleManagerDelegate.Builder()
42
+ DefaultTurboModuleManagerDelegate.Builder(),
43
+ private val hostHandlers: List<ReactNativeHostHandler>
34
44
  ) : ReactHostDelegate {
35
45
 
36
46
  // Keeps this `_jsBundleLoader` backing property for DevLauncher to replace its internal value
@@ -42,33 +52,28 @@ object ExpoReactHostFactory {
42
52
  return backingJSBundleLoader
43
53
  }
44
54
  val context = weakContext.get() ?: throw IllegalStateException("Unable to get concrete Context")
45
- reactNativeHostWrapper.jsBundleFile?.let { jsBundleFile ->
55
+ jsBundleFilePath?.let { jsBundleFile ->
46
56
  if (jsBundleFile.startsWith("assets://")) {
47
57
  return JSBundleLoader.createAssetLoader(context, jsBundleFile, true)
48
58
  }
49
59
  return JSBundleLoader.createFileLoader(jsBundleFile)
50
60
  }
51
- val jsBundleAssetPath = reactNativeHostWrapper.bundleAssetName
61
+
52
62
  return JSBundleLoader.createAssetLoader(context, "assets://$jsBundleAssetPath", true)
53
63
  }
54
64
 
55
- override val jsMainModulePath: String
56
- get() = reactNativeHostWrapper.jsMainModuleName
57
-
58
65
  override val jsRuntimeFactory: JSRuntimeFactory
59
66
  get() = HermesInstance()
60
67
 
61
68
  override val reactPackages: List<ReactPackage>
62
- get() = reactNativeHostWrapper.packages
69
+ get() = packageList
63
70
 
64
71
  override fun handleInstanceException(error: Exception) {
65
- val handlers = reactNativeHostWrapper.reactNativeHostHandlers
66
- if (handlers.isEmpty()) {
72
+ if (hostHandlers.isEmpty()) {
67
73
  throw error
68
74
  }
69
- val useDeveloperSupport = reactNativeHostWrapper.useDeveloperSupport
70
- handlers.forEach { handler ->
71
- handler.onReactInstanceException(useDeveloperSupport, error)
75
+ hostHandlers.forEach { handler ->
76
+ handler.onReactInstanceException(useDevSupport, error)
72
77
  }
73
78
  }
74
79
  }
@@ -84,7 +89,6 @@ object ExpoReactHostFactory {
84
89
  }
85
90
  if (reactHost == null) {
86
91
  val useDeveloperSupport = reactNativeHost.useDeveloperSupport
87
- val reactHostDelegate = ExpoReactHostDelegate(WeakReference(context), reactNativeHost)
88
92
  val componentFactory = ComponentFactory()
89
93
  DefaultComponentsRegistry.register(componentFactory)
90
94
 
@@ -92,23 +96,105 @@ object ExpoReactHostFactory {
92
96
  handler.onWillCreateReactInstance(useDeveloperSupport)
93
97
  }
94
98
 
99
+ val reactHostDelegate = ExpoReactHostDelegate(
100
+ WeakReference(context),
101
+ reactNativeHost.packages,
102
+ reactNativeHost.jsMainModuleName,
103
+ reactNativeHost.bundleAssetName,
104
+ reactNativeHost.jsBundleFile,
105
+ reactNativeHost.useDeveloperSupport,
106
+ hostHandlers = reactNativeHost.reactNativeHostHandlers
107
+ )
108
+
109
+ val reactHostImpl = when {
110
+ ExpoLogBoxBuildConfig.UNSTABLE_IS_ENABLED && useDeveloperSupport -> ReactHostImpl(
111
+ context,
112
+ reactHostDelegate,
113
+ componentFactory,
114
+ Executors.newSingleThreadExecutor(),
115
+ Task.UI_THREAD_EXECUTOR,
116
+ allowPackagerServerAccess = true,
117
+ useDevSupport = true,
118
+ devSupportManagerFactory = ExpoDefaultDevSupportManagerFactory(),
119
+ )
120
+ else -> ReactHostImpl(
121
+ context,
122
+ reactHostDelegate,
123
+ componentFactory,
124
+ true,
125
+ useDeveloperSupport
126
+ )
127
+ }
128
+
129
+ reactNativeHost.reactNativeHostHandlers.forEach { handler ->
130
+ handler.onDidCreateDevSupportManager(reactHostImpl.devSupportManager)
131
+ }
132
+
133
+
134
+
135
+ reactHostImpl.addReactInstanceEventListener(object : ReactInstanceEventListener {
136
+ override fun onReactContextInitialized(context: ReactContext) {
137
+ reactNativeHost.reactNativeHostHandlers.forEach { handler ->
138
+ handler.onDidCreateReactInstance(useDeveloperSupport, context)
139
+ }
140
+ }
141
+ })
142
+
143
+ reactHost = reactHostImpl
144
+ }
145
+ return reactHost as ReactHost
146
+ }
147
+
148
+ @OptIn(UnstableReactNativeAPI::class)
149
+ @JvmStatic
150
+ fun getDefaultReactHost(
151
+ context: Context,
152
+ packageList: List<ReactPackage>,
153
+ jsMainModulePath: String = ".expo/.virtual-metro-entry",
154
+ jsBundleAssetPath: String = "index.android.bundle",
155
+ jsBundleFilePath: String? = null,
156
+ jsRuntimeFactory: JSRuntimeFactory? = null,
157
+ useDevSupport: Boolean = ReactBuildConfig.DEBUG,
158
+ bindingsInstaller: BindingsInstaller? = null
159
+ ): ReactHost {
160
+ if (reactHost == null) {
161
+ val hostHandlers = ExpoModulesPackage.packageList
162
+ .flatMap { it.createReactNativeHostHandlers(context) }
163
+
164
+ val reactHostDelegate = ExpoReactHostDelegate(
165
+ WeakReference(context),
166
+ packageList,
167
+ jsMainModulePath,
168
+ jsBundleAssetPath,
169
+ jsBundleFilePath,
170
+ useDevSupport,
171
+ bindingsInstaller,
172
+ hostHandlers = hostHandlers
173
+ )
174
+ val componentFactory = ComponentFactory()
175
+ DefaultComponentsRegistry.register(componentFactory)
176
+
177
+ hostHandlers.forEach { handler ->
178
+ handler.onWillCreateReactInstance(useDevSupport)
179
+ }
180
+
95
181
  val reactHostImpl =
96
182
  ReactHostImpl(
97
183
  context,
98
184
  reactHostDelegate,
99
185
  componentFactory,
100
186
  true,
101
- useDeveloperSupport
187
+ useDevSupport
102
188
  )
103
189
 
104
- reactNativeHost.reactNativeHostHandlers.forEach { handler ->
190
+ hostHandlers.forEach { handler ->
105
191
  handler.onDidCreateDevSupportManager(reactHostImpl.devSupportManager)
106
192
  }
107
193
 
108
194
  reactHostImpl.addReactInstanceEventListener(object : ReactInstanceEventListener {
109
195
  override fun onReactContextInitialized(context: ReactContext) {
110
- reactNativeHost.reactNativeHostHandlers.forEach { handler ->
111
- handler.onDidCreateReactInstance(useDeveloperSupport, context)
196
+ hostHandlers.forEach { handler ->
197
+ handler.onDidCreateReactInstance(useDevSupport, context)
112
198
  }
113
199
  }
114
200
  })
@@ -7,7 +7,6 @@ import com.facebook.react.ReactActivity
7
7
  import com.facebook.react.ReactActivityDelegate
8
8
  import com.facebook.react.ReactApplication
9
9
  import com.facebook.react.ReactHost
10
- import com.facebook.react.ReactNativeHost
11
10
  import com.facebook.react.ReactRootView
12
11
  import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
13
12
  import com.facebook.react.defaults.DefaultReactActivityDelegate
@@ -253,8 +252,6 @@ internal class MockApplication : Application(), ReactApplication {
253
252
  currentActivity = activity
254
253
  }
255
254
 
256
- override val reactNativeHost: ReactNativeHost = mockk<ReactNativeHost>(relaxed = true)
257
-
258
255
  override val reactHost: ReactHost by lazy {
259
256
  mockk<ReactHost>(relaxed = true)
260
257
  .also {
@@ -1,17 +1,17 @@
1
1
  type LogLevel = 'trace' | 'info' | 'warn' | 'error' | 'log' | 'group' | 'groupCollapsed' | 'groupEnd' | 'debug';
2
- export type HMRClientNativeInterface = {
2
+ /**
3
+ * HMR Client that receives from the server HMR updates and propagates them
4
+ * runtime to reflects those changes.
5
+ */
6
+ declare const HMRClient: {
3
7
  enable(): void;
4
8
  disable(): void;
5
9
  registerBundle(requestUrl: string): void;
6
10
  log(level: LogLevel, data: any[]): void;
7
- setup(props: {
11
+ setup({ isEnabled }: {
8
12
  isEnabled: boolean;
9
13
  }): void;
14
+ _onMetroError(data: unknown): void;
10
15
  };
11
- /**
12
- * HMR Client that receives from the server HMR updates and propagates them
13
- * runtime to reflects those changes.
14
- */
15
- declare const HMRClient: HMRClientNativeInterface;
16
16
  export default HMRClient;
17
17
  //# sourceMappingURL=hmr.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../../src/async-require/hmr.ts"],"names":[],"mappings":"AA4CA,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,OAAO,GACP,KAAK,GACL,OAAO,GACP,gBAAgB,GAChB,UAAU,GACV,OAAO,CAAC;AAEZ,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;IAChB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACxC,KAAK,CAAC,KAAK,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CAC5C,CAAC;AAMF;;;GAGG;AACH,QAAA,MAAM,SAAS,EAAE,wBAsMhB,CAAC;AAuEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"hmr.d.ts","sourceRoot":"","sources":["../../src/async-require/hmr.ts"],"names":[],"mappings":"AAqCA,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,OAAO,GACP,KAAK,GACL,OAAO,GACP,gBAAgB,GAChB,UAAU,GACV,OAAO,CAAC;AAMZ;;;GAGG;AACH,QAAA,MAAM,SAAS;;;+BAyCc,MAAM;eAMtB,QAAQ,QAAQ,GAAG,EAAE;yBAsCX;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE;wBAoGvB,OAAO;CAkC5B,CAAC;AA6DF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { DOMProps } from './dom.types';
2
+ export interface DOMPropsInternal extends DOMProps {
3
+ /**
4
+ * Allows dynamically redirecting a component to a different source, for example prebuilt version.
5
+ * @internal
6
+ */
7
+ sourceOverride?: {
8
+ uri: string;
9
+ };
10
+ }
11
+ //# sourceMappingURL=dom-internal.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-internal.types.d.ts","sourceRoot":"","sources":["../../src/dom/dom-internal.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAChD;;;OAGG;IACH,cAAc,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CAClC"}
@@ -1,3 +1,4 @@
1
1
  export { default as WebView } from './webview-wrapper';
2
+ export * from './dom-internal.types';
2
3
  export declare const registerDOMComponent: undefined | typeof import('./dom-entry').registerDOMComponent;
3
4
  //# sourceMappingURL=internal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/dom/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAGvD,eAAO,MAAM,oBAAoB,EAAE,SAAS,GAAG,cAAc,aAAa,EAAE,oBACjE,CAAC"}
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/dom/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEvD,cAAc,sBAAsB,CAAC;AAGrC,eAAO,MAAM,oBAAoB,EAAE,SAAS,GAAG,cAAc,aAAa,EAAE,oBACjE,CAAC"}
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import type { DOMProps } from './dom.types';
3
2
  import ExpoDomWebView from './webview/ExpoDOMWebView';
4
3
  import RNWebView from './webview/RNWebView';
4
+ import { DOMPropsInternal } from './dom-internal.types';
5
5
  type RawWebViewProps = React.ComponentProps<Exclude<typeof ExpoDomWebView, undefined>> & React.ComponentProps<Exclude<typeof RNWebView, undefined>>;
6
6
  interface Props {
7
7
  children?: any;
8
- dom?: DOMProps;
8
+ dom?: DOMPropsInternal;
9
9
  filePath: string;
10
10
  ref: React.Ref<object>;
11
11
  [propName: string]: unknown;
@@ -1 +1 @@
1
- {"version":3,"file":"webview-wrapper.d.ts","sourceRoot":"","sources":["../../src/dom/webview-wrapper.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAiB,QAAQ,EAA4B,MAAM,aAAa,CAAC;AAUrF,OAAO,cAAc,MAAM,0BAA0B,CAAC;AACtD,OAAO,SAAS,MAAM,qBAAqB,CAAC;AAG5C,KAAK,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,cAAc,EAAE,SAAS,CAAC,CAAC,GACpF,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAE7D,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,QAAA,MAAM,UAAU,mFAgMd,CAAC;AAiBH,wBAAgB,cAAc,CAC5B,iBAAiB,EAAE,OAAO,GACzB,KAAK,CAAC,yBAAyB,CAAC,eAAe,CAAC,CASlD;AAED,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"webview-wrapper.d.ts","sourceRoot":"","sources":["../../src/dom/webview-wrapper.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAc1B,OAAO,cAAc,MAAM,0BAA0B,CAAC;AACtD,OAAO,SAAS,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,KAAK,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,cAAc,EAAE,SAAS,CAAC,CAAC,GACpF,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAE7D,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,QAAA,MAAM,UAAU,mFAkMd,CAAC;AAiBH,wBAAgB,cAAc,CAC5B,iBAAiB,EAAE,OAAO,GACzB,KAAK,CAAC,yBAAyB,CAAC,eAAe,CAAC,CASlD;AAED,eAAe,UAAU,CAAC"}
@@ -1,8 +1,8 @@
1
1
  {
2
- "@expo/fingerprint": "0.15.2-canary-20250930-9dc59d3",
3
- "@expo/metro-runtime": "6.1.3-canary-20250930-9dc59d3",
2
+ "@expo/fingerprint": "0.15.2-canary-20251008-6acbc1c",
3
+ "@expo/metro-runtime": "6.1.3-canary-20251008-6acbc1c",
4
4
  "@expo/vector-icons": "^15.0.2",
5
- "@expo/ui": "0.2.0-canary-20250930-9dc59d3",
5
+ "@expo/ui": "0.2.0-canary-20251008-6acbc1c",
6
6
  "@react-native-async-storage/async-storage": "2.2.0",
7
7
  "@react-native-community/datetimepicker": "8.4.4",
8
8
  "@react-native-masked-view/masked-view": "0.3.2",
@@ -12,88 +12,88 @@
12
12
  "@react-native-picker/picker": "2.11.2",
13
13
  "@react-native-segmented-control/segmented-control": "2.5.7",
14
14
  "@stripe/stripe-react-native": "0.50.3",
15
- "eslint-config-expo": "10.0.1-canary-20250930-9dc59d3",
15
+ "eslint-config-expo": "10.0.1-canary-20251008-6acbc1c",
16
16
  "expo-analytics-amplitude": "~11.3.0",
17
17
  "expo-app-auth": "~11.1.0",
18
18
  "expo-app-loader-provider": "~8.0.0",
19
- "expo-apple-authentication": "8.0.8-canary-20250930-9dc59d3",
20
- "expo-application": "7.0.8-canary-20250930-9dc59d3",
21
- "expo-asset": "12.0.10-canary-20250930-9dc59d3",
22
- "expo-audio": "1.0.14-canary-20250930-9dc59d3",
23
- "expo-auth-session": "7.0.9-canary-20250930-9dc59d3",
24
- "expo-av": "16.0.8-canary-20250930-9dc59d3",
25
- "expo-background-fetch": "14.0.8-canary-20250930-9dc59d3",
26
- "expo-background-task": "1.1.0-canary-20250930-9dc59d3",
27
- "expo-battery": "10.0.8-canary-20250930-9dc59d3",
28
- "expo-blur": "15.0.8-canary-20250930-9dc59d3",
29
- "expo-brightness": "14.0.8-canary-20250930-9dc59d3",
30
- "expo-build-properties": "1.0.10-canary-20250930-9dc59d3",
31
- "expo-calendar": "15.0.8-canary-20250930-9dc59d3",
32
- "expo-camera": "17.0.9-canary-20250930-9dc59d3",
33
- "expo-cellular": "8.0.8-canary-20250930-9dc59d3",
34
- "expo-checkbox": "5.0.8-canary-20250930-9dc59d3",
35
- "expo-clipboard": "8.0.8-canary-20250930-9dc59d3",
36
- "expo-constants": "18.0.10-canary-20250930-9dc59d3",
37
- "expo-contacts": "15.0.9-canary-20250930-9dc59d3",
38
- "expo-crypto": "15.0.8-canary-20250930-9dc59d3",
39
- "expo-dev-client": "6.0.13-canary-20250930-9dc59d3",
40
- "expo-device": "8.1.0-canary-20250930-9dc59d3",
41
- "expo-document-picker": "14.0.8-canary-20250930-9dc59d3",
42
- "expo-file-system": "19.1.0-canary-20250930-9dc59d3",
43
- "expo-font": "14.0.9-canary-20250930-9dc59d3",
44
- "expo-gl": "16.0.8-canary-20250930-9dc59d3",
45
- "expo-glass-effect": "0.1.5-canary-20250930-9dc59d3",
19
+ "expo-apple-authentication": "8.0.8-canary-20251008-6acbc1c",
20
+ "expo-application": "7.0.8-canary-20251008-6acbc1c",
21
+ "expo-asset": "12.0.10-canary-20251008-6acbc1c",
22
+ "expo-audio": "1.1.0-canary-20251008-6acbc1c",
23
+ "expo-auth-session": "7.0.9-canary-20251008-6acbc1c",
24
+ "expo-av": "16.0.8-canary-20251008-6acbc1c",
25
+ "expo-background-fetch": "14.0.8-canary-20251008-6acbc1c",
26
+ "expo-background-task": "1.0.9-canary-20251008-6acbc1c",
27
+ "expo-battery": "10.0.8-canary-20251008-6acbc1c",
28
+ "expo-blur": "15.0.8-canary-20251008-6acbc1c",
29
+ "expo-brightness": "14.0.8-canary-20251008-6acbc1c",
30
+ "expo-build-properties": "1.0.10-canary-20251008-6acbc1c",
31
+ "expo-calendar": "15.0.8-canary-20251008-6acbc1c",
32
+ "expo-camera": "17.0.9-canary-20251008-6acbc1c",
33
+ "expo-cellular": "8.0.8-canary-20251008-6acbc1c",
34
+ "expo-checkbox": "5.0.8-canary-20251008-6acbc1c",
35
+ "expo-clipboard": "8.0.8-canary-20251008-6acbc1c",
36
+ "expo-constants": "18.0.10-canary-20251008-6acbc1c",
37
+ "expo-contacts": "15.0.10-canary-20251008-6acbc1c",
38
+ "expo-crypto": "15.0.8-canary-20251008-6acbc1c",
39
+ "expo-dev-client": "6.0.14-canary-20251008-6acbc1c",
40
+ "expo-device": "8.0.10-canary-20251008-6acbc1c",
41
+ "expo-document-picker": "14.0.8-canary-20251008-6acbc1c",
42
+ "expo-file-system": "19.0.17-canary-20251008-6acbc1c",
43
+ "expo-font": "14.0.9-canary-20251008-6acbc1c",
44
+ "expo-gl": "16.0.8-canary-20251008-6acbc1c",
45
+ "expo-glass-effect": "0.1.5-canary-20251008-6acbc1c",
46
46
  "expo-google-app-auth": "~8.3.0",
47
- "expo-haptics": "15.0.8-canary-20250930-9dc59d3",
48
- "expo-image": "3.1.0-canary-20250930-9dc59d3",
49
- "expo-image-loader": "6.0.1-canary-20250930-9dc59d3",
50
- "expo-image-manipulator": "14.0.8-canary-20250930-9dc59d3",
51
- "expo-image-picker": "17.0.9-canary-20250930-9dc59d3",
52
- "expo-intent-launcher": "13.0.8-canary-20250930-9dc59d3",
53
- "expo-insights": "0.10.8-canary-20250930-9dc59d3",
54
- "expo-keep-awake": "15.0.8-canary-20250930-9dc59d3",
55
- "expo-linear-gradient": "15.0.8-canary-20250930-9dc59d3",
56
- "expo-linking": "8.0.9-canary-20250930-9dc59d3",
57
- "expo-local-authentication": "17.0.8-canary-20250930-9dc59d3",
58
- "expo-localization": "17.0.8-canary-20250930-9dc59d3",
59
- "expo-location": "19.0.8-canary-20250930-9dc59d3",
60
- "expo-mail-composer": "15.0.8-canary-20250930-9dc59d3",
61
- "expo-manifests": "1.0.9-canary-20250930-9dc59d3",
62
- "expo-maps": "0.12.8-canary-20250930-9dc59d3",
63
- "expo-media-library": "18.3.0-canary-20250930-9dc59d3",
64
- "expo-mesh-gradient": "0.4.8-canary-20250930-9dc59d3",
65
- "expo-module-template": "11.0.15-canary-20250930-9dc59d3",
66
- "expo-modules-core": "3.1.0-canary-20250930-9dc59d3",
67
- "expo-navigation-bar": "5.0.9-canary-20250930-9dc59d3",
68
- "expo-network": "8.0.8-canary-20250930-9dc59d3",
69
- "expo-notifications": "1.0.0-canary-20250930-9dc59d3",
70
- "expo-print": "15.0.8-canary-20250930-9dc59d3",
71
- "expo-live-photo": "1.0.8-canary-20250930-9dc59d3",
72
- "expo-router": "6.1.0-canary-20250930-9dc59d3",
73
- "expo-screen-capture": "8.0.9-canary-20250930-9dc59d3",
74
- "expo-screen-orientation": "9.0.8-canary-20250930-9dc59d3",
75
- "expo-secure-store": "15.0.8-canary-20250930-9dc59d3",
76
- "expo-sensors": "15.0.8-canary-20250930-9dc59d3",
77
- "expo-sharing": "14.0.8-canary-20250930-9dc59d3",
78
- "expo-sms": "14.0.8-canary-20250930-9dc59d3",
79
- "expo-speech": "14.0.8-canary-20250930-9dc59d3",
80
- "expo-splash-screen": "31.0.11-canary-20250930-9dc59d3",
81
- "expo-sqlite": "16.0.9-canary-20250930-9dc59d3",
82
- "expo-status-bar": "3.0.9-canary-20250930-9dc59d3",
83
- "expo-store-review": "9.0.8-canary-20250930-9dc59d3",
84
- "expo-symbols": "1.0.8-canary-20250930-9dc59d3",
85
- "expo-system-ui": "6.0.8-canary-20250930-9dc59d3",
86
- "expo-task-manager": "14.0.8-canary-20250930-9dc59d3",
87
- "expo-tracking-transparency": "6.0.8-canary-20250930-9dc59d3",
88
- "expo-updates": "29.1.0-canary-20250930-9dc59d3",
89
- "expo-video-thumbnails": "10.0.8-canary-20250930-9dc59d3",
90
- "expo-video": "3.0.12-canary-20250930-9dc59d3",
91
- "expo-web-browser": "15.0.8-canary-20250930-9dc59d3",
92
- "jest-expo": "55.0.0-canary-20250930-9dc59d3",
47
+ "expo-haptics": "15.0.8-canary-20251008-6acbc1c",
48
+ "expo-image": "3.1.0-canary-20251008-6acbc1c",
49
+ "expo-image-loader": "6.0.1-canary-20251008-6acbc1c",
50
+ "expo-image-manipulator": "14.0.8-canary-20251008-6acbc1c",
51
+ "expo-image-picker": "17.0.9-canary-20251008-6acbc1c",
52
+ "expo-intent-launcher": "13.0.8-canary-20251008-6acbc1c",
53
+ "expo-insights": "0.10.8-canary-20251008-6acbc1c",
54
+ "expo-keep-awake": "15.0.8-canary-20251008-6acbc1c",
55
+ "expo-linear-gradient": "15.0.8-canary-20251008-6acbc1c",
56
+ "expo-linking": "8.0.9-canary-20251008-6acbc1c",
57
+ "expo-local-authentication": "17.0.8-canary-20251008-6acbc1c",
58
+ "expo-localization": "17.0.8-canary-20251008-6acbc1c",
59
+ "expo-location": "19.0.8-canary-20251008-6acbc1c",
60
+ "expo-mail-composer": "15.0.8-canary-20251008-6acbc1c",
61
+ "expo-manifests": "1.0.9-canary-20251008-6acbc1c",
62
+ "expo-maps": "0.12.9-canary-20251008-6acbc1c",
63
+ "expo-media-library": "18.3.0-canary-20251008-6acbc1c",
64
+ "expo-mesh-gradient": "0.4.8-canary-20251008-6acbc1c",
65
+ "expo-module-template": "11.0.16-canary-20251008-6acbc1c",
66
+ "expo-modules-core": "3.1.0-canary-20251008-6acbc1c",
67
+ "expo-navigation-bar": "5.0.9-canary-20251008-6acbc1c",
68
+ "expo-network": "8.0.8-canary-20251008-6acbc1c",
69
+ "expo-notifications": "1.0.0-canary-20251008-6acbc1c",
70
+ "expo-print": "15.0.8-canary-20251008-6acbc1c",
71
+ "expo-live-photo": "1.0.8-canary-20251008-6acbc1c",
72
+ "expo-router": "6.1.0-canary-20251008-6acbc1c",
73
+ "expo-screen-capture": "8.0.9-canary-20251008-6acbc1c",
74
+ "expo-screen-orientation": "9.0.8-canary-20251008-6acbc1c",
75
+ "expo-secure-store": "15.0.8-canary-20251008-6acbc1c",
76
+ "expo-sensors": "15.0.8-canary-20251008-6acbc1c",
77
+ "expo-sharing": "14.0.8-canary-20251008-6acbc1c",
78
+ "expo-sms": "14.0.8-canary-20251008-6acbc1c",
79
+ "expo-speech": "14.0.8-canary-20251008-6acbc1c",
80
+ "expo-splash-screen": "31.0.11-canary-20251008-6acbc1c",
81
+ "expo-sqlite": "16.0.9-canary-20251008-6acbc1c",
82
+ "expo-status-bar": "3.0.9-canary-20251008-6acbc1c",
83
+ "expo-store-review": "9.0.9-canary-20251008-6acbc1c",
84
+ "expo-symbols": "1.1.0-canary-20251008-6acbc1c",
85
+ "expo-system-ui": "6.0.8-canary-20251008-6acbc1c",
86
+ "expo-task-manager": "14.0.8-canary-20251008-6acbc1c",
87
+ "expo-tracking-transparency": "6.0.8-canary-20251008-6acbc1c",
88
+ "expo-updates": "29.1.0-canary-20251008-6acbc1c",
89
+ "expo-video-thumbnails": "10.0.8-canary-20251008-6acbc1c",
90
+ "expo-video": "3.0.12-canary-20251008-6acbc1c",
91
+ "expo-web-browser": "15.0.9-canary-20251008-6acbc1c",
92
+ "jest-expo": "55.0.0-canary-20251008-6acbc1c",
93
93
  "lottie-react-native": "~7.3.1",
94
94
  "react": "19.1.1",
95
95
  "react-dom": "19.1.1",
96
- "react-native": "0.82.0-rc.4",
96
+ "react-native": "0.82.0-rc.5",
97
97
  "react-native-web": "~0.21.0",
98
98
  "react-native-gesture-handler": "~2.28.0",
99
99
  "react-native-get-random-values": "~1.11.0",
@@ -108,7 +108,7 @@
108
108
  "react-native-view-shot": "4.0.3",
109
109
  "react-native-webview": "13.15.0",
110
110
  "sentry-expo": "~7.0.0",
111
- "unimodules-app-loader": "6.0.8-canary-20250930-9dc59d3",
111
+ "unimodules-app-loader": "6.0.8-canary-20251008-6acbc1c",
112
112
  "unimodules-image-loader-interface": "~6.1.0",
113
113
  "@shopify/react-native-skia": "2.2.12",
114
114
  "@shopify/flash-list": "2.0.2",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo",
3
- "version": "55.0.0-canary-20250930-9dc59d3",
3
+ "version": "55.0.0-canary-20251008-6acbc1c",
4
4
  "description": "The Expo SDK",
5
5
  "main": "src/Expo.ts",
6
6
  "module": "src/Expo.ts",
@@ -75,23 +75,24 @@
75
75
  "homepage": "https://github.com/expo/expo/tree/main/packages/expo",
76
76
  "dependencies": {
77
77
  "@babel/runtime": "^7.20.0",
78
- "@expo/cli": "54.1.0-canary-20250930-9dc59d3",
79
- "@expo/config": "12.0.10-canary-20250930-9dc59d3",
80
- "@expo/config-plugins": "54.1.0-canary-20250930-9dc59d3",
81
- "@expo/devtools": "0.1.8-canary-20250930-9dc59d3",
82
- "@expo/fingerprint": "0.15.2-canary-20250930-9dc59d3",
78
+ "@expo/cli": "54.1.0-canary-20251008-6acbc1c",
79
+ "@expo/config": "12.0.11-canary-20251008-6acbc1c",
80
+ "@expo/config-plugins": "54.0.3-canary-20251008-6acbc1c",
81
+ "@expo/devtools": "0.1.8-canary-20251008-6acbc1c",
82
+ "@expo/fingerprint": "0.15.2-canary-20251008-6acbc1c",
83
83
  "@expo/metro": "~54.0.0",
84
- "@expo/metro-config": "54.0.6-canary-20250930-9dc59d3",
84
+ "@expo/metro-config": "54.0.7-canary-20251008-6acbc1c",
85
85
  "@expo/vector-icons": "^15.0.2",
86
+ "@expo/log-box": "0.0.13-canary-20251008-6acbc1c",
86
87
  "@ungap/structured-clone": "^1.3.0",
87
- "babel-preset-expo": "54.0.4-canary-20250930-9dc59d3",
88
- "expo-asset": "12.0.10-canary-20250930-9dc59d3",
89
- "expo-constants": "18.0.10-canary-20250930-9dc59d3",
90
- "expo-file-system": "19.1.0-canary-20250930-9dc59d3",
91
- "expo-font": "14.0.9-canary-20250930-9dc59d3",
92
- "expo-keep-awake": "15.0.8-canary-20250930-9dc59d3",
93
- "expo-modules-autolinking": "3.1.0-canary-20250930-9dc59d3",
94
- "expo-modules-core": "3.1.0-canary-20250930-9dc59d3",
88
+ "babel-preset-expo": "54.0.4-canary-20251008-6acbc1c",
89
+ "expo-asset": "12.0.10-canary-20251008-6acbc1c",
90
+ "expo-constants": "18.0.10-canary-20251008-6acbc1c",
91
+ "expo-file-system": "19.0.17-canary-20251008-6acbc1c",
92
+ "expo-font": "14.0.9-canary-20251008-6acbc1c",
93
+ "expo-keep-awake": "15.0.8-canary-20251008-6acbc1c",
94
+ "expo-modules-autolinking": "3.1.0-canary-20251008-6acbc1c",
95
+ "expo-modules-core": "3.1.0-canary-20251008-6acbc1c",
95
96
  "pretty-format": "^29.7.0",
96
97
  "react-refresh": "^0.14.2",
97
98
  "whatwg-url-without-unicode": "8.0.0-3"
@@ -100,15 +101,15 @@
100
101
  "@types/node": "^22.14.0",
101
102
  "@types/react": "~19.1.10",
102
103
  "@types/react-test-renderer": "~19.1.0",
103
- "expo-module-scripts": "5.0.8-canary-20250930-9dc59d3",
104
+ "expo-module-scripts": "5.0.8-canary-20251008-6acbc1c",
104
105
  "react": "19.1.1",
105
106
  "react-dom": "19.1.1",
106
- "react-native": "0.82.0-rc.4",
107
+ "react-native": "0.82.0-rc.5",
107
108
  "web-streams-polyfill": "^3.3.2"
108
109
  },
109
110
  "peerDependencies": {
110
- "@expo/dom-webview": "0.2.8-canary-20250930-9dc59d3",
111
- "@expo/metro-runtime": "6.1.3-canary-20250930-9dc59d3",
111
+ "@expo/dom-webview": "0.2.8-canary-20251008-6acbc1c",
112
+ "@expo/metro-runtime": "6.1.3-canary-20251008-6acbc1c",
112
113
  "react": "*",
113
114
  "react-native": "*",
114
115
  "react-native-webview": "*"
@@ -8,6 +8,7 @@
8
8
  * Based on this but with web support:
9
9
  * https://github.com/facebook/react-native/blob/086714b02b0fb838dee5a66c5bcefe73b53cf3df/Libraries/Utilities/HMRClient.js
10
10
  */
11
+ import { parseWebHmrBuildErrors, type MetroBuildError } from '@expo/log-box/utils';
11
12
  import MetroHMRClient from '@expo/metro/metro-runtime/modules/HMRClient';
12
13
  import prettyFormat, { plugins } from 'pretty-format';
13
14
  import { DeviceEventEmitter } from 'react-native';
@@ -28,17 +29,9 @@ const pendingEntryPoints: string[] = [];
28
29
  // @ts-expect-error: Account for multiple versions of pretty-format inside of a monorepo.
29
30
  const prettyFormatFunc = typeof prettyFormat === 'function' ? prettyFormat : prettyFormat.default;
30
31
 
31
- type HMRClientType = {
32
- send: (msg: string) => void;
33
- isEnabled: () => boolean;
34
- disable: () => void;
35
- enable: () => void;
36
- hasPendingUpdates: () => boolean;
37
- };
38
-
39
- let hmrClient: HMRClientType | null = null;
32
+ let hmrClient: MetroHMRClient | null = null;
40
33
  let hmrUnavailableReason: string | null = null;
41
- let currentCompileErrorMessage: string | null = null;
34
+ const buildErrorQueue = new Set<MetroBuildError>();
42
35
  let didConnect: boolean = false;
43
36
  const pendingLogs: [LogLevel, any[]][] = [];
44
37
 
@@ -53,14 +46,6 @@ type LogLevel =
53
46
  | 'groupEnd'
54
47
  | 'debug';
55
48
 
56
- export type HMRClientNativeInterface = {
57
- enable(): void;
58
- disable(): void;
59
- registerBundle(requestUrl: string): void;
60
- log(level: LogLevel, data: any[]): void;
61
- setup(props: { isEnabled: boolean }): void;
62
- };
63
-
64
49
  function assert(foo: any, msg: string): asserts foo {
65
50
  if (!foo) throw new Error(msg);
66
51
  }
@@ -69,7 +54,7 @@ function assert(foo: any, msg: string): asserts foo {
69
54
  * HMR Client that receives from the server HMR updates and propagates them
70
55
  * runtime to reflects those changes.
71
56
  */
72
- const HMRClient: HMRClientNativeInterface = {
57
+ const HMRClient = {
73
58
  enable() {
74
59
  if (hmrUnavailableReason !== null) {
75
60
  // If HMR became unavailable while you weren't using it,
@@ -181,10 +166,10 @@ const HMRClient: HMRClientNativeInterface = {
181
166
  );
182
167
 
183
168
  client.on('connection-error', (e: Error) => {
184
- let error = `Cannot connect to Metro.
169
+ let error = `Cannot connect to Expo CLI.
185
170
 
186
171
  Try the following to fix the issue:
187
- - Ensure the Metro dev server is running and available on the same network as this device`;
172
+ - Ensure the Expo dev server is running and available on the same network as this device`;
188
173
  error += `
189
174
 
190
175
  URL: ${window.location.host}
@@ -195,7 +180,7 @@ const HMRClient: HMRClientNativeInterface = {
195
180
  });
196
181
 
197
182
  client.on('update-start', ({ isInitialUpdate }: { isInitialUpdate?: boolean }) => {
198
- currentCompileErrorMessage = null;
183
+ buildErrorQueue.clear();
199
184
  didConnect = true;
200
185
 
201
186
  if (client.isEnabled() && !isInitialUpdate) {
@@ -205,10 +190,11 @@ const HMRClient: HMRClientNativeInterface = {
205
190
 
206
191
  client.on('update', ({ isInitialUpdate }: { isInitialUpdate?: boolean }) => {
207
192
  if (client.isEnabled() && !isInitialUpdate) {
208
- dismissRedbox();
193
+ // dismissRedbox();
209
194
  // @ts-expect-error
210
195
  globalThis.__expo_dev_resetErrors?.();
211
196
  // LogBox.clearAllLogs();
197
+ // dismissGlobalErrorOverlay();
212
198
  }
213
199
  });
214
200
 
@@ -216,22 +202,7 @@ const HMRClient: HMRClientNativeInterface = {
216
202
  hideLoading();
217
203
  });
218
204
 
219
- client.on('error', (data: { type: string; message: string }) => {
220
- hideLoading();
221
-
222
- if (data.type === 'GraphNotFoundError') {
223
- client.close();
224
- setHMRUnavailableReason('Metro has restarted since the last edit. Reload to reconnect.');
225
- } else if (data.type === 'RevisionNotFoundError') {
226
- client.close();
227
- setHMRUnavailableReason('Metro and the client are out of sync. Reload to reconnect.');
228
- } else {
229
- currentCompileErrorMessage = `${data.type} ${data.message}`;
230
- if (client.isEnabled()) {
231
- showCompileError();
232
- }
233
- }
234
- });
205
+ client.on('error', (data) => this._onMetroError(data));
235
206
 
236
207
  client.on('close', (closeEvent: { code: number; reason: string }) => {
237
208
  hideLoading();
@@ -242,19 +213,19 @@ const HMRClient: HMRClientNativeInterface = {
242
213
  closeEvent == null ||
243
214
  closeEvent.code === 1000 ||
244
215
  closeEvent.code === 1005 ||
216
+ closeEvent.code === 1006 ||
245
217
  closeEvent.code == null;
246
218
 
247
219
  setHMRUnavailableReason(
248
220
  `${
249
221
  isNormalOrUnsetCloseReason
250
- ? 'Disconnected from Metro.'
251
- : `Disconnected from Metro (${closeEvent.code}: "${closeEvent.reason}").`
222
+ ? 'Disconnected from Expo CLI.'
223
+ : `Disconnected from Expo CLI (${closeEvent.code}: "${closeEvent.reason}").`
252
224
  }
253
225
 
254
226
  To reconnect:
255
- - Ensure that Metro is running and available on the same network
256
- - Reload this app (will trigger further help if Metro cannot be connected to)
257
- `
227
+ - Start the dev server with: npx expo
228
+ - Reload the ${process.env.EXPO_OS === 'web' ? 'page' : 'app'}`
258
229
  );
259
230
  });
260
231
 
@@ -267,6 +238,41 @@ To reconnect:
267
238
  registerBundleEntryPoints(hmrClient);
268
239
  flushEarlyLogs();
269
240
  },
241
+
242
+ _onMetroError(data: unknown) {
243
+ if (!hmrClient) {
244
+ return;
245
+ }
246
+
247
+ assert(typeof data === 'object' && data != null, 'Expected data to be an object');
248
+
249
+ hideLoading();
250
+
251
+ if ('type' in data) {
252
+ if (data.type === 'GraphNotFoundError') {
253
+ hmrClient.close();
254
+ setHMRUnavailableReason('Expo CLI has restarted since the last edit. Reload to reconnect.');
255
+ return;
256
+ } else if (data.type === 'RevisionNotFoundError') {
257
+ hmrClient.close();
258
+ setHMRUnavailableReason(
259
+ `Expo CLI and the ${process.env.EXPO_OS} client are out of sync. Reload to reconnect.`
260
+ );
261
+ return;
262
+ }
263
+ }
264
+
265
+ // Fallback for resolution errors which don't return a type
266
+ // https://github.com/facebook/metro/blob/a3fac645dc377f78bd4182ca0ca73629b2707d5b/packages/metro/src/lib/formatBundlingError.js#L65-L73
267
+ // https://github.com/facebook/metro/pull/1487
268
+ const error = parseWebHmrBuildErrors(data);
269
+
270
+ buildErrorQueue.add(error);
271
+
272
+ if (hmrClient.isEnabled()) {
273
+ showCompileError();
274
+ }
275
+ },
270
276
  };
271
277
 
272
278
  function setHMRUnavailableReason(reason: string) {
@@ -286,7 +292,7 @@ function setHMRUnavailableReason(reason: string) {
286
292
  }
287
293
  }
288
294
 
289
- function registerBundleEntryPoints(client: HMRClientType | null) {
295
+ function registerBundleEntryPoints(client: MetroHMRClient | null) {
290
296
  if (hmrUnavailableReason != null) {
291
297
  // "Bundle Splitting – Metro disconnected"
292
298
  window.location.reload();
@@ -314,27 +320,17 @@ function flushEarlyLogs() {
314
320
  }
315
321
  }
316
322
 
317
- function dismissRedbox() {
318
- // TODO(EvanBacon): Error overlay for web.
319
- }
320
-
321
323
  function showCompileError() {
322
- if (currentCompileErrorMessage === null) {
324
+ if (buildErrorQueue.size === 0) {
323
325
  return;
324
326
  }
325
327
 
326
328
  // Even if there is already a redbox, syntax errors are more important.
327
329
  // Otherwise you risk seeing a stale runtime error while a syntax error is more recent.
328
- dismissRedbox();
329
-
330
- const message = currentCompileErrorMessage;
331
- currentCompileErrorMessage = null;
330
+ // dismissGlobalErrorOverlay();
332
331
 
333
- const error = new Error(message);
334
- // Symbolicating compile errors is wasted effort
335
- // because the stack trace is meaningless:
336
- // @ts-expect-error
337
- error.preventSymbolication = true;
332
+ const error = buildErrorQueue.values().next().value;
333
+ buildErrorQueue.clear();
338
334
  throw error;
339
335
  }
340
336
 
@@ -1,12 +1,12 @@
1
1
  // Entry file for a DOM Component.
2
2
  import '@expo/metro-runtime';
3
3
 
4
- import { withErrorOverlay } from '@expo/metro-runtime/error-overlay';
5
4
  import React from 'react';
6
5
 
7
6
  import { JSONValue } from './dom.types';
8
7
  import { addEventListener, getActionsObject } from './marshal';
9
8
  import registerRootComponent from '../launch/registerRootComponent';
9
+ import { useLogBox } from '@expo/log-box';
10
10
 
11
11
  interface MarshalledProps {
12
12
  name: string[];
@@ -102,12 +102,12 @@ export function registerDOMComponent(AppModule: any) {
102
102
  }
103
103
 
104
104
  try {
105
+ if (process.env.NODE_ENV !== 'production') {
106
+ useLogBox();
107
+ }
108
+
105
109
  React.startTransition(() => {
106
- if (process.env.NODE_ENV !== 'production') {
107
- registerRootComponent(withErrorOverlay(DOMComponentRoot));
108
- } else {
109
- registerRootComponent(DOMComponentRoot);
110
- }
110
+ registerRootComponent(DOMComponentRoot);
111
111
  });
112
112
  } catch (e) {
113
113
  const error = convertError(e);
@@ -0,0 +1,9 @@
1
+ import type { DOMProps } from './dom.types';
2
+
3
+ export interface DOMPropsInternal extends DOMProps {
4
+ /**
5
+ * Allows dynamically redirecting a component to a different source, for example prebuilt version.
6
+ * @internal
7
+ */
8
+ sourceOverride?: { uri: string };
9
+ }
@@ -1,5 +1,7 @@
1
1
  export { default as WebView } from './webview-wrapper';
2
2
 
3
+ export * from './dom-internal.types';
4
+
3
5
  // Skip all dom-only functions to give 'undefined is not a function' errors.
4
6
  export const registerDOMComponent: undefined | typeof import('./dom-entry').registerDOMComponent =
5
7
  undefined;
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { AppState } from 'react-native';
4
4
 
5
5
  import { getBaseURL } from './base';
6
- import type { BridgeMessage, DOMProps, WebViewProps, WebViewRef } from './dom.types';
6
+ import type { BridgeMessage, WebViewProps, WebViewRef } from './dom.types';
7
7
  import { _emitGlobalEvent } from './global-events';
8
8
  import {
9
9
  getInjectBodySizeObserverScript,
@@ -16,13 +16,14 @@ import {
16
16
  import ExpoDomWebView from './webview/ExpoDOMWebView';
17
17
  import RNWebView from './webview/RNWebView';
18
18
  import { useDebugZeroHeight } from './webview/useDebugZeroHeight';
19
+ import { DOMPropsInternal } from './dom-internal.types';
19
20
 
20
21
  type RawWebViewProps = React.ComponentProps<Exclude<typeof ExpoDomWebView, undefined>> &
21
22
  React.ComponentProps<Exclude<typeof RNWebView, undefined>>;
22
23
 
23
24
  interface Props {
24
25
  children?: any;
25
- dom?: DOMProps;
26
+ dom?: DOMPropsInternal;
26
27
  filePath: string;
27
28
  ref: React.Ref<object>;
28
29
  [propName: string]: unknown;
@@ -30,6 +31,8 @@ interface Props {
30
31
 
31
32
  const RawWebView = React.forwardRef<object, Props>((props, ref) => {
32
33
  const { children, dom, filePath, ref: _ref, ...marshalProps } = props as Props;
34
+ const { sourceOverride, ...domProps } = dom || {};
35
+
33
36
  if (__DEV__) {
34
37
  if (children !== undefined) {
35
38
  throw new Error(
@@ -66,7 +69,7 @@ const RawWebView = React.forwardRef<object, Props>((props, ref) => {
66
69
  const webView = resolveWebView(dom?.useExpoDOMWebView ?? false);
67
70
  const webviewRef = React.useRef<WebViewRef>(null);
68
71
  const domImperativeHandlePropsRef = React.useRef<string[]>([]);
69
- const source = { uri: `${getBaseURL()}/${filePath}` };
72
+ const source = sourceOverride ?? { uri: `${getBaseURL()}/${filePath}` };
70
73
  const [containerStyle, setContainerStyle] = React.useState<WebViewProps['containerStyle']>(null);
71
74
 
72
75
  const { debugZeroHeightStyle, debugOnLayout } = useDebugZeroHeight(dom);
@@ -129,7 +132,7 @@ const RawWebView = React.forwardRef<object, Props>((props, ref) => {
129
132
  subscription.remove();
130
133
  });
131
134
  },
132
- ...dom,
135
+ ...domProps,
133
136
  containerStyle: [containerStyle, debugZeroHeightStyle, dom?.containerStyle],
134
137
  onLayout: __DEV__ ? debugOnLayout : dom?.onLayout,
135
138
  injectedJavaScriptBeforeContentLoaded: [
package/template.tgz CHANGED
Binary file