expo-updates 1.0.0-canary-20250304-f08e984 → 1.0.0-canary-20250306-d9d3e02

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -28,6 +28,7 @@
28
28
  - Add update id headers to asset requests ([#34453](https://github.com/expo/expo/pull/34453) by [@gabrieldonadel](https://github.com/gabrieldonadel))
29
29
  - Drop `fs-extra` in favor of `fs`. ([#35036](https://github.com/expo/expo/pull/35036) by [@kitten](https://github.com/kitten))
30
30
  - Drop `fast-glob` in favor of `glob`. ([#35082](https://github.com/expo/expo/pull/35082) by [@kitten](https://github.com/kitten))
31
+ - Drop `fbemitter` in favor of custom emitter. ([#35317](https://github.com/expo/expo/pull/35317) by [@kitten](https://github.com/kitten))
31
32
 
32
33
  ## 0.27.1 - 2025-02-21
33
34
 
@@ -8,7 +8,6 @@ import com.facebook.react.bridge.ReactMarker.MarkerListener
8
8
  import com.facebook.react.bridge.ReactMarkerConstants
9
9
  import com.facebook.react.devsupport.ReleaseDevSupportManager
10
10
  import com.facebook.react.devsupport.interfaces.DevSupportManager
11
- import expo.modules.rncompatibility.IReactNativeFeatureFlagsProvider
12
11
  import expo.modules.updates.logging.UpdatesErrorCode
13
12
  import expo.modules.updates.logging.UpdatesLogger
14
13
  import java.lang.ref.WeakReference
@@ -28,7 +27,7 @@ import java.lang.ref.WeakReference
28
27
  */
29
28
  class ErrorRecovery(
30
29
  private val logger: UpdatesLogger,
31
- private val reactNativeFeatureFlagsProvider: IReactNativeFeatureFlagsProvider
30
+ private val enableBridgelessArchitecture: Boolean = true
32
31
  ) {
33
32
  internal val handlerThread = HandlerThread("expo-updates-error-recovery")
34
33
  internal lateinit var handler: Handler
@@ -98,7 +97,7 @@ class ErrorRecovery(
98
97
  }
99
98
 
100
99
  private fun registerErrorHandler(devSupportManager: DevSupportManager) {
101
- if (reactNativeFeatureFlagsProvider.enableBridgelessArchitecture) {
100
+ if (enableBridgelessArchitecture) {
102
101
  registerErrorHandlerImplBridgeless()
103
102
  } else {
104
103
  registerErrorHandlerImplBridge(devSupportManager)
@@ -131,7 +130,7 @@ class ErrorRecovery(
131
130
  }
132
131
 
133
132
  private fun unregisterErrorHandler() {
134
- if (reactNativeFeatureFlagsProvider.enableBridgelessArchitecture) {
133
+ if (enableBridgelessArchitecture) {
135
134
  unregisterErrorHandlerImplBridgeless()
136
135
  } else {
137
136
  unregisterErrorHandlerImplBridge()
@@ -65,7 +65,7 @@ class StartupProcedure(
65
65
 
66
66
  var emergencyLaunchException: Exception? = null
67
67
  private set
68
- private val errorRecovery = ErrorRecovery(logger, ReactNativeFeatureFlags)
68
+ private val errorRecovery = ErrorRecovery(logger, ReactNativeFeatureFlags.enableBridgelessArchitecture)
69
69
  private var remoteLoadStatus = ErrorRecoveryDelegate.RemoteLoadStatus.IDLE
70
70
 
71
71
  // TODO: move away from DatabaseHolder pattern to Handler thread
@@ -1,10 +1,13 @@
1
1
  import type { UpdatesNativeStateChangeEvent, UpdatesNativeStateMachineContext } from './Updates.types';
2
2
  export declare let latestContext: UpdatesNativeStateMachineContext;
3
+ interface UpdatesStateChangeSubscription {
4
+ remove(): void;
5
+ }
3
6
  /**
4
7
  * Add listener for state change events
5
8
  * @hidden
6
9
  */
7
- export declare const addUpdatesStateChangeListener: (listener: (event: UpdatesNativeStateChangeEvent) => void) => import("fbemitter").EventSubscription;
10
+ export declare const addUpdatesStateChangeListener: (listener: (event: UpdatesNativeStateChangeEvent) => void) => UpdatesStateChangeSubscription;
8
11
  /**
9
12
  * Allows JS test to emit a simulated native state change event (used in unit testing)
10
13
  * @hidden
@@ -15,4 +18,5 @@ export declare const emitTestStateChangeEvent: (event: UpdatesNativeStateChangeE
15
18
  * @hidden
16
19
  */
17
20
  export declare const resetLatestContext: () => void;
21
+ export {};
18
22
  //# sourceMappingURL=UpdatesEmitter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"UpdatesEmitter.d.ts","sourceRoot":"","sources":["../src/UpdatesEmitter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gCAAgC,EACjC,MAAM,iBAAiB,CAAC;AAEzB,eAAO,IAAI,aAAa,kCAAuE,CAAC;AAqBhG;;;GAGG;AACH,eAAO,MAAM,6BAA6B,qBACtB,6BAA6B,KAAK,IAAI,0CAGzD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,UAAW,6BAA6B,SAE5E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,YAE9B,CAAC"}
1
+ {"version":3,"file":"UpdatesEmitter.d.ts","sourceRoot":"","sources":["../src/UpdatesEmitter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gCAAgC,EACjC,MAAM,iBAAiB,CAAC;AAEzB,eAAO,IAAI,aAAa,kCAAuE,CAAC;AAIhG,UAAU,8BAA8B;IACtC,MAAM,IAAI,IAAI,CAAC;CAChB;AAmBD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,qBACtB,6BAA6B,KAAK,IAAI,KACvD,8BAOF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,UAAW,6BAA6B,SAE5E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,YAE9B,CAAC"}
@@ -1,8 +1,7 @@
1
- import { EventEmitter as JsEventEmitter } from 'fbemitter';
2
1
  import ExpoUpdatesModule from './ExpoUpdates';
3
2
  export let latestContext = transformNativeStateMachineContext(ExpoUpdatesModule.initialContext);
4
3
  ExpoUpdatesModule.addListener('Expo.nativeUpdatesStateChangeEvent', _handleNativeStateChangeEvent);
5
- const _jsEventEmitter = new JsEventEmitter();
4
+ const _updatesStateChangeListeners = new Set();
6
5
  // Reemits native state change events
7
6
  function _handleNativeStateChangeEvent(params) {
8
7
  const newParams = typeof params === 'string' ? JSON.parse(params) : { ...params };
@@ -13,14 +12,19 @@ function _handleNativeStateChangeEvent(params) {
13
12
  }
14
13
  newParams.context = transformedContext;
15
14
  latestContext = transformedContext;
16
- _jsEventEmitter.emit('Expo.updatesStateChangeEvent', newParams);
15
+ _updatesStateChangeListeners.forEach((listener) => listener(newParams));
17
16
  }
18
17
  /**
19
18
  * Add listener for state change events
20
19
  * @hidden
21
20
  */
22
21
  export const addUpdatesStateChangeListener = (listener) => {
23
- return _jsEventEmitter.addListener('Expo.updatesStateChangeEvent', listener);
22
+ _updatesStateChangeListeners.add(listener);
23
+ return {
24
+ remove() {
25
+ _updatesStateChangeListeners.delete(listener);
26
+ },
27
+ };
24
28
  };
25
29
  /**
26
30
  * Allows JS test to emit a simulated native state change event (used in unit testing)
@@ -1 +1 @@
1
- {"version":3,"file":"UpdatesEmitter.js","sourceRoot":"","sources":["../src/UpdatesEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3D,OAAO,iBAAiB,MAAM,eAAe,CAAC;AAM9C,MAAM,CAAC,IAAI,aAAa,GAAG,kCAAkC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAEhG,iBAAiB,CAAC,WAAW,CAAC,oCAAoC,EAAE,6BAA6B,CAAC,CAAC;AAEnG,MAAM,eAAe,GAAG,IAAI,cAAc,EAAE,CAAC;AAE7C,qCAAqC;AACrC,SAAS,6BAA6B,CAAC,MAAW;IAChD,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAClF,MAAM,kBAAkB,GAAG,kCAAkC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAEjF,wDAAwD;IACxD,IAAI,kBAAkB,CAAC,cAAc,IAAI,aAAa,CAAC,cAAc,EAAE;QACrE,OAAO;KACR;IAED,SAAS,CAAC,OAAO,GAAG,kBAAkB,CAAC;IACvC,aAAa,GAAG,kBAAkB,CAAC;IACnC,eAAe,CAAC,IAAI,CAAC,8BAA8B,EAAE,SAAS,CAAC,CAAC;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,QAAwD,EACxD,EAAE;IACF,OAAO,eAAe,CAAC,WAAW,CAAC,8BAA8B,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAoC,EAAE,EAAE;IAC/E,6BAA6B,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,EAAE;IACrC,aAAa,GAAG,kCAAkC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,SAAS,kCAAkC,CACzC,qBAKC;IAED,MAAM,aAAa,GAAG,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACnD,IAAI,aAAa,CAAC,oBAAoB,EAAE;QACtC,aAAa,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;QAC9E,OAAO,aAAa,CAAC,oBAAoB,CAAC;KAC3C;IACD,IAAI,aAAa,CAAC,wBAAwB,EAAE;QAC1C,aAAa,CAAC,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;QACtF,OAAO,aAAa,CAAC,wBAAwB,CAAC;KAC/C;IACD,IAAI,aAAa,CAAC,4BAA4B,EAAE;QAC9C,aAAa,CAAC,sBAAsB,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC;QAC5F,OAAO,aAAa,CAAC,4BAA4B,CAAC;KACnD;IACD,IAAI,aAAa,CAAC,cAAc,EAAE;QAChC,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAClE,OAAO,aAAa,CAAC,cAAc,CAAC;KACrC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import { EventEmitter as JsEventEmitter } from 'fbemitter';\n\nimport ExpoUpdatesModule from './ExpoUpdates';\nimport type {\n UpdatesNativeStateChangeEvent,\n UpdatesNativeStateMachineContext,\n} from './Updates.types';\n\nexport let latestContext = transformNativeStateMachineContext(ExpoUpdatesModule.initialContext);\n\nExpoUpdatesModule.addListener('Expo.nativeUpdatesStateChangeEvent', _handleNativeStateChangeEvent);\n\nconst _jsEventEmitter = new JsEventEmitter();\n\n// Reemits native state change events\nfunction _handleNativeStateChangeEvent(params: any) {\n const newParams = typeof params === 'string' ? JSON.parse(params) : { ...params };\n const transformedContext = transformNativeStateMachineContext(newParams.context);\n\n // only process state change events if they are in order\n if (transformedContext.sequenceNumber <= latestContext.sequenceNumber) {\n return;\n }\n\n newParams.context = transformedContext;\n latestContext = transformedContext;\n _jsEventEmitter.emit('Expo.updatesStateChangeEvent', newParams);\n}\n\n/**\n * Add listener for state change events\n * @hidden\n */\nexport const addUpdatesStateChangeListener = (\n listener: (event: UpdatesNativeStateChangeEvent) => void\n) => {\n return _jsEventEmitter.addListener('Expo.updatesStateChangeEvent', listener);\n};\n\n/**\n * Allows JS test to emit a simulated native state change event (used in unit testing)\n * @hidden\n */\nexport const emitTestStateChangeEvent = (event: UpdatesNativeStateChangeEvent) => {\n _handleNativeStateChangeEvent(event);\n};\n\n/**\n * Allows JS test to reset latest context (and sequence number)\n * @hidden\n */\nexport const resetLatestContext = () => {\n latestContext = transformNativeStateMachineContext(ExpoUpdatesModule.initialContext);\n};\n\nfunction transformNativeStateMachineContext(\n originalNativeContext: UpdatesNativeStateMachineContext & {\n latestManifestString?: string;\n downloadedManifestString?: string;\n lastCheckForUpdateTimeString?: string;\n rollbackString?: string;\n }\n): UpdatesNativeStateMachineContext {\n const nativeContext = { ...originalNativeContext };\n if (nativeContext.latestManifestString) {\n nativeContext.latestManifest = JSON.parse(nativeContext.latestManifestString);\n delete nativeContext.latestManifestString;\n }\n if (nativeContext.downloadedManifestString) {\n nativeContext.downloadedManifest = JSON.parse(nativeContext.downloadedManifestString);\n delete nativeContext.downloadedManifestString;\n }\n if (nativeContext.lastCheckForUpdateTimeString) {\n nativeContext.lastCheckForUpdateTime = new Date(nativeContext.lastCheckForUpdateTimeString);\n delete nativeContext.lastCheckForUpdateTimeString;\n }\n if (nativeContext.rollbackString) {\n nativeContext.rollback = JSON.parse(nativeContext.rollbackString);\n delete nativeContext.rollbackString;\n }\n return nativeContext;\n}\n"]}
1
+ {"version":3,"file":"UpdatesEmitter.js","sourceRoot":"","sources":["../src/UpdatesEmitter.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,eAAe,CAAC;AAM9C,MAAM,CAAC,IAAI,aAAa,GAAG,kCAAkC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;AAEhG,iBAAiB,CAAC,WAAW,CAAC,oCAAoC,EAAE,6BAA6B,CAAC,CAAC;AAMnG,MAAM,4BAA4B,GAAG,IAAI,GAAG,EAAkD,CAAC;AAE/F,qCAAqC;AACrC,SAAS,6BAA6B,CAAC,MAAW;IAChD,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC;IAClF,MAAM,kBAAkB,GAAG,kCAAkC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAEjF,wDAAwD;IACxD,IAAI,kBAAkB,CAAC,cAAc,IAAI,aAAa,CAAC,cAAc,EAAE;QACrE,OAAO;KACR;IAED,SAAS,CAAC,OAAO,GAAG,kBAAkB,CAAC;IACvC,aAAa,GAAG,kBAAkB,CAAC;IACnC,4BAA4B,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAC3C,QAAwD,EACxB,EAAE;IAClC,4BAA4B,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,OAAO;QACL,MAAM;YACJ,4BAA4B,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,KAAoC,EAAE,EAAE;IAC/E,6BAA6B,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,EAAE;IACrC,aAAa,GAAG,kCAAkC,CAAC,iBAAiB,CAAC,cAAc,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,SAAS,kCAAkC,CACzC,qBAKC;IAED,MAAM,aAAa,GAAG,EAAE,GAAG,qBAAqB,EAAE,CAAC;IACnD,IAAI,aAAa,CAAC,oBAAoB,EAAE;QACtC,aAAa,CAAC,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;QAC9E,OAAO,aAAa,CAAC,oBAAoB,CAAC;KAC3C;IACD,IAAI,aAAa,CAAC,wBAAwB,EAAE;QAC1C,aAAa,CAAC,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,wBAAwB,CAAC,CAAC;QACtF,OAAO,aAAa,CAAC,wBAAwB,CAAC;KAC/C;IACD,IAAI,aAAa,CAAC,4BAA4B,EAAE;QAC9C,aAAa,CAAC,sBAAsB,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,4BAA4B,CAAC,CAAC;QAC5F,OAAO,aAAa,CAAC,4BAA4B,CAAC;KACnD;IACD,IAAI,aAAa,CAAC,cAAc,EAAE;QAChC,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC;QAClE,OAAO,aAAa,CAAC,cAAc,CAAC;KACrC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import ExpoUpdatesModule from './ExpoUpdates';\nimport type {\n UpdatesNativeStateChangeEvent,\n UpdatesNativeStateMachineContext,\n} from './Updates.types';\n\nexport let latestContext = transformNativeStateMachineContext(ExpoUpdatesModule.initialContext);\n\nExpoUpdatesModule.addListener('Expo.nativeUpdatesStateChangeEvent', _handleNativeStateChangeEvent);\n\ninterface UpdatesStateChangeSubscription {\n remove(): void;\n}\n\nconst _updatesStateChangeListeners = new Set<(event: UpdatesNativeStateChangeEvent) => void>();\n\n// Reemits native state change events\nfunction _handleNativeStateChangeEvent(params: any) {\n const newParams = typeof params === 'string' ? JSON.parse(params) : { ...params };\n const transformedContext = transformNativeStateMachineContext(newParams.context);\n\n // only process state change events if they are in order\n if (transformedContext.sequenceNumber <= latestContext.sequenceNumber) {\n return;\n }\n\n newParams.context = transformedContext;\n latestContext = transformedContext;\n _updatesStateChangeListeners.forEach((listener) => listener(newParams));\n}\n\n/**\n * Add listener for state change events\n * @hidden\n */\nexport const addUpdatesStateChangeListener = (\n listener: (event: UpdatesNativeStateChangeEvent) => void\n): UpdatesStateChangeSubscription => {\n _updatesStateChangeListeners.add(listener);\n return {\n remove() {\n _updatesStateChangeListeners.delete(listener);\n },\n };\n};\n\n/**\n * Allows JS test to emit a simulated native state change event (used in unit testing)\n * @hidden\n */\nexport const emitTestStateChangeEvent = (event: UpdatesNativeStateChangeEvent) => {\n _handleNativeStateChangeEvent(event);\n};\n\n/**\n * Allows JS test to reset latest context (and sequence number)\n * @hidden\n */\nexport const resetLatestContext = () => {\n latestContext = transformNativeStateMachineContext(ExpoUpdatesModule.initialContext);\n};\n\nfunction transformNativeStateMachineContext(\n originalNativeContext: UpdatesNativeStateMachineContext & {\n latestManifestString?: string;\n downloadedManifestString?: string;\n lastCheckForUpdateTimeString?: string;\n rollbackString?: string;\n }\n): UpdatesNativeStateMachineContext {\n const nativeContext = { ...originalNativeContext };\n if (nativeContext.latestManifestString) {\n nativeContext.latestManifest = JSON.parse(nativeContext.latestManifestString);\n delete nativeContext.latestManifestString;\n }\n if (nativeContext.downloadedManifestString) {\n nativeContext.downloadedManifest = JSON.parse(nativeContext.downloadedManifestString);\n delete nativeContext.downloadedManifestString;\n }\n if (nativeContext.lastCheckForUpdateTimeString) {\n nativeContext.lastCheckForUpdateTime = new Date(nativeContext.lastCheckForUpdateTimeString);\n delete nativeContext.lastCheckForUpdateTimeString;\n }\n if (nativeContext.rollbackString) {\n nativeContext.rollback = JSON.parse(nativeContext.rollbackString);\n delete nativeContext.rollbackString;\n }\n return nativeContext;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-updates",
3
- "version": "1.0.0-canary-20250304-f08e984",
3
+ "version": "1.0.0-canary-20250306-d9d3e02",
4
4
  "description": "Fetches and manages remotely-hosted assets and updates to your app's JS bundle.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -39,16 +39,15 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@expo/code-signing-certificates": "0.0.5",
42
- "@expo/config": "11.0.0-canary-20250304-f08e984",
43
- "@expo/config-plugins": "9.1.0-canary-20250304-f08e984",
42
+ "@expo/config": "11.0.0-canary-20250306-d9d3e02",
43
+ "@expo/config-plugins": "9.1.0-canary-20250306-d9d3e02",
44
44
  "@expo/spawn-async": "^1.7.2",
45
45
  "arg": "4.1.0",
46
46
  "chalk": "^4.1.2",
47
- "expo-eas-client": "0.13.4-canary-20250304-f08e984",
48
- "expo-manifests": "0.15.8-canary-20250304-f08e984",
49
- "expo-structured-headers": "4.0.1-canary-20250304-f08e984",
50
- "expo-updates-interface": "1.0.1-canary-20250304-f08e984",
51
- "fbemitter": "^3.0.0",
47
+ "expo-eas-client": "0.13.4-canary-20250306-d9d3e02",
48
+ "expo-manifests": "0.15.8-canary-20250306-d9d3e02",
49
+ "expo-structured-headers": "4.0.1-canary-20250306-d9d3e02",
50
+ "expo-updates-interface": "1.0.1-canary-20250306-d9d3e02",
52
51
  "glob": "^10.4.2",
53
52
  "ignore": "^5.3.1",
54
53
  "resolve-from": "^5.0.0"
@@ -57,15 +56,15 @@
57
56
  "@types/jest": "^29.2.1",
58
57
  "@types/node": "^18.19.34",
59
58
  "@types/node-forge": "^1.0.0",
60
- "expo-module-scripts": "4.0.5-canary-20250304-f08e984",
59
+ "expo-module-scripts": "4.0.5-canary-20250306-d9d3e02",
61
60
  "express": "^4.21.1",
62
61
  "form-data": "^4.0.0",
63
62
  "memfs": "^3.2.0",
64
63
  "xstate": "^4.37.2"
65
64
  },
66
65
  "peerDependencies": {
67
- "expo": "53.0.0-canary-20250304-f08e984",
66
+ "expo": "53.0.0-canary-20250306-d9d3e02",
68
67
  "react": "*"
69
68
  },
70
- "gitHead": "f08e984ac18968d26ea7f7f34d11d29a0a97d518"
69
+ "gitHead": "d9d3e024d8742099c307754673f17117a20c1dea"
71
70
  }
@@ -1,5 +1,3 @@
1
- import { EventEmitter as JsEventEmitter } from 'fbemitter';
2
-
3
1
  import ExpoUpdatesModule from './ExpoUpdates';
4
2
  import type {
5
3
  UpdatesNativeStateChangeEvent,
@@ -10,7 +8,11 @@ export let latestContext = transformNativeStateMachineContext(ExpoUpdatesModule.
10
8
 
11
9
  ExpoUpdatesModule.addListener('Expo.nativeUpdatesStateChangeEvent', _handleNativeStateChangeEvent);
12
10
 
13
- const _jsEventEmitter = new JsEventEmitter();
11
+ interface UpdatesStateChangeSubscription {
12
+ remove(): void;
13
+ }
14
+
15
+ const _updatesStateChangeListeners = new Set<(event: UpdatesNativeStateChangeEvent) => void>();
14
16
 
15
17
  // Reemits native state change events
16
18
  function _handleNativeStateChangeEvent(params: any) {
@@ -24,7 +26,7 @@ function _handleNativeStateChangeEvent(params: any) {
24
26
 
25
27
  newParams.context = transformedContext;
26
28
  latestContext = transformedContext;
27
- _jsEventEmitter.emit('Expo.updatesStateChangeEvent', newParams);
29
+ _updatesStateChangeListeners.forEach((listener) => listener(newParams));
28
30
  }
29
31
 
30
32
  /**
@@ -33,8 +35,13 @@ function _handleNativeStateChangeEvent(params: any) {
33
35
  */
34
36
  export const addUpdatesStateChangeListener = (
35
37
  listener: (event: UpdatesNativeStateChangeEvent) => void
36
- ) => {
37
- return _jsEventEmitter.addListener('Expo.updatesStateChangeEvent', listener);
38
+ ): UpdatesStateChangeSubscription => {
39
+ _updatesStateChangeListeners.add(listener);
40
+ return {
41
+ remove() {
42
+ _updatesStateChangeListeners.delete(listener);
43
+ },
44
+ };
38
45
  };
39
46
 
40
47
  /**