@react-native-firebase/app 26.3.3 → 27.0.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 (283) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +10 -27
  3. package/RNFBApp.podspec +13 -5
  4. package/android/build.gradle +3 -0
  5. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleCollisionException.kt +29 -0
  6. package/android/src/main/java/io/invertase/firebase/common/RNFBHandleMap.kt +146 -0
  7. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.kt +156 -0
  8. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.kt +44 -0
  9. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.kt +100 -0
  10. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.kt +250 -0
  11. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.kt +64 -0
  12. package/android/src/reactnative/java/io/invertase/firebase/app/{ReactNativeFirebaseAppInitProvider.java → ReactNativeFirebaseAppInitProvider.kt} +3 -4
  13. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.kt +47 -0
  14. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.kt +33 -0
  15. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseVersion.java +1 -1
  16. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.kt +185 -0
  17. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.kt +35 -0
  18. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.kt +662 -0
  19. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.kt +103 -0
  20. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.kt +96 -0
  21. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.kt +140 -0
  22. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.kt +109 -0
  23. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.kt +451 -0
  24. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{ContextProvider.java → ContextProvider.kt} +8 -8
  25. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeError.java → NativeError.kt} +8 -8
  26. package/android/src/reactnative/java/io/invertase/firebase/interfaces/{NativeEvent.java → NativeEvent.kt} +6 -6
  27. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.kt +219 -0
  28. package/android/src/test/java/expo/core/ModuleRegistry.java +9 -0
  29. package/android/src/test/java/io/invertase/firebase/app/NativeRNFBTurboAppTest.java +208 -60
  30. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppComponentsJavaCompatibilityTest.java +70 -0
  31. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppJavaCompatibilityTest.java +60 -0
  32. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackageTest.java +165 -0
  33. package/android/src/test/java/io/invertase/firebase/app/ReactNativeFirebaseAppTest.kt +167 -0
  34. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseJavaCompatibilityTest.java +112 -0
  35. package/android/src/test/java/io/invertase/firebase/common/RCTConvertFirebaseTest.kt +317 -0
  36. package/android/src/test/java/io/invertase/firebase/common/RNFBHandleMapTest.kt +309 -0
  37. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterJavaCompatibilityTest.java +176 -0
  38. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitterTest.java +144 -13
  39. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseEventTest.kt +61 -0
  40. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONJavaCompatibilityTest.java +85 -0
  41. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseJSONTest.kt +296 -0
  42. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaJavaCompatibilityTest.java +67 -0
  43. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseMetaTest.kt +246 -0
  44. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebaseModuleTest.kt +254 -0
  45. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesJavaCompatibilityTest.java +87 -0
  46. package/android/src/test/java/io/invertase/firebase/common/ReactNativeFirebasePreferencesTest.kt +260 -0
  47. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsJavaCompatibilityTest.java +255 -0
  48. package/android/src/test/java/io/invertase/firebase/common/SharedUtilsTest.kt +674 -0
  49. package/android/src/test/java/io/invertase/firebase/common/TaskExecutorServiceTest.kt +290 -0
  50. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebaseModuleJavaCompatibilityTest.java +178 -0
  51. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesJavaCompatibilityTest.java +99 -0
  52. package/android/src/test/java/io/invertase/firebase/common/UniversalFirebasePreferencesTest.kt +217 -0
  53. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleJavaCompatibilityTest.java +176 -0
  54. package/android/src/test/java/io/invertase/firebase/commoncompat/ReactNativeFirebaseModuleKotlinCompatibilityTest.kt +52 -0
  55. package/android/src/test/java/io/invertase/firebase/interfaces/InterfacesJavaCompatibilityTest.java +144 -0
  56. package/android/src/test/java/io/invertase/firebase/interfaces/NativeEventTest.kt +56 -0
  57. package/android/src/test/java/io/invertase/firebase/utils/NativeRNFBTurboUtilsTest.java +517 -23
  58. package/dist/module/FirebaseApp.js +10 -0
  59. package/dist/module/FirebaseApp.js.map +1 -1
  60. package/dist/module/common/Base64.js +13 -21
  61. package/dist/module/common/Base64.js.map +1 -1
  62. package/dist/module/common/deeps.js +3 -0
  63. package/dist/module/common/deeps.js.map +1 -1
  64. package/dist/module/common/index.js +17 -9
  65. package/dist/module/common/index.js.map +1 -1
  66. package/dist/module/internal/FirebaseModule.js.map +1 -1
  67. package/dist/module/internal/RNFBNativeEventEmitter.js +12 -1
  68. package/dist/module/internal/RNFBNativeEventEmitter.js.map +1 -1
  69. package/dist/module/internal/SharedEventEmitter.js +3 -1
  70. package/dist/module/internal/SharedEventEmitter.js.map +1 -1
  71. package/dist/module/internal/asyncStorage.js +7 -11
  72. package/dist/module/internal/asyncStorage.js.map +1 -1
  73. package/dist/module/internal/index.js +1 -0
  74. package/dist/module/internal/index.js.map +1 -1
  75. package/dist/module/internal/logger.js +44 -40
  76. package/dist/module/internal/logger.js.map +1 -1
  77. package/dist/module/internal/nativeModuleAndroidIos.js +2 -29
  78. package/dist/module/internal/nativeModuleAndroidIos.js.map +1 -1
  79. package/dist/module/internal/nativeModuleDebug.js +74 -0
  80. package/dist/module/internal/nativeModuleDebug.js.map +1 -0
  81. package/dist/module/internal/nativeModuleWeb.js +9 -29
  82. package/dist/module/internal/nativeModuleWeb.js.map +1 -1
  83. package/dist/module/internal/registry/app.js +8 -2
  84. package/dist/module/internal/registry/app.js.map +1 -1
  85. package/dist/module/internal/registry/modular.js +2 -2
  86. package/dist/module/internal/registry/modular.js.map +1 -1
  87. package/dist/module/internal/registry/nativeModule.js +3 -3
  88. package/dist/module/internal/registry/nativeModule.js.map +1 -1
  89. package/dist/module/internal/web/RNFBAppModule.js +16 -15
  90. package/dist/module/internal/web/RNFBAppModule.js.map +1 -1
  91. package/dist/module/internal/web/memidb/lib/FakeEventTarget.js +3 -1
  92. package/dist/module/internal/web/memidb/lib/FakeEventTarget.js.map +1 -1
  93. package/dist/module/types/app.js.map +1 -1
  94. package/dist/module/types/internal.js +2 -0
  95. package/dist/module/version.js +1 -1
  96. package/dist/typescript/lib/FirebaseApp.d.ts +7 -0
  97. package/dist/typescript/lib/FirebaseApp.d.ts.map +1 -1
  98. package/dist/typescript/lib/common/Base64.d.ts.map +1 -1
  99. package/dist/typescript/lib/common/deeps.d.ts.map +1 -1
  100. package/dist/typescript/lib/common/index.d.ts.map +1 -1
  101. package/dist/typescript/lib/internal/FirebaseModule.d.ts +2 -3
  102. package/dist/typescript/lib/internal/FirebaseModule.d.ts.map +1 -1
  103. package/dist/typescript/lib/internal/NativeModules.d.ts +4 -1
  104. package/dist/typescript/lib/internal/NativeModules.d.ts.map +1 -1
  105. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts +2 -2
  106. package/dist/typescript/lib/internal/RNFBNativeEventEmitter.d.ts.map +1 -1
  107. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts +3 -3
  108. package/dist/typescript/lib/internal/SharedEventEmitter.d.ts.map +1 -1
  109. package/dist/typescript/lib/internal/asyncStorage.d.ts.map +1 -1
  110. package/dist/typescript/lib/internal/index.d.ts +1 -0
  111. package/dist/typescript/lib/internal/index.d.ts.map +1 -1
  112. package/dist/typescript/lib/internal/logger.d.ts.map +1 -1
  113. package/dist/typescript/lib/internal/nativeModuleAndroidIos.d.ts.map +1 -1
  114. package/dist/typescript/lib/internal/nativeModuleDebug.d.ts +2 -0
  115. package/dist/typescript/lib/internal/nativeModuleDebug.d.ts.map +1 -0
  116. package/dist/typescript/lib/internal/nativeModuleWeb.d.ts.map +1 -1
  117. package/dist/typescript/lib/internal/registry/app.d.ts.map +1 -1
  118. package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts +7 -7
  119. package/dist/typescript/lib/internal/web/RNFBAppModule.d.ts.map +1 -1
  120. package/dist/typescript/lib/types/app.d.ts +10 -3
  121. package/dist/typescript/lib/types/app.d.ts.map +1 -1
  122. package/dist/typescript/lib/types/internal.d.ts +12 -0
  123. package/dist/typescript/lib/types/internal.d.ts.map +1 -1
  124. package/dist/typescript/lib/version.d.ts +1 -1
  125. package/firebase-schema.json +5 -1
  126. package/firebase_spm.rb +552 -96
  127. package/ios/RNFBApp/RCTConvert+FIRApp.h +2 -5
  128. package/ios/RNFBApp/RCTConvert+FIRApp.m +11 -6
  129. package/ios/RNFBApp/RCTConvert+FIROptions.h +2 -5
  130. package/ios/RNFBApp/RCTConvert+FIROptions.m +11 -10
  131. package/ios/RNFBApp/RCTConvertFIRApp.swift +86 -0
  132. package/ios/RNFBApp/RCTConvertFIROptions.swift +259 -0
  133. package/ios/RNFBApp/RNFBAppCustomAuthDomains.swift +63 -0
  134. package/ios/RNFBApp/RNFBAppInitializeOptionsMapper.swift +113 -0
  135. package/ios/RNFBApp/RNFBAppLogLevelMapper.swift +53 -0
  136. package/ios/RNFBApp/RNFBAppModule+CustomAuthDomain.m +35 -0
  137. package/ios/RNFBApp/RNFBAppModule.h +6 -2
  138. package/ios/RNFBApp/RNFBAppModule.mm +67 -204
  139. package/ios/RNFBApp/RNFBAppModuleFirebase.swift +439 -0
  140. package/ios/RNFBApp/RNFBAppModuleImplementation.h +68 -0
  141. package/ios/RNFBApp/RNFBAppModuleImplementation.m +195 -0
  142. package/ios/RNFBApp/RNFBHandleMap.h +73 -0
  143. package/ios/RNFBApp/RNFBHandleMap.m +87 -0
  144. package/ios/RNFBApp/RNFBHandleMapStorage.swift +90 -0
  145. package/ios/RNFBApp/RNFBInitializeAppArguments.swift +82 -0
  146. package/ios/RNFBApp/RNFBJSON.m +22 -38
  147. package/ios/RNFBApp/RNFBJSONImplementation.swift +71 -0
  148. package/ios/RNFBApp/RNFBMeta.m +24 -26
  149. package/ios/RNFBApp/RNFBMetaStorage.swift +76 -0
  150. package/ios/RNFBApp/RNFBNullSentinelDecoding.swift +135 -0
  151. package/ios/RNFBApp/RNFBNullSentinelInterceptor.h +30 -3
  152. package/ios/RNFBApp/RNFBNullSentinelInterceptor.m +28 -5
  153. package/ios/RNFBApp/RNFBPreferences.m +22 -20
  154. package/ios/RNFBApp/RNFBPreferencesStorage.swift +101 -0
  155. package/ios/RNFBApp/RNFBRCTEventEmitter.m +36 -93
  156. package/ios/RNFBApp/RNFBRCTEventEmitterCore.swift +161 -0
  157. package/ios/RNFBApp/RNFBSharedUtils.h +2 -5
  158. package/ios/RNFBApp/RNFBSharedUtils.m +109 -197
  159. package/ios/RNFBApp/RNFBSharedUtilsConfig.swift +72 -0
  160. package/ios/RNFBApp/RNFBSharedUtilsFIRApp.swift +271 -0
  161. package/ios/RNFBApp/RNFBSharedUtilsFormatting.swift +59 -0
  162. package/ios/RNFBApp/RNFBSharedUtilsPromiseRejection.swift +88 -0
  163. package/ios/RNFBApp/RNFBUtilsHelpers.swift +116 -0
  164. package/ios/RNFBApp/RNFBUtilsModule+Foundation.m +44 -0
  165. package/ios/RNFBApp/RNFBUtilsModule+PhotoAssets.m +47 -0
  166. package/ios/RNFBApp/RNFBUtilsModule.h +11 -1
  167. package/ios/RNFBApp/RNFBUtilsModule.mm +10 -85
  168. package/ios/RNFBApp/RNFBUtilsModuleImplementation.h +32 -0
  169. package/ios/RNFBApp/RNFBUtilsModuleImplementation.m +56 -0
  170. package/ios/RNFBApp/RNFBVersion.m +1 -1
  171. package/ios/RNFBApp.xcodeproj/project.pbxproj +106 -0
  172. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FIRApp.m +171 -0
  173. package/ios/RNFBAppUnitTests/HostStubs/FirebaseCore/FirebaseCore.h +78 -0
  174. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FIRInstallations.m +7 -0
  175. package/ios/RNFBAppUnitTests/HostStubs/FirebaseInstallations/FirebaseInstallations.h +8 -0
  176. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppModuleHostStub.m +55 -0
  177. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.h +89 -0
  178. package/ios/RNFBAppUnitTests/HostStubs/RNFBAppTurboModules.mm +30 -0
  179. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.h +19 -0
  180. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridge.m +32 -0
  181. package/ios/RNFBAppUnitTests/HostStubs/React/RCTBridgeModule.h +19 -0
  182. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.h +28 -0
  183. package/ios/RNFBAppUnitTests/HostStubs/React/RCTConvert.m +23 -0
  184. package/ios/RNFBAppUnitTests/HostStubs/React/RCTEventEmitter.h +9 -0
  185. package/ios/RNFBAppUnitTests/HostStubs/React/RCTInvalidating.h +24 -0
  186. package/ios/RNFBAppUnitTests/HostStubs/React/RCTUtils.h +9 -0
  187. package/ios/RNFBAppUnitTests/HostStubs/module.modulemap +13 -0
  188. package/ios/RNFBAppUnitTests/RCTConvertFIRAppFacadeTests.m +61 -0
  189. package/ios/RNFBAppUnitTests/RCTConvertFIRAppTests.swift +73 -0
  190. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsFacadeTests.m +57 -0
  191. package/ios/RNFBAppUnitTests/RCTConvertFIROptionsTests.swift +243 -0
  192. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsFacadeTests.m +73 -0
  193. package/ios/RNFBAppUnitTests/RNFBAppCustomAuthDomainsTests.swift +70 -0
  194. package/ios/RNFBAppUnitTests/RNFBAppInitializeOptionsMapperTests.swift +190 -0
  195. package/ios/RNFBAppUnitTests/RNFBAppLogLevelFacadeTests.m +76 -0
  196. package/ios/RNFBAppUnitTests/RNFBAppLogLevelMapperTests.swift +59 -0
  197. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseFacadeTests.m +215 -0
  198. package/ios/RNFBAppUnitTests/RNFBAppModuleFirebaseTests.swift +430 -0
  199. package/ios/RNFBAppUnitTests/RNFBAppModuleLifecycleTests.m +206 -0
  200. package/ios/RNFBAppUnitTests/RNFBAppModuleShellTests.mm +367 -0
  201. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/project.pbxproj +590 -0
  202. package/ios/RNFBAppUnitTests/RNFBAppUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBAppUnitTests.xcscheme +69 -0
  203. package/ios/RNFBAppUnitTests/RNFBFirebaseAppClientTests.swift +165 -0
  204. package/ios/RNFBAppUnitTests/RNFBHandleMapStorageTests.swift +121 -0
  205. package/ios/RNFBAppUnitTests/RNFBHandleMapTests.m +238 -0
  206. package/ios/RNFBAppUnitTests/RNFBInitializeAppArgumentsTests.swift +256 -0
  207. package/ios/RNFBAppUnitTests/RNFBJSONImplementationTests.swift +126 -0
  208. package/ios/RNFBAppUnitTests/RNFBJSONTests.m +172 -0
  209. package/ios/RNFBAppUnitTests/RNFBMetaStorageTests.swift +106 -0
  210. package/ios/RNFBAppUnitTests/RNFBMetaTests.m +65 -0
  211. package/ios/RNFBAppUnitTests/RNFBNullSentinelDecodingTests.swift +286 -0
  212. package/ios/RNFBAppUnitTests/RNFBNullSentinelInterceptorTests.m +312 -0
  213. package/ios/RNFBAppUnitTests/RNFBPreferencesStorageTests.swift +105 -0
  214. package/ios/RNFBAppUnitTests/RNFBPreferencesTests.m +110 -0
  215. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterCoreTests.swift +163 -0
  216. package/ios/RNFBAppUnitTests/RNFBRCTEventEmitterFacadeTests.m +141 -0
  217. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigFacadeTests.m +100 -0
  218. package/ios/RNFBAppUnitTests/RNFBSharedUtilsConfigTests.swift +234 -0
  219. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppFacadeTests.m +145 -0
  220. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFIRAppTests.swift +173 -0
  221. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingFacadeTests.m +38 -0
  222. package/ios/RNFBAppUnitTests/RNFBSharedUtilsFormattingTests.swift +82 -0
  223. package/ios/RNFBAppUnitTests/RNFBSharedUtilsNullSentinelTests.m +35 -0
  224. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionFacadeTests.m +107 -0
  225. package/ios/RNFBAppUnitTests/RNFBSharedUtilsPromiseRejectionTests.swift +133 -0
  226. package/ios/RNFBAppUnitTests/RNFBUtilsHelpersTests.swift +144 -0
  227. package/ios/RNFBAppUnitTests/RNFBUtilsModuleFacadeTests.m +72 -0
  228. package/ios/RNFBAppUnitTests/RNFBUtilsModuleShellTests.mm +282 -0
  229. package/ios/RNFBFirebase/Package.swift +53 -0
  230. package/ios/RNFBFirebase/Sources/RNFBFirebase/RNFBFirebase.swift +285 -0
  231. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/Public/.gitkeep +0 -0
  232. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/RNFBFirebaseBridge.m +169 -0
  233. package/ios/RNFBFirebase/Sources/RNFBFirebaseBridge/include/RNFBFirebaseBridge.h +52 -0
  234. package/ios/RNFBFirebaseUnitTests/RNFBAppDynamicFacadeTests.swift +240 -0
  235. package/{android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppRegistrar.java → ios/RNFBFirebaseUnitTests/RNFBFirebaseClientImport.swift} +22 -17
  236. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/project.pbxproj +588 -0
  237. package/ios/RNFBFirebaseUnitTests/RNFBFirebaseUnitTests.xcodeproj/xcshareddata/xcschemes/RNFBFirebaseUnitTests.xcscheme +83 -0
  238. package/ios_config.sh +50 -22
  239. package/lib/FirebaseApp.ts +10 -0
  240. package/lib/common/Base64.ts +10 -16
  241. package/lib/common/deeps.ts +3 -0
  242. package/lib/common/index.ts +20 -9
  243. package/lib/internal/FirebaseModule.ts +6 -3
  244. package/lib/internal/NativeModules.ts +4 -1
  245. package/lib/internal/RNFBNativeEventEmitter.ts +14 -5
  246. package/lib/internal/SharedEventEmitter.ts +5 -1
  247. package/lib/internal/asyncStorage.ts +7 -11
  248. package/lib/internal/index.ts +1 -0
  249. package/lib/internal/logger.ts +53 -43
  250. package/lib/internal/nativeModuleAndroidIos.ts +2 -40
  251. package/lib/internal/nativeModuleDebug.ts +97 -0
  252. package/lib/internal/nativeModuleWeb.ts +10 -40
  253. package/lib/internal/react-native-vendor-emitter.d.ts +11 -0
  254. package/lib/internal/registry/app.ts +8 -2
  255. package/lib/internal/registry/modular.ts +2 -2
  256. package/lib/internal/registry/nativeModule.ts +3 -3
  257. package/lib/internal/web/RNFBAppModule.ts +16 -15
  258. package/lib/internal/web/memidb/lib/FakeEventTarget.js +3 -1
  259. package/lib/types/app.ts +10 -3
  260. package/lib/types/internal.ts +19 -0
  261. package/lib/version.ts +1 -1
  262. package/package.json +9 -8
  263. package/plugin/build/ios/appDelegate.js +19 -9
  264. package/plugin/build/ios/podfile.js +16 -16
  265. package/plugin/build/pluginConfig.d.ts +4 -2
  266. package/plugin/src/ios/appDelegate.ts +45 -15
  267. package/plugin/src/ios/podfile.ts +20 -23
  268. package/plugin/src/pluginConfig.ts +4 -2
  269. package/android/src/main/java/io/invertase/firebase/common/TaskExecutorService.java +0 -124
  270. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebaseModule.java +0 -62
  271. package/android/src/main/java/io/invertase/firebase/common/UniversalFirebasePreferences.java +0 -91
  272. package/android/src/reactnative/java/io/invertase/firebase/app/NativeRNFBTurboApp.java +0 -222
  273. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseApp.java +0 -46
  274. package/android/src/reactnative/java/io/invertase/firebase/app/ReactNativeFirebaseAppPackage.java +0 -49
  275. package/android/src/reactnative/java/io/invertase/firebase/common/RCTConvertFirebase.java +0 -191
  276. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEvent.java +0 -53
  277. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseEventEmitter.java +0 -606
  278. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseJSON.java +0 -107
  279. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseMeta.java +0 -101
  280. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebaseModule.java +0 -146
  281. package/android/src/reactnative/java/io/invertase/firebase/common/ReactNativeFirebasePreferences.java +0 -96
  282. package/android/src/reactnative/java/io/invertase/firebase/common/SharedUtils.java +0 -441
  283. package/android/src/reactnative/java/io/invertase/firebase/utils/NativeRNFBTurboUtils.java +0 -223
@@ -1,606 +0,0 @@
1
- package io.invertase.firebase.common;
2
-
3
- /*
4
- * Copyright (c) 2016-present Invertase Limited & Contributors
5
- *
6
- * Licensed under the Apache License, Version 2.0 (the "License");
7
- * you may not use this library except in compliance with the License.
8
- * You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software
13
- * distributed under the License is distributed on an "AS IS" BASIS,
14
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- * See the License for the specific language governing permissions and
16
- * limitations under the License.
17
- *
18
- */
19
-
20
- import android.content.Context;
21
- import android.os.Handler;
22
- import android.os.Looper;
23
- import android.util.Log;
24
- import androidx.annotation.MainThread;
25
- import androidx.annotation.Nullable;
26
- import com.facebook.react.ReactApplication;
27
- import com.facebook.react.ReactHost;
28
- import com.facebook.react.ReactNativeHost;
29
- import com.facebook.react.bridge.Arguments;
30
- import com.facebook.react.bridge.ReactContext;
31
- import com.facebook.react.bridge.WritableMap;
32
- import com.facebook.react.modules.core.DeviceEventManagerModule;
33
- import io.invertase.firebase.app.ReactNativeFirebaseApp;
34
- import io.invertase.firebase.interfaces.NativeEvent;
35
- import java.lang.ref.WeakReference;
36
- import java.util.ArrayList;
37
- import java.util.HashMap;
38
- import java.util.List;
39
-
40
- public class ReactNativeFirebaseEventEmitter {
41
- private static final String TAG = "RNFB_EMITTER";
42
- private static ReactNativeFirebaseEventEmitter sharedInstance =
43
- new ReactNativeFirebaseEventEmitter();
44
- private final Handler handler = new Handler(Looper.getMainLooper());
45
-
46
- // All mutable state below is guarded by the jsListeners monitor. Attach/detach/ready
47
- // transitions happen synchronously at cause time under the same monitor as listener
48
- // registration: with more than one ReactContext generation alive during an instance
49
- // reload, deferring any of these transitions (e.g. to a congested main looper) reorders
50
- // them against a replacement runtime's synchronous registrations and can wipe or wedge
51
- // that runtime's state. Only queue flushing is posted to the main thread.
52
- private final List<NativeEvent> queuedEvents = new ArrayList<>();
53
- private final HashMap<String, Integer> jsListeners = new HashMap<>();
54
- // Weak so the emitter never pins a dead ReactContext (and its module graph) for the
55
- // lifetime of the process if a runtime is torn down without a paired detach.
56
- private WeakReference<ReactContext> attachedReactContext = new WeakReference<>(null);
57
- // When the host still names a dying generation, a live module's attach is remembered here
58
- // and promoted once that dying context detaches or the host catches up — without waiting
59
- // solely on a later Activity resume that may never arrive.
60
- private WeakReference<ReactContext> pendingReactContext = new WeakReference<>(null);
61
- // Host identity we moved past while converging onto pending/attached; late attaches of this
62
- // identity must not displace the live generation while the host ref lags.
63
- private WeakReference<ReactContext> hostLagReactContext = new WeakReference<>(null);
64
- // When a new pending candidate enters while the attached generation still lives, listener
65
- // accounting is reset so events queue until the pending JS re-registers. Keep a snapshot of
66
- // the attached generation's accounting so a pending-only cancel can restore it — otherwise
67
- // the surviving attached runtime stays deaf for the rest of the session (#8374-class).
68
- @Nullable private HashMap<String, Integer> attachedListenersSnapshot;
69
- private boolean attachedJsReadySnapshot;
70
- private int attachedJsListenerCountSnapshot;
71
- // After pending-only cancel restores that snapshot, emit must keep targeting the restored
72
- // attached generation even if the host has already advanced to an unrelated unattached
73
- // context — otherwise resolveEmitContext prefers raw hostCurrent and silently loses events
74
- // into a runtime with no RNFB JS subscribers (R1 class after cancel). Cleared when a new
75
- // generation attaches through acceptAttachedContext / convergence / full detach.
76
- private boolean emitPrefersRestoredAttached;
77
- private boolean jsReady = false;
78
- private int jsListenerCount;
79
-
80
- public static ReactNativeFirebaseEventEmitter getSharedInstance() {
81
- return sharedInstance;
82
- }
83
-
84
- public void attachReactContext(final ReactContext reactContext) {
85
- // Resolve host current outside jsListeners so ReactApplication getters are not held
86
- // under the listener monitor (they are RN-owned and not expected to re-enter, but the
87
- // coupling is unnecessary for attach arbitration).
88
- ReactContext hostCurrent = getCurrentReactContextFromHost(reactContext);
89
-
90
- synchronized (jsListeners) {
91
- // Under the new architecture more than one ReactContext generation can exist while an
92
- // instance is destroyed and recreated: a module belonging to the dying generation may
93
- // run initialize() after the replacement generation has already attached (for example
94
- // TurboModuleManager creates requested-but-never-built modules during invalidate).
95
- // Attach is fail-closed when something is already attached: accept the candidate only
96
- // when the host currently names it. A null host current keeps the previous attachment
97
- // rather than accepting a late stale context. When the host still names the previous
98
- // (dying) context, remember the candidate as pending so detach/host catch-up can
99
- // converge without depending only on a later Activity resume.
100
- ReactContext previousContext = attachedReactContext.get();
101
- if (previousContext != null && previousContext != reactContext) {
102
- if (hostCurrent == null) {
103
- Log.w(
104
- TAG,
105
- "Ignoring attach of ReactContext@"
106
- + System.identityHashCode(reactContext)
107
- + " while host current is null; keeping @"
108
- + System.identityHashCode(previousContext));
109
- return;
110
- }
111
-
112
- ReactContext hostLag = hostLagReactContext.get();
113
- if (hostCurrent == reactContext) {
114
- if (hostLag != null && hostLag == reactContext) {
115
- Log.w(
116
- TAG,
117
- "Ignoring attach of host-lag ReactContext@"
118
- + System.identityHashCode(reactContext)
119
- + "; keeping live @"
120
- + System.identityHashCode(previousContext));
121
- return;
122
- }
123
- acceptAttachedContext(
124
- reactContext, /* resetListenerState= */ pendingReactContext.get() != reactContext);
125
- clearConvergenceState();
126
- discardAttachedListenerSnapshot();
127
- } else if (hostCurrent == previousContext) {
128
- // Host still names the dying attached generation. Remember the candidate as pending
129
- // so detach/host catch-up can converge. Idempotent re-attach of the same pending
130
- // identity (e.g. async onHostResume while the host still lags) must not wipe
131
- // listeners the pending JS already registered. Reset only when entering pending for
132
- // a new candidate: first pending, or last-writer-wins replace of a different one.
133
- ReactContext existingPending = pendingReactContext.get();
134
- boolean newPendingCandidate = existingPending != reactContext;
135
- Log.i(
136
- TAG,
137
- "Host still on @"
138
- + System.identityHashCode(previousContext)
139
- + "; pending attach of @"
140
- + System.identityHashCode(reactContext)
141
- + (newPendingCandidate ? "" : " (idempotent)"));
142
- pendingReactContext = new WeakReference<>(reactContext);
143
- hostLagReactContext = new WeakReference<>(previousContext);
144
- if (newPendingCandidate) {
145
- // Drop previous-generation listener accounting; replacement JS will re-register.
146
- // Snapshot once per pending window so pending-only cancel can restore the
147
- // surviving attached generation (last-writer-wins replace keeps the first
148
- // snapshot — that is still the attached runtime's pre-pending state).
149
- snapshotAttachedListenerStateIfNeeded();
150
- resetListenerState();
151
- }
152
- handler.post(this::tryConvergePendingReactContext);
153
- return;
154
- } else {
155
- Log.w(
156
- TAG,
157
- "Ignoring attach of non-current ReactContext@"
158
- + System.identityHashCode(reactContext)
159
- + ", current is @"
160
- + System.identityHashCode(hostCurrent));
161
- return;
162
- }
163
- } else if (previousContext != reactContext) {
164
- acceptAttachedContext(reactContext, /* resetListenerState= */ false);
165
- clearConvergenceState();
166
- } else {
167
- // Same context re-attach (e.g. resume). Clear lag only when this identity is the
168
- // live pending/attached generation the host has caught up to — not when we are
169
- // still the dying hostLag while a different pending replacement is waiting.
170
- if (hostCurrent == reactContext) {
171
- ReactContext pending = pendingReactContext.get();
172
- if (pending == null || pending == reactContext) {
173
- clearConvergenceState();
174
- }
175
- }
176
- }
177
- }
178
-
179
- handler.post(this::sendQueuedEvents);
180
- }
181
-
182
- public void detachReactContext(final ReactContext reactContext) {
183
- synchronized (jsListeners) {
184
- // Pending-only invalidate (failed replacement startup / overlapping teardown): the
185
- // candidate never became attached, so cancel it before the attached-identity check.
186
- // Restore the surviving attached generation's listener / jsReady snapshot taken when
187
- // pending first entered — pending-window registrations belong to the cancelled
188
- // generation and must not leave the attached runtime deaf. Superseded identities that
189
- // are not the current pending fall through and no-op below — they must not wipe a
190
- // newer live pending's registrations.
191
- ReactContext pending = pendingReactContext.get();
192
- if (pending == reactContext && attachedReactContext.get() != reactContext) {
193
- Log.i(
194
- TAG,
195
- "Cancelled pending ReactContext@"
196
- + System.identityHashCode(reactContext)
197
- + "; attached remains @"
198
- + System.identityHashCode(attachedReactContext.get()));
199
- clearConvergenceState();
200
- restoreAttachedListenerSnapshot();
201
- // Events queued while the pending window wiped listeners must drain now — attached
202
- // JS already registered before pending entered and will not re-addListener.
203
- handler.post(this::sendQueuedEvents);
204
- return;
205
- }
206
-
207
- // Only clear state installed by the runtime that is going away; a dying generation
208
- // must not wipe listener registrations a replacement runtime has already made. A
209
- // replacement runtime always attaches (synchronously, at module creation) before its
210
- // JS can register listeners, so an identity match here means the dying state is ours.
211
- if (attachedReactContext.get() != reactContext) {
212
- return;
213
- }
214
-
215
- if (pending != null && pending != reactContext) {
216
- Log.i(
217
- TAG,
218
- "Detached ReactContext@"
219
- + System.identityHashCode(reactContext)
220
- + "; promoting pending @"
221
- + System.identityHashCode(pending));
222
- attachedReactContext = new WeakReference<>(pending);
223
- pendingReactContext = new WeakReference<>(null);
224
- // Keep jsReady / jsListeners: they belong to the promoted generation's JS.
225
- // hostLag stays set so emit and late attaches do not regress to the dying identity
226
- // while the host ref still names it.
227
- discardAttachedListenerSnapshot();
228
- emitPrefersRestoredAttached = false;
229
- handler.post(this::sendQueuedEvents);
230
- return;
231
- }
232
-
233
- Log.i(TAG, "Detached ReactContext@" + System.identityHashCode(reactContext));
234
- attachedReactContext = new WeakReference<>(null);
235
- resetListenerState();
236
- clearConvergenceState();
237
- discardAttachedListenerSnapshot();
238
- emitPrefersRestoredAttached = false;
239
- // queuedEvents are intentionally kept: they drain once the next runtime attaches and
240
- // registers listeners, which is how events raised while no runtime is alive (for
241
- // example messaging events for a killed app) reach JS.
242
- }
243
- }
244
-
245
- public void notifyJsReady(Boolean ready) {
246
- synchronized (jsListeners) {
247
- jsReady = ready;
248
- }
249
-
250
- handler.post(this::sendQueuedEvents);
251
- }
252
-
253
- public void sendEvent(final NativeEvent event) {
254
- handler.post(
255
- () -> {
256
- synchronized (jsListeners) {
257
- if (!jsListeners.containsKey(event.getEventName())) {
258
- queuedEvents.add(event);
259
- return;
260
- }
261
- }
262
- // emit() resolves ReactApplication host current outside jsListeners; do not hold
263
- // the monitor across that call.
264
- if (!emit(event)) {
265
- synchronized (jsListeners) {
266
- queuedEvents.add(event);
267
- }
268
- }
269
- });
270
- }
271
-
272
- public void addListener(String eventName) {
273
- synchronized (jsListeners) {
274
- jsListenerCount++;
275
- if (!jsListeners.containsKey(eventName)) {
276
- jsListeners.put(eventName, 1);
277
- } else {
278
- int listenersForEvent = jsListeners.get(eventName);
279
- jsListeners.put(eventName, listenersForEvent + 1);
280
- }
281
- }
282
-
283
- handler.post(this::sendQueuedEvents);
284
- }
285
-
286
- public void removeListener(String eventName, Boolean all) {
287
- synchronized (jsListeners) {
288
- if (jsListeners.containsKey(eventName)) {
289
- int listenersForEvent = jsListeners.get(eventName);
290
-
291
- if (listenersForEvent <= 1 || all) {
292
- jsListeners.remove(eventName);
293
- } else {
294
- jsListeners.put(eventName, listenersForEvent - 1);
295
- }
296
-
297
- jsListenerCount -= all ? listenersForEvent : 1;
298
- }
299
- }
300
- }
301
-
302
- public WritableMap getListenersMap() {
303
- WritableMap writableMap = Arguments.createMap();
304
- WritableMap events = Arguments.createMap();
305
-
306
- // Resolve host current outside jsListeners; converge/snapshot under the monitor.
307
- ReactContext pendingHint;
308
- ReactContext attachedHint;
309
- synchronized (jsListeners) {
310
- pendingHint = pendingReactContext.get();
311
- attachedHint = attachedReactContext.get();
312
- }
313
- ReactContext hostForConverge =
314
- getCurrentReactContextFromHost(pendingHint != null ? pendingHint : attachedHint);
315
-
316
- ReactContext attachedContext;
317
- synchronized (jsListeners) {
318
- tryConvergePendingReactContextLocked(hostForConverge);
319
- attachedContext = attachedReactContext.get();
320
-
321
- writableMap.putInt("listeners", jsListenerCount);
322
- writableMap.putInt("queued", queuedEvents.size());
323
- writableMap.putBoolean("jsReady", jsReady);
324
- writableMap.putInt(
325
- "attachedContextHash",
326
- attachedContext == null ? 0 : System.identityHashCode(attachedContext));
327
-
328
- for (HashMap.Entry<String, Integer> entry : jsListeners.entrySet()) {
329
- events.putInt(entry.getKey(), entry.getValue());
330
- }
331
- }
332
-
333
- ReactContext currentContext = getCurrentReactContextFromHost(attachedContext);
334
- writableMap.putInt(
335
- "currentContextHash", currentContext == null ? 0 : System.identityHashCode(currentContext));
336
- writableMap.putMap("events", events);
337
-
338
- return writableMap;
339
- }
340
-
341
- @MainThread
342
- private void sendQueuedEvents() {
343
- List<NativeEvent> toSend;
344
- synchronized (jsListeners) {
345
- toSend = new ArrayList<>();
346
- for (NativeEvent event : new ArrayList<>(queuedEvents)) {
347
- if (jsListeners.containsKey(event.getEventName())) {
348
- queuedEvents.remove(event);
349
- toSend.add(event);
350
- }
351
- }
352
- }
353
- for (NativeEvent event : toSend) {
354
- sendEvent(event);
355
- }
356
- }
357
-
358
- @MainThread
359
- private boolean emit(final NativeEvent event) {
360
- // Snapshot readiness / pointers under the monitor, resolve host current outside (avoid
361
- // holding jsListeners across ReactApplication getters), then re-enter to converge/resolve.
362
- ReactContext attachedHint;
363
- boolean ready;
364
- synchronized (jsListeners) {
365
- ready = jsReady;
366
- if (!ready) {
367
- return false;
368
- }
369
- attachedHint = attachedReactContext.get();
370
- if (attachedHint == null) {
371
- attachedHint = pendingReactContext.get();
372
- }
373
- }
374
- ReactContext hostCurrent = getCurrentReactContextFromHost(attachedHint);
375
-
376
- ReactContext emitContext;
377
- synchronized (jsListeners) {
378
- if (!jsReady) {
379
- return false;
380
- }
381
- tryConvergePendingReactContextLocked(hostCurrent);
382
-
383
- // Resolve the context hosting the live JS runtime at emit time rather than trusting the
384
- // attached one alone: a context captured at module-creation time can belong to a previous
385
- // generation whose runtime no longer contains the JS listeners, and on bridgeless a stale
386
- // context still reports an active instance so it cannot be validated - only replaced
387
- // (#8374, #8900). When attached has already converged ahead of a lagging host ref, prefer
388
- // attached over the dying host current so events are not delivered into a runtime with no
389
- // listeners.
390
- ReactContext attached = attachedReactContext.get();
391
- emitContext = resolveEmitContext(attached, hostCurrent);
392
- }
393
-
394
- if (emitContext == null || !emitContext.hasActiveReactInstance()) {
395
- return false;
396
- }
397
-
398
- try {
399
- emitContext
400
- .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
401
- .emit("rnfb_" + event.getEventName(), event.getEventBody());
402
- } catch (Exception e) {
403
- Log.wtf(TAG, "Error sending Event " + event.getEventName(), e);
404
- return false;
405
- }
406
-
407
- return true;
408
- }
409
-
410
- @Nullable
411
- private ReactContext resolveEmitContext(
412
- @Nullable ReactContext attached, @Nullable ReactContext hostCurrent) {
413
- ReactContext pending = pendingReactContext.get();
414
- ReactContext hostLag = hostLagReactContext.get();
415
-
416
- // A pending replacement owns (or will own) the listener map. Prefer it over host/attached
417
- // for the whole pending window — including when the host has already advanced to an
418
- // unrelated third generation that has not yet attached via this emitter. Emitting into
419
- // that third context would return true with no RNFB JS subscribers and no re-queue.
420
- if (pending != null) {
421
- return pending;
422
- }
423
-
424
- if (hostCurrent == null) {
425
- return attached;
426
- }
427
- if (attached == null || attached == hostCurrent) {
428
- if (attached == hostCurrent) {
429
- clearConvergenceState();
430
- emitPrefersRestoredAttached = false;
431
- }
432
- return hostCurrent;
433
- }
434
-
435
- if (hostLag != null && hostLag == hostCurrent) {
436
- return attached;
437
- }
438
-
439
- // Pending-only cancel restored listeners onto attached; an unrelated hostCurrent that has
440
- // not yet attached through this emitter must not steal delivery (silent loss, no re-queue).
441
- // Flag is only set while an attached generation still owns the restored map.
442
- if (emitPrefersRestoredAttached) {
443
- return attached;
444
- }
445
-
446
- // Attached is stale relative to a host that has moved on — prefer the host.
447
- return hostCurrent;
448
- }
449
-
450
- private void tryConvergePendingReactContext() {
451
- ReactContext pendingHint;
452
- synchronized (jsListeners) {
453
- pendingHint = pendingReactContext.get();
454
- }
455
- if (pendingHint == null) {
456
- return;
457
- }
458
- ReactContext hostCurrent = getCurrentReactContextFromHost(pendingHint);
459
- synchronized (jsListeners) {
460
- if (tryConvergePendingReactContextLocked(hostCurrent)) {
461
- handler.post(this::sendQueuedEvents);
462
- }
463
- }
464
- }
465
-
466
- /**
467
- * Prefer resolving {@code hostCurrent} outside {@code jsListeners} and passing it in so
468
- * ReactApplication getters are not held under the listener monitor.
469
- *
470
- * @return true when attachment changed
471
- */
472
- private boolean tryConvergePendingReactContextLocked(@Nullable ReactContext hostCurrent) {
473
- ReactContext pending = pendingReactContext.get();
474
- if (pending == null) {
475
- return false;
476
- }
477
- if (hostCurrent != pending) {
478
- return false;
479
- }
480
- ReactContext previous = attachedReactContext.get();
481
- if (previous == pending) {
482
- clearConvergenceState();
483
- return false;
484
- }
485
- Log.i(
486
- TAG, "Host caught up; attaching pending ReactContext@" + System.identityHashCode(pending));
487
- acceptAttachedContext(pending, /* resetListenerState= */ false);
488
- clearConvergenceState();
489
- discardAttachedListenerSnapshot();
490
- return true;
491
- }
492
-
493
- private void acceptAttachedContext(ReactContext reactContext, boolean resetListenerState) {
494
- ReactContext previousContext = attachedReactContext.get();
495
- if (previousContext != reactContext) {
496
- Log.i(
497
- TAG,
498
- "ReactContext changed: @"
499
- + System.identityHashCode(previousContext)
500
- + " -> @"
501
- + System.identityHashCode(reactContext));
502
- attachedReactContext = new WeakReference<>(reactContext);
503
- // A real attach of a new generation supersedes restored-attached emit affinity.
504
- emitPrefersRestoredAttached = false;
505
- if (resetListenerState) {
506
- discardAttachedListenerSnapshot();
507
- resetListenerState();
508
- }
509
- }
510
- }
511
-
512
- private void resetListenerState() {
513
- jsReady = false;
514
- jsListeners.clear();
515
- jsListenerCount = 0;
516
- }
517
-
518
- private void snapshotAttachedListenerStateIfNeeded() {
519
- if (attachedListenersSnapshot != null) {
520
- return;
521
- }
522
- attachedListenersSnapshot = new HashMap<>(jsListeners);
523
- attachedJsReadySnapshot = jsReady;
524
- attachedJsListenerCountSnapshot = jsListenerCount;
525
- }
526
-
527
- private void restoreAttachedListenerSnapshot() {
528
- if (attachedListenersSnapshot == null) {
529
- resetListenerState();
530
- emitPrefersRestoredAttached = false;
531
- return;
532
- }
533
- jsListeners.clear();
534
- jsListeners.putAll(attachedListenersSnapshot);
535
- jsReady = attachedJsReadySnapshot;
536
- jsListenerCount = attachedJsListenerCountSnapshot;
537
- discardAttachedListenerSnapshot();
538
- emitPrefersRestoredAttached = true;
539
- }
540
-
541
- private void discardAttachedListenerSnapshot() {
542
- attachedListenersSnapshot = null;
543
- attachedJsReadySnapshot = false;
544
- attachedJsListenerCountSnapshot = 0;
545
- }
546
-
547
- private void clearConvergenceState() {
548
- pendingReactContext = new WeakReference<>(null);
549
- hostLagReactContext = new WeakReference<>(null);
550
- }
551
-
552
- @Nullable
553
- private static ReactContext getCurrentReactContextFromHost(@Nullable ReactContext contextHint) {
554
- Context applicationContext =
555
- contextHint != null
556
- ? contextHint.getApplicationContext()
557
- : ReactNativeFirebaseApp.getApplicationContext();
558
- if (applicationContext != null) {
559
- // Normalize in case a non-application context (for example a ContentProvider context)
560
- // was stored as the fallback.
561
- applicationContext = applicationContext.getApplicationContext();
562
- }
563
- if (!(applicationContext instanceof ReactApplication)) {
564
- // Brownfield hosts that do not implement ReactApplication fall back to the attached
565
- // context, preserving pre-existing behaviour.
566
- return null;
567
- }
568
-
569
- ReactApplication reactApplication = (ReactApplication) applicationContext;
570
-
571
- // Note: these getters may lazily construct their host on first call; that is acceptable
572
- // here because a live react-native-firebase module implies the app's host already exists.
573
- ReactContext fromReactHost = null;
574
- try {
575
- ReactHost reactHost = reactApplication.getReactHost();
576
- if (reactHost != null) {
577
- fromReactHost = reactHost.getCurrentReactContext();
578
- if (fromReactHost != null) {
579
- return fromReactHost;
580
- }
581
- // Hybrid / transitional hosts may expose a non-null ReactHost whose current context
582
- // is briefly null while the bridge ReactNativeHost still carries the live context.
583
- // Fall through rather than treating null as a permanent answer.
584
- }
585
- } catch (RuntimeException | LinkageError e) {
586
- // App-authored hosts may throw, and react-native 0.83+ throws from the deprecated
587
- // reactNativeHost getter on bridgeless-only apps.
588
- Log.d(TAG, "Failed to resolve current ReactContext via ReactHost", e);
589
- }
590
-
591
- try {
592
- ReactNativeHost reactNativeHost = reactApplication.getReactNativeHost();
593
- // hasInstance() guards against getReactInstanceManager() eagerly creating an instance
594
- // manager purely as a side effect of emitting an event.
595
- if (reactNativeHost != null && reactNativeHost.hasInstance()) {
596
- return reactNativeHost.getReactInstanceManager().getCurrentReactContext();
597
- }
598
- } catch (RuntimeException | LinkageError e) {
599
- // Bridgeless-only apps throw from getReactNativeHost(); if ReactHost was present but
600
- // returned null current, that null stands — still log so the failure is visible.
601
- Log.d(TAG, "Failed to resolve current ReactContext via ReactNativeHost", e);
602
- }
603
-
604
- return fromReactHost;
605
- }
606
- }