expo 54.0.20 → 54.0.22

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.
@@ -32,7 +32,7 @@ buildscript {
32
32
  def reactNativeVersion = project.extensions.getByType(ExpoModuleExtension).reactNativeVersion
33
33
 
34
34
  group = 'host.exp.exponent'
35
- version = '54.0.20'
35
+ version = '54.0.22'
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 "54.0.20"
46
+ versionName "54.0.22"
47
47
  consumerProguardFiles("proguard-rules.pro")
48
48
  }
49
49
  testOptions {
@@ -12,7 +12,6 @@ import android.os.Bundle
12
12
  import android.util.Log
13
13
  import android.view.KeyEvent
14
14
  import android.view.ViewGroup
15
- import android.view.Window
16
15
  import androidx.annotation.VisibleForTesting
17
16
  import androidx.collection.ArrayMap
18
17
  import androidx.lifecycle.lifecycleScope
@@ -156,11 +155,6 @@ class ReactActivityDelegateWrapper(
156
155
  activity.window.colorMode = ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT
157
156
  }
158
157
 
159
- val edgeToEdgeEnabled = invokeWindowUtilKtMethod<Boolean>("isEdgeToEdgeFeatureFlagOn") ?: true
160
- if (edgeToEdgeEnabled) {
161
- invokeWindowUtilKtMethod<Unit>("enableEdgeToEdge", Pair(Window::class.java, plainActivity.window))
162
- }
163
-
164
158
  val launchOptions = composeLaunchOptions()
165
159
  val reactDelegate: ReactDelegate
166
160
  if (ReactNativeFeatureFlags.enableBridgelessArchitecture) {
@@ -432,25 +426,6 @@ class ReactActivityDelegateWrapper(
432
426
  return method!!.invoke(delegate, *args) as T
433
427
  }
434
428
 
435
- private inline fun <reified T> invokeWindowUtilKtMethod(
436
- methodName: String,
437
- vararg args: Pair<Class<*>, Any?>
438
- ): T? {
439
- val windowUtilClassName = "com.facebook.react.views.view.WindowUtilKt"
440
-
441
- return runCatching {
442
- val windowUtilKtClass = Class.forName(windowUtilClassName)
443
- val parameterTypes = args.map { it.first }.toTypedArray()
444
- val parameterValues = args.map { it.second }.toTypedArray()
445
- val method = windowUtilKtClass.getDeclaredMethod(methodName, *parameterTypes)
446
-
447
- method.isAccessible = true
448
- method.invoke(null, *parameterValues) as? T
449
- }.onFailure {
450
- Log.e(TAG, "Failed to invoke '$methodName' on $windowUtilClassName", it)
451
- }.getOrNull()
452
- }
453
-
454
429
  private suspend fun loadAppImpl(appKey: String?, supportsDelayLoad: Boolean) {
455
430
  // Give modules a chance to wrap the ReactRootView in a container ViewGroup. If some module
456
431
  // wants to do this, we override the functionality of `loadApp` and call `setContentView` with
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright © 2025 650 Industries.
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * This is added as `asyncRequireModulePath` in `@expo/metro-config`
9
+ * Fork of https://github.com/facebook/metro/blob/b8e9e64f1de97a67234e223f5ee21524b160e8a5/packages/metro-runtime/src/modules/asyncRequire.js#L1
10
+ * - Adds worker support.
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=asyncRequireModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncRequireModule.d.ts","sourceRoot":"","sources":["../../src/async-require/asyncRequireModule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG"}
@@ -1,5 +1,5 @@
1
1
  {
2
- "@expo/fingerprint": "~0.15.2",
2
+ "@expo/fingerprint": "~0.15.3",
3
3
  "@expo/metro-runtime": "~6.1.2",
4
4
  "@expo/vector-icons": "^15.0.3",
5
5
  "@expo/ui": "~0.2.0-beta.7",
@@ -19,7 +19,7 @@
19
19
  "expo-apple-authentication": "~8.0.7",
20
20
  "expo-application": "~7.0.7",
21
21
  "expo-asset": "~12.0.9",
22
- "expo-audio": "~1.0.13",
22
+ "expo-audio": "~1.0.14",
23
23
  "expo-auth-session": "~7.0.8",
24
24
  "expo-av": "~16.0.7",
25
25
  "expo-background-fetch": "~14.0.7",
@@ -29,7 +29,7 @@
29
29
  "expo-brightness": "~14.0.7",
30
30
  "expo-build-properties": "~1.0.9",
31
31
  "expo-calendar": "~15.0.7",
32
- "expo-camera": "~17.0.8",
32
+ "expo-camera": "~17.0.9",
33
33
  "expo-cellular": "~8.0.7",
34
34
  "expo-checkbox": "~5.0.7",
35
35
  "expo-clipboard": "~8.0.7",
@@ -42,7 +42,7 @@
42
42
  "expo-file-system": "~19.0.17",
43
43
  "expo-font": "~14.0.9",
44
44
  "expo-gl": "~16.0.7",
45
- "expo-glass-effect": "~0.1.4",
45
+ "expo-glass-effect": "~0.1.6",
46
46
  "expo-google-app-auth": "~8.3.0",
47
47
  "expo-haptics": "~15.0.7",
48
48
  "expo-image": "~3.0.10",
@@ -63,22 +63,23 @@
63
63
  "expo-media-library": "~18.2.0",
64
64
  "expo-mesh-gradient": "~0.4.7",
65
65
  "expo-module-template": "~11.0.16",
66
- "expo-modules-core": "~3.0.22",
66
+ "expo-modules-core": "~3.0.24",
67
67
  "expo-navigation-bar": "~5.0.9",
68
68
  "expo-network": "~8.0.7",
69
69
  "expo-notifications": "~0.32.12",
70
70
  "expo-print": "~15.0.7",
71
71
  "expo-live-photo": "~1.0.7",
72
- "expo-router": "~6.0.13",
72
+ "expo-router": "~6.0.14",
73
73
  "expo-screen-capture": "~8.0.8",
74
74
  "expo-screen-orientation": "~9.0.7",
75
75
  "expo-secure-store": "~15.0.7",
76
76
  "expo-sensors": "~15.0.7",
77
+ "expo-server": "~1.0.4",
77
78
  "expo-sharing": "~14.0.7",
78
79
  "expo-sms": "~14.0.7",
79
80
  "expo-speech": "~14.0.7",
80
81
  "expo-splash-screen": "~31.0.10",
81
- "expo-sqlite": "~16.0.8",
82
+ "expo-sqlite": "~16.0.9",
82
83
  "expo-status-bar": "~3.0.8",
83
84
  "expo-store-review": "~9.0.8",
84
85
  "expo-symbols": "~1.0.7",
@@ -87,8 +88,8 @@
87
88
  "expo-tracking-transparency": "~6.0.7",
88
89
  "expo-updates": "~29.0.12",
89
90
  "expo-video-thumbnails": "~10.0.7",
90
- "expo-video": "~3.0.11",
91
- "expo-web-browser": "~15.0.8",
91
+ "expo-video": "~3.0.13",
92
+ "expo-web-browser": "~15.0.9",
92
93
  "jest-expo": "~54.0.13",
93
94
  "lottie-react-native": "~7.3.1",
94
95
  "react": "19.1.0",
@@ -0,0 +1,2 @@
1
+ // WARN: Internal re-export, don't rely on this to be a public API
2
+ module.exports = require('../src/async-require/asyncRequireModule');
@@ -147,7 +147,15 @@ open class ExpoAppDelegate: NSObject, @preconcurrency ReactNativeFactoryProvider
147
147
  }
148
148
  #endif
149
149
 
150
- // TODO: - Responding to Environment Changes
150
+ // MARK: - Responding to Environment Changes
151
+
152
+ #if os(iOS) || os(tvOS)
153
+
154
+ open func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
155
+ ExpoAppDelegateSubscriberManager.applicationDidReceiveMemoryWarning(application)
156
+ }
157
+
158
+ #endif
151
159
 
152
160
  // TODO: - Managing App State Restoration
153
161
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo",
3
- "version": "54.0.20",
3
+ "version": "54.0.22",
4
4
  "description": "The Expo SDK",
5
5
  "main": "src/Expo.ts",
6
6
  "module": "src/Expo.ts",
@@ -75,13 +75,13 @@
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.0.13",
78
+ "@expo/cli": "54.0.15",
79
79
  "@expo/config": "~12.0.10",
80
80
  "@expo/config-plugins": "~54.0.2",
81
81
  "@expo/devtools": "0.1.7",
82
- "@expo/fingerprint": "0.15.2",
82
+ "@expo/fingerprint": "0.15.3",
83
83
  "@expo/metro": "~54.1.0",
84
- "@expo/metro-config": "54.0.7",
84
+ "@expo/metro-config": "54.0.8",
85
85
  "@expo/vector-icons": "^15.0.3",
86
86
  "@ungap/structured-clone": "^1.3.0",
87
87
  "babel-preset-expo": "~54.0.6",
@@ -90,8 +90,8 @@
90
90
  "expo-file-system": "~19.0.17",
91
91
  "expo-font": "~14.0.9",
92
92
  "expo-keep-awake": "~15.0.7",
93
- "expo-modules-autolinking": "3.0.19",
94
- "expo-modules-core": "3.0.22",
93
+ "expo-modules-autolinking": "3.0.20",
94
+ "expo-modules-core": "3.0.24",
95
95
  "pretty-format": "^29.7.0",
96
96
  "react-refresh": "^0.14.2",
97
97
  "whatwg-url-without-unicode": "8.0.0-3"
@@ -124,5 +124,5 @@
124
124
  "optional": true
125
125
  }
126
126
  },
127
- "gitHead": "f17f3b55004d10db40d4c5455498444ad032e173"
127
+ "gitHead": "1bba12a43e14a442f2cf1c73fe21968e0ef097c1"
128
128
  }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Copyright © 2025 650 Industries.
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ *
8
+ * This is added as `asyncRequireModulePath` in `@expo/metro-config`
9
+ * Fork of https://github.com/facebook/metro/blob/b8e9e64f1de97a67234e223f5ee21524b160e8a5/packages/metro-runtime/src/modules/asyncRequire.js#L1
10
+ * - Adds worker support.
11
+ */
12
+
13
+ type MetroRequire = {
14
+ (id: number): unknown;
15
+ importAll: <T>(id: number) => T;
16
+ };
17
+
18
+ type DependencyMapPaths = { [moduleID: number | string]: unknown } | null;
19
+
20
+ declare let __METRO_GLOBAL_PREFIX__: string;
21
+
22
+ function maybeLoadBundle(moduleID: number, paths: DependencyMapPaths): void | Promise<void> {
23
+ const loadBundle: (bundlePath: unknown) => Promise<void> = (global as any)[
24
+ `${__METRO_GLOBAL_PREFIX__}__loadBundleAsync`
25
+ ];
26
+
27
+ if (loadBundle != null) {
28
+ const stringModuleID = String(moduleID);
29
+ if (paths != null) {
30
+ const bundlePath = paths[stringModuleID];
31
+ if (bundlePath != null) {
32
+ // NOTE: Errors will be swallowed by asyncRequire.prefetch
33
+ return loadBundle(bundlePath);
34
+ }
35
+ }
36
+ }
37
+
38
+ return undefined;
39
+ }
40
+
41
+ function asyncRequireImpl<T>(moduleID: number, paths: DependencyMapPaths): Promise<T> | T {
42
+ const maybeLoadBundlePromise = maybeLoadBundle(moduleID, paths);
43
+ const importAll = () => (require as unknown as MetroRequire).importAll<T>(moduleID);
44
+
45
+ if (maybeLoadBundlePromise != null) {
46
+ return maybeLoadBundlePromise.then(importAll);
47
+ }
48
+
49
+ return importAll();
50
+ }
51
+
52
+ async function asyncRequire<T>(
53
+ moduleID: number,
54
+ paths: DependencyMapPaths,
55
+ moduleName?: string // unused
56
+ ): Promise<T> {
57
+ return asyncRequireImpl<T>(moduleID, paths);
58
+ }
59
+
60
+ // Synchronous version of asyncRequire, which can still return a promise
61
+ // if the module is split.
62
+ asyncRequire.unstable_importMaybeSync = function unstable_importMaybeSync<T>(
63
+ moduleID: number,
64
+ paths: DependencyMapPaths
65
+ ): Promise<T> | T {
66
+ return asyncRequireImpl(moduleID, paths);
67
+ };
68
+
69
+ asyncRequire.prefetch = function (
70
+ moduleID: number,
71
+ paths: DependencyMapPaths,
72
+ moduleName?: string // unused
73
+ ): void {
74
+ maybeLoadBundle(moduleID, paths)?.then(
75
+ () => {},
76
+ () => {}
77
+ );
78
+ };
79
+
80
+ asyncRequire.unstable_resolve = function unstable_resolve(
81
+ moduleID: number,
82
+ paths: DependencyMapPaths
83
+ ) {
84
+ if (!paths) {
85
+ throw new Error('Bundle splitting is required for Web Worker imports');
86
+ }
87
+ const id = paths[moduleID];
88
+ if (!id) {
89
+ throw new Error('Worker import is missing from split bundle paths: ' + id);
90
+ }
91
+ return id;
92
+ };
93
+
94
+ // TODO(@kitten): Missing metro type definitions
95
+ declare const module: any;
96
+
97
+ module.exports = asyncRequire;
@@ -27,8 +27,14 @@ describe('getBaseURL', () => {
27
27
  isEnabled: true,
28
28
  isEmbeddedLaunch: false,
29
29
  localAssets: {
30
+ '8d4e297c3b3e49a614248143d53e40ca':
31
+ 'file:///android_res/drawable-mdpi/node_modules_reactnavigation_elements_lib_module_assets_closeicon.png',
32
+ '4403c6117ec30c859bc95d70ce4a71d3':
33
+ 'file:///android_res/drawable-mdpi/node_modules_reactnavigation_elements_lib_module_assets_searchicon.png',
30
34
  '5d41402abc4b2a76b9719d911017c592':
31
35
  'file:///path/to/.expo-internal/5d41402abc4b2a76b9719d911017c592.png',
36
+ '1d1ea1496f9057eb392d5bbf3732a61b7':
37
+ 'file:///android_res/drawable/node_modules_exporouter_assets_error.png',
32
38
  },
33
39
  },
34
40
  },
@@ -45,8 +51,15 @@ describe('getBaseURL', () => {
45
51
  isEnabled: true,
46
52
  isEmbeddedLaunch: true,
47
53
  localAssets: {
54
+ '8d4e297c3b3e49a614248143d53e40ca':
55
+ 'file:///android_res/drawable-mdpi/node_modules_reactnavigation_elements_lib_module_assets_closeicon.png',
56
+ '4403c6117ec30c859bc95d70ce4a71d3':
57
+ 'file:///android_res/drawable-mdpi/node_modules_reactnavigation_elements_lib_module_assets_searchicon.png',
58
+
48
59
  '5d41402abc4b2a76b9719d911017c592':
49
60
  'file:///path/to/.expo-internal/5d41402abc4b2a76b9719d911017c592.png',
61
+ '1d1ea1496f9057eb392d5bbf3732a61b7':
62
+ 'file:///android_res/drawable/node_modules_exporouter_assets_error.png',
50
63
  },
51
64
  },
52
65
  },
package/src/dom/base.ts CHANGED
@@ -52,7 +52,10 @@ function getUpdatesBaseURL(): string | null {
52
52
  // If updates is installed and enabled, and we're not running from an embedded launch, we should serve the DOM Components from the `.expo-internal` directory
53
53
  if (shouldServeDomFromUpdates) {
54
54
  const localAssets = ExpoUpdates?.localAssets ?? {};
55
- const anyLocalAsset = Object.values(localAssets)[0];
55
+ const anyLocalAsset = Object.values(localAssets).find(
56
+ (asset) =>
57
+ !asset.startsWith('file:///android_res/') && !asset.startsWith('file:///android_asset/')
58
+ );
56
59
  if (anyLocalAsset) {
57
60
  // Try to get the `.expo-internal` directory from the first local asset
58
61
  return anyLocalAsset.slice(0, anyLocalAsset.lastIndexOf('/'));
package/template.tgz CHANGED
Binary file