expo-modules-core 0.6.5 → 0.9.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 (219) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +1 -1
  3. package/android/ExpoModulesCorePlugin.gradle +15 -0
  4. package/android/build.gradle +31 -15
  5. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +5 -5
  6. package/android/src/main/java/expo/modules/adapters/react/services/UIManagerModuleWrapper.java +13 -0
  7. package/android/src/main/java/expo/modules/core/ViewManager.java +9 -0
  8. package/android/src/main/java/expo/modules/core/interfaces/JavaScriptContextProvider.java +4 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +37 -1
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +30 -0
  11. package/android/src/main/java/expo/modules/core/interfaces/services/UIManager.java +2 -0
  12. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +23 -5
  13. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +5 -3
  14. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +3 -8
  15. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +24 -9
  16. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +12 -7
  17. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +23 -1
  18. package/android/src/main/java/expo/modules/kotlin/Promise.kt +1 -1
  19. package/android/src/main/java/expo/modules/kotlin/callbacks/Callback.kt +5 -0
  20. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +39 -0
  21. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallbackDelegate.kt +27 -0
  22. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +25 -0
  23. package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
  24. package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
  25. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +93 -9
  26. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +11 -0
  27. package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +18 -18
  28. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
  29. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +170 -0
  30. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
  31. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
  32. package/android/src/main/java/expo/modules/kotlin/modules/DefinitionMarker.kt +4 -0
  33. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +17 -2
  34. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +416 -43
  35. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
  36. package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
  37. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +71 -15
  38. package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
  39. package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
  40. package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
  41. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +11 -5
  42. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +10 -4
  45. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +12 -6
  46. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +29 -13
  47. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +2 -1
  48. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
  49. package/android/src/main/java/expo/modules/kotlin/views/CallbacksDefinition.kt +3 -0
  50. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +71 -0
  51. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +22 -0
  52. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +114 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +30 -2
  55. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +81 -2
  56. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +62 -2
  57. package/build/EventEmitter.d.ts +1 -0
  58. package/build/EventEmitter.d.ts.map +1 -0
  59. package/build/NativeModulesProxy.d.ts +1 -0
  60. package/build/NativeModulesProxy.d.ts.map +1 -0
  61. package/build/NativeModulesProxy.native.d.ts +1 -4
  62. package/build/NativeModulesProxy.native.d.ts.map +1 -0
  63. package/build/NativeModulesProxy.native.js +1 -14
  64. package/build/NativeModulesProxy.native.js.map +1 -1
  65. package/build/NativeModulesProxy.types.d.ts +1 -3
  66. package/build/NativeModulesProxy.types.d.ts.map +1 -0
  67. package/build/NativeModulesProxy.types.js.map +1 -1
  68. package/build/NativeViewManagerAdapter.d.ts +1 -0
  69. package/build/NativeViewManagerAdapter.d.ts.map +1 -0
  70. package/build/NativeViewManagerAdapter.native.d.ts +1 -0
  71. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -0
  72. package/build/NativeViewManagerAdapter.native.js +9 -33
  73. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  74. package/build/PermissionsHook.d.ts +1 -0
  75. package/build/PermissionsHook.d.ts.map +1 -0
  76. package/build/PermissionsInterface.d.ts +1 -0
  77. package/build/PermissionsInterface.d.ts.map +1 -0
  78. package/build/Platform.d.ts +1 -0
  79. package/build/Platform.d.ts.map +1 -0
  80. package/build/SyntheticPlatformEmitter.d.ts +1 -0
  81. package/build/SyntheticPlatformEmitter.d.ts.map +1 -0
  82. package/build/SyntheticPlatformEmitter.web.d.ts +1 -0
  83. package/build/SyntheticPlatformEmitter.web.d.ts.map +1 -0
  84. package/build/deprecate.d.ts +1 -0
  85. package/build/deprecate.d.ts.map +1 -0
  86. package/build/environment/browser.d.ts +1 -0
  87. package/build/environment/browser.d.ts.map +1 -0
  88. package/build/environment/browser.web.d.ts +1 -0
  89. package/build/environment/browser.web.d.ts.map +1 -0
  90. package/build/errors/CodedError.d.ts +1 -0
  91. package/build/errors/CodedError.d.ts.map +1 -0
  92. package/build/errors/UnavailabilityError.d.ts +1 -0
  93. package/build/errors/UnavailabilityError.d.ts.map +1 -0
  94. package/build/index.d.ts +3 -0
  95. package/build/index.d.ts.map +1 -0
  96. package/build/index.js +2 -0
  97. package/build/index.js.map +1 -1
  98. package/build/requireNativeModule.d.ts +16 -0
  99. package/build/requireNativeModule.d.ts.map +1 -0
  100. package/build/requireNativeModule.js +18 -0
  101. package/build/requireNativeModule.js.map +1 -0
  102. package/build/sweet/NativeErrorManager.d.ts +3 -0
  103. package/build/sweet/NativeErrorManager.d.ts.map +1 -0
  104. package/build/sweet/NativeErrorManager.js +3 -0
  105. package/build/sweet/NativeErrorManager.js.map +1 -0
  106. package/build/sweet/setUpErrorManager.fx.d.ts +2 -0
  107. package/build/sweet/setUpErrorManager.fx.d.ts.map +1 -0
  108. package/build/sweet/setUpErrorManager.fx.js +11 -0
  109. package/build/sweet/setUpErrorManager.fx.js.map +1 -0
  110. package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
  111. package/ios/AppDelegates/ExpoAppDelegate.swift +22 -20
  112. package/ios/EXAppDefines.h +1 -0
  113. package/ios/EXAppDefines.m +6 -0
  114. package/ios/EXUtilities.h +2 -0
  115. package/ios/EXUtilities.m +12 -0
  116. package/ios/ExpoModulesCore.h +4 -0
  117. package/ios/ExpoModulesCore.podspec +4 -2
  118. package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
  119. package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
  120. package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +5 -0
  121. package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +21 -1
  122. package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +10 -0
  123. package/ios/JSI/EXJSIInstaller.mm +17 -0
  124. package/ios/JSI/EXJSIUtils.h +19 -0
  125. package/ios/JSI/EXJSIUtils.mm +89 -0
  126. package/ios/JSI/EXJavaScriptObject.h +97 -0
  127. package/ios/JSI/EXJavaScriptObject.mm +121 -0
  128. package/ios/JSI/EXJavaScriptRuntime.h +73 -0
  129. package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
  130. package/ios/JSI/EXJavaScriptValue.h +57 -0
  131. package/ios/JSI/EXJavaScriptValue.mm +166 -0
  132. package/ios/JSI/ExpoModulesHostObject.h +33 -0
  133. package/ios/JSI/ExpoModulesHostObject.mm +41 -0
  134. package/ios/JSI/JavaScriptRuntime.swift +32 -0
  135. package/ios/JSI/JavaScriptValue.swift +94 -0
  136. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +3 -23
  137. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
  138. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +101 -75
  139. package/ios/RCTComponentData+Privates.h +12 -0
  140. package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
  141. package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
  142. package/ios/ReactDelegates/ExpoReactDelegate.swift +3 -3
  143. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +4 -4
  144. package/ios/ReactDelegates/ModulePriorities.swift +1 -1
  145. package/ios/Swift/AppContext.swift +57 -4
  146. package/ios/Swift/Arguments/AnyArgumentType.swift +1 -1
  147. package/ios/Swift/Arguments/ArgumentType.swift +4 -0
  148. package/ios/Swift/Arguments/Convertibles.swift +13 -13
  149. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +11 -17
  150. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +1 -1
  151. package/ios/Swift/Arguments/Types/RawArgumentType.swift +2 -2
  152. package/ios/Swift/Conversions.swift +51 -56
  153. package/ios/Swift/EventListener.swift +8 -10
  154. package/ios/Swift/Events/Callback.swift +66 -0
  155. package/ios/Swift/Events/Event.swift +43 -0
  156. package/ios/Swift/Exceptions/ChainableException.swift +51 -0
  157. package/ios/Swift/{CodedError.swift → Exceptions/CodedError.swift} +1 -12
  158. package/ios/Swift/Exceptions/Exception.swift +62 -0
  159. package/ios/Swift/Exceptions/ExceptionOrigin.swift +28 -0
  160. package/ios/Swift/Exceptions/GenericException.swift +20 -0
  161. package/ios/Swift/Exceptions/UnexpectedException.swift +16 -0
  162. package/ios/Swift/Functions/AnyFunction.swift +16 -1
  163. package/ios/Swift/Functions/AsyncFunctionComponent.swift +182 -0
  164. package/ios/Swift/Functions/ConcreteFunction.swift +52 -59
  165. package/ios/Swift/Functions/SyncFunctionComponent.swift +181 -0
  166. package/ios/Swift/JavaScriptUtils.swift +99 -0
  167. package/ios/Swift/ModuleHolder.swift +69 -18
  168. package/ios/Swift/ModuleRegistry.swift +4 -1
  169. package/ios/Swift/Modules/AnyModule.swift +0 -1
  170. package/ios/Swift/Modules/ModuleDefinition.swift +4 -13
  171. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +0 -1
  172. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +54 -220
  173. package/ios/Swift/ModulesProvider.swift +3 -11
  174. package/ios/Swift/Objects/ObjectDefinition.swift +30 -0
  175. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +257 -0
  176. package/ios/Swift/Promise.swift +8 -3
  177. package/ios/Swift/Records/AnyField.swift +7 -0
  178. package/ios/Swift/Records/Field.swift +24 -19
  179. package/ios/Swift/Records/FieldOption.swift +1 -1
  180. package/ios/Swift/Records/Record.swift +12 -4
  181. package/ios/Swift/SwiftInteropBridge.swift +53 -15
  182. package/ios/Swift/Views/AnyViewProp.swift +1 -1
  183. package/ios/Swift/Views/ComponentData.swift +96 -0
  184. package/ios/Swift/Views/ConcreteViewProp.swift +6 -8
  185. package/ios/Swift/Views/ExpoView.swift +8 -0
  186. package/ios/Swift/Views/ViewFactory.swift +1 -1
  187. package/ios/Swift/Views/ViewManagerDefinition.swift +23 -2
  188. package/ios/Swift/Views/ViewManagerDefinitionBuilder.swift +0 -1
  189. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +49 -0
  190. package/ios/Swift/Views/ViewModuleWrapper.swift +5 -2
  191. package/ios/Swift.h +5 -0
  192. package/ios/Tests/ArgumentTypeSpec.swift +5 -7
  193. package/ios/Tests/ConstantsSpec.swift +6 -7
  194. package/ios/Tests/ConvertiblesSpec.swift +35 -36
  195. package/ios/Tests/ExceptionsSpec.swift +111 -0
  196. package/ios/Tests/ExpoModulesSpec.swift +75 -0
  197. package/ios/Tests/FunctionSpec.swift +21 -25
  198. package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
  199. package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
  200. package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
  201. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  202. package/ios/Tests/Mocks/ModulesProviderMock.swift +0 -1
  203. package/ios/Tests/ModuleEventListenersSpec.swift +16 -17
  204. package/ios/Tests/ModuleRegistrySpec.swift +2 -3
  205. package/ios/Tests/RecordSpec.swift +9 -20
  206. package/package.json +3 -3
  207. package/src/NativeModulesProxy.native.ts +2 -22
  208. package/src/NativeModulesProxy.types.ts +0 -8
  209. package/src/NativeViewManagerAdapter.native.tsx +12 -28
  210. package/src/index.ts +4 -0
  211. package/src/requireNativeModule.ts +29 -0
  212. package/src/sweet/NativeErrorManager.ts +2 -0
  213. package/src/sweet/setUpErrorManager.fx.ts +12 -0
  214. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
  215. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
  216. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
  217. package/ios/JSI/ExpoModulesProxySpec.h +0 -24
  218. package/ios/JSI/ExpoModulesProxySpec.mm +0 -135
  219. package/ios/JSI/JSIInstaller.mm +0 -22
package/CHANGELOG.md CHANGED
@@ -10,6 +10,63 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.9.0 — 2022-04-21
14
+
15
+ ### ⚠️ Notices
16
+
17
+ - Renamed all definition components to start with the uppercase letter. The old names will be removed in the next minor release. ([#17153](https://github.com/expo/expo/pull/17153) by [@lukmccall](https://github.com/lukmccall), [#17098](https://github.com/expo/expo/pull/17098) by [@tsapeta](https://github.com/tsapeta))
18
+
19
+ ### 🎉 New features
20
+
21
+ - Add `ReactNativeHostHandler.getUseDeveloperSupport()` to allow `expo-dev-launcher` to override this value at runtime. ([#17069](https://github.com/expo/expo/pull/17069) by [@esamelson](https://github.com/esamelson))
22
+
23
+ ## 0.8.0 — 2022-04-18
24
+
25
+ ### 🛠 Breaking changes
26
+
27
+ - Remove backward compatible workaround and drop react-native 0.64 support. ([#16446](https://github.com/expo/expo/pull/16446) by [@kudo](https://github.com/kudo))
28
+
29
+ ### ⚠️ Notices
30
+
31
+ - Deprecated current behavior of `function` module definition component in favor of `asyncFunction` to emphasize that it's being executed asynchronously in JavaScript. In the future release `function` will become synchronous. ([#16630](https://github.com/expo/expo/pull/16630) by [@tsapeta](https://github.com/tsapeta), [#16656](https://github.com/expo/expo/pull/16656) by [@lukmccall](https://github.com/lukmccall))
32
+ - On Android bump `compileSdkVersion` to `31`, `targetSdkVersion` to `31` and `Java` version to `11`. ([#16941](https://github.com/expo/expo/pull/16941) by [@bbarthec](https://github.com/bbarthec))
33
+
34
+ ### 🎉 New features
35
+
36
+ - Add `getDevSupportManagerFactory` support to `ReactNativeHostHandler`. ([#16434](https://github.com/expo/expo/pull/16434) by [@lukmccall](https://github.com/lukmccall))
37
+ - Add support for automatic setup of `expo-dev-client` on Android. ([#16441](https://github.com/expo/expo/pull/16441) by [@esamelson](https://github.com/esamelson))
38
+ - Stopped relying on deprecated `ViewPropTypes` from React Native. ([#16207](https://github.com/expo/expo/pull/16207) by [@tsapeta](https://github.com/tsapeta))
39
+ - Added Android `ReactNativeHostHandler.getJavaScriptExecutorFactory()` for a module to override the `JavaScriptExecutorFactory`. ([#17005](https://github.com/expo/expo/pull/17005) by [@kudo](https://github.com/kudo))
40
+
41
+ ### 🐛 Bug fixes
42
+
43
+ - Fix the `Fatal error: Expo modules provider must implement "ModulesProviderProtocol"` runtime error in XCTest targets and SwiftUI Preview. ([#16733](https://github.com/expo/expo/pull/16733) by [@kudo](https://github.com/kudo))
44
+
45
+ ### 💡 Others
46
+
47
+ - Removed the opt-in feature to use the turbo module implementation of `NativeModulesProxy` in favor of another solution introduced in [#15847](https://github.com/expo/expo/pull/15847). ([#16825](https://github.com/expo/expo/pull/16825) by [@tsapeta](https://github.com/tsapeta))
48
+
49
+ ## 0.7.0 — 2022-01-26
50
+
51
+ ### 🎉 New features
52
+
53
+ - Allow accessing `RCTBridge` from the modules on iOS. ([#15816](https://github.com/expo/expo/pull/15816) by [@tsapeta](https://github.com/tsapeta))
54
+ - Added support for native callbacks through the view props in Sweet API on iOS. ([#15731](https://github.com/expo/expo/pull/15731) by [@tsapeta](https://github.com/tsapeta))
55
+ - Added support for native callbacks through the view props in Sweet API on Android. ([#15743](https://github.com/expo/expo/pull/15743) by [@lukmccall](https://github.com/lukmccall))
56
+ - The `ModuleDefinition` will use class name if the `name` component wasn't provided in Sweet API on Android. ([#15738](https://github.com/expo/expo/pull/15738) by [@lukmccall](https://github.com/lukmccall))
57
+ - Added `onViewDestroys` component to the `ViewManager` in Sweet API on Android. ([#15740](https://github.com/expo/expo/pull/15740) by [@lukmccall](https://github.com/lukmccall))
58
+ - Added shortened `constants` component that takes `vargs Pair<String, Any?>` as an argument in Sweet API on Android. ([#15742](https://github.com/expo/expo/pull/15742) by [@lukmccall](https://github.com/lukmccall))
59
+ - Introduced the concept of chainable exceptions in Sweet API on iOS. ([#15813](https://github.com/expo/expo/pull/15813) by [@tsapeta](https://github.com/tsapeta))
60
+ - Sweet function closures can throw errors on iOS. ([#15849](https://github.com/expo/expo/pull/15849) by [@tsapeta](https://github.com/tsapeta))
61
+ - Add `requireNativeModule` function to replace accessing native modules from `NativeModulesProxy`. ([#15848](https://github.com/expo/expo/pull/15848) by [@tsapeta](https://github.com/tsapeta))
62
+ - Implemented basic functionality of JSI host object to replace `NativeModulesProxy` on iOS. ([#15847](https://github.com/expo/expo/pull/15847) by [@tsapeta](https://github.com/tsapeta))
63
+
64
+ ### 🐛 Bug fixes
65
+
66
+ - It's no longer possible to directly call methods from the `ModuleDefinition` in the `ViewManagers` on Android. ([#15741](https://github.com/expo/expo/pull/15741) by [@lukmccall](https://github.com/lukmccall))
67
+ - Fix compatibility with react-native 0.66. ([#15914](https://github.com/expo/expo/pull/15914) by [@kudo](https://github.com/kudo))
68
+ - Fix `Plugin with id 'maven' not found` build error from Android Gradle 7. ([#16080](https://github.com/expo/expo/pull/16080) by [@kudo](https://github.com/kudo))
69
+
13
70
  ## 0.6.5 — 2022-02-01
14
71
 
15
72
  ### 🐛 Bug fixes
package/README.md CHANGED
@@ -4,7 +4,7 @@ The core of Expo Modules architecture.
4
4
 
5
5
  # Installation in managed Expo projects
6
6
 
7
- For managed [managed](https://docs.expo.io/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects &mdash; it is likely to be included in an upcoming Expo SDK release.
7
+ For [managed](https://docs.expo.dev/versions/latest/introduction/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects &mdash; it is likely to be included in an upcoming Expo SDK release.
8
8
 
9
9
  # Installation in bare React Native projects
10
10
 
@@ -0,0 +1,15 @@
1
+ class KotlinExpoModulesCorePlugin implements Plugin<Project> {
2
+ void apply(Project project) {
3
+ project.buildscript {
4
+ project.ext.kotlinVersion = {
5
+ project.rootProject.ext.has("kotlinVersion")
6
+ ? project.rootProject.ext.get("kotlinVersion")
7
+ : "1.6.10"
8
+ }
9
+ }
10
+ }
11
+ }
12
+
13
+ ext.applyKotlinExpoModulesCorePlugin = {
14
+ apply plugin: KotlinExpoModulesCorePlugin
15
+ }
@@ -3,20 +3,35 @@ apply plugin: 'kotlin-android'
3
3
  apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.6.5'
6
+ version = '0.9.0'
7
7
 
8
8
  buildscript {
9
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
10
+ if (expoModulesCorePlugin.exists()) {
11
+ apply from: expoModulesCorePlugin
12
+ applyKotlinExpoModulesCorePlugin()
13
+ }
14
+
9
15
  // Simple helper that allows the root project to override versions declared by this library.
10
16
  ext.safeExtGet = { prop, fallback ->
11
17
  rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
12
18
  }
13
19
 
20
+ // Ensures backward compatibility
21
+ ext.getKotlinVersion = {
22
+ if (ext.has("kotlinVersion")) {
23
+ ext.kotlinVersion()
24
+ } else {
25
+ ext.safeExtGet("kotlinVersion", "1.6.10")
26
+ }
27
+ }
28
+
14
29
  repositories {
15
30
  mavenCentral()
16
31
  }
17
32
 
18
33
  dependencies {
19
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', '1.4.21')}")
34
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
20
35
  }
21
36
  }
22
37
 
@@ -44,26 +59,27 @@ afterEvaluate {
44
59
  }
45
60
 
46
61
  android {
47
- compileSdkVersion safeExtGet("compileSdkVersion", 30)
62
+ compileSdkVersion safeExtGet("compileSdkVersion", 31)
48
63
 
49
64
  compileOptions {
50
- sourceCompatibility JavaVersion.VERSION_1_8
51
- targetCompatibility JavaVersion.VERSION_1_8
65
+ sourceCompatibility JavaVersion.VERSION_11
66
+ targetCompatibility JavaVersion.VERSION_11
67
+ }
68
+
69
+ kotlinOptions {
70
+ jvmTarget = JavaVersion.VERSION_11.majorVersion
52
71
  }
53
72
 
54
73
  defaultConfig {
55
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
56
- targetSdkVersion safeExtGet("targetSdkVersion", 30)
75
+ targetSdkVersion safeExtGet("targetSdkVersion", 31)
57
76
  consumerProguardFiles 'proguard-rules.pro'
58
77
  versionCode 1
59
- versionName "0.6.5"
78
+ versionName "0.9.0"
60
79
  }
61
80
  lintOptions {
62
81
  abortOnError false
63
82
  }
64
- kotlinOptions {
65
- jvmTarget = JavaVersion.VERSION_1_8
66
- }
67
83
 
68
84
  testOptions {
69
85
  unitTests.all {
@@ -79,12 +95,10 @@ android {
79
95
  }
80
96
 
81
97
  dependencies {
82
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '1.4.21')}"
83
- implementation "org.jetbrains.kotlin:kotlin-reflect:${safeExtGet('kotlinVersion', '1.4.21')}"
98
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
99
+ implementation "org.jetbrains.kotlin:kotlin-reflect:${getKotlinVersion()}"
84
100
  implementation 'androidx.annotation:annotation:1.2.0'
85
-
86
- // used only in `expo.modules.core.errors.ModuleDestroyedException` for API export
87
- compileOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
101
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0"
88
102
 
89
103
  //noinspection GradleDynamicVersion
90
104
  implementation 'com.facebook.react:react-native:+'
@@ -93,6 +107,8 @@ dependencies {
93
107
  testImplementation 'junit:junit:4.13.1'
94
108
  testImplementation 'io.mockk:mockk:1.10.6'
95
109
  testImplementation "com.google.truth:truth:1.1.2"
110
+ testImplementation "org.robolectric:robolectric:4.5.1"
111
+ testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0"
96
112
  }
97
113
 
98
114
  /**
@@ -36,7 +36,7 @@ import javax.annotation.Nullable;
36
36
  */
37
37
  public class NativeModulesProxy extends ReactContextBaseJavaModule {
38
38
  private final static String NAME = "NativeUnimoduleProxy";
39
- private final static String VIEW_MANAGERS_NAMES_KEY = "viewManagersNames";
39
+ private final static String VIEW_MANAGERS_METADATA_KEY = "viewManagersMetadata";
40
40
  private final static String MODULES_CONSTANTS_KEY = "modulesConstants";
41
41
  private final static String EXPORTED_METHODS_KEY = "exportedMethods";
42
42
 
@@ -97,7 +97,7 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
97
97
 
98
98
  Map<String, Object> modulesConstants = new HashMap<>(exportedModules.size());
99
99
  Map<String, Object> exportedMethodsMap = new HashMap<>(exportedModules.size());
100
- List<String> viewManagersNames = new ArrayList<>(viewManagers.size());
100
+ Map<String, Object> viewManagersMetadata = new HashMap<>(viewManagers.size());
101
101
 
102
102
  for (ExportedModule exportedModule : exportedModules) {
103
103
  String moduleName = exportedModule.getName();
@@ -116,15 +116,15 @@ public class NativeModulesProxy extends ReactContextBaseJavaModule {
116
116
  }));
117
117
 
118
118
  for (ViewManager viewManager : viewManagers) {
119
- viewManagersNames.add(viewManager.getName());
119
+ viewManagersMetadata.put(viewManager.getName(), viewManager.getMetadata());
120
120
  }
121
121
 
122
- viewManagersNames.addAll(mKotlinInteropModuleRegistry.exportedViewManagersNames());
122
+ viewManagersMetadata.putAll(mKotlinInteropModuleRegistry.viewManagersMetadata());
123
123
 
124
124
  Map<String, Object> constants = new HashMap<>(3);
125
125
  constants.put(MODULES_CONSTANTS_KEY, modulesConstants);
126
126
  constants.put(EXPORTED_METHODS_KEY, exportedMethodsMap);
127
- constants.put(VIEW_MANAGERS_NAMES_KEY, viewManagersNames);
127
+ constants.put(VIEW_MANAGERS_METADATA_KEY, viewManagersMetadata);
128
128
  return constants;
129
129
  }
130
130
 
@@ -6,6 +6,7 @@ import android.util.Log;
6
6
  import android.view.View;
7
7
 
8
8
  import com.facebook.react.bridge.ReactContext;
9
+ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
9
10
  import com.facebook.react.uimanager.IllegalViewOperationException;
10
11
  import com.facebook.react.uimanager.NativeViewHierarchyManager;
11
12
  import com.facebook.react.uimanager.UIManagerModule;
@@ -115,6 +116,14 @@ public class UIManagerModuleWrapper implements
115
116
  }
116
117
  }
117
118
 
119
+ public void runOnNativeModulesQueueThread(Runnable runnable) {
120
+ if (mReactContext.isOnNativeModulesQueueThread()) {
121
+ runnable.run();
122
+ } else {
123
+ mReactContext.runOnNativeModulesQueueThread(runnable);
124
+ }
125
+ }
126
+
118
127
 
119
128
  @Override
120
129
  public void registerLifecycleEventListener(final LifecycleEventListener listener) {
@@ -188,6 +197,10 @@ public class UIManagerModuleWrapper implements
188
197
  return mReactContext.getJavaScriptContextHolder().get();
189
198
  }
190
199
 
200
+ public CallInvokerHolderImpl getJSCallInvokerHolder() {
201
+ return (CallInvokerHolderImpl) mReactContext.getCatalystInstance().getJSCallInvokerHolder();
202
+ }
203
+
191
204
  @Override
192
205
  public Activity getCurrentActivity() {
193
206
  return getContext().getCurrentActivity();
@@ -50,6 +50,15 @@ public abstract class ViewManager<V extends View> implements RegistryLifecycleLi
50
50
  // by default do nothing
51
51
  }
52
52
 
53
+ /**
54
+ * Returns a map of view manager's metadata that will be exposed to JavaScript.
55
+ */
56
+ public Map<String, Object> getMetadata() {
57
+ Map<String, Object> metadata = new HashMap<>();
58
+ metadata.put("propsNames", getPropSetters().keySet().toArray());
59
+ return metadata;
60
+ }
61
+
53
62
  /**
54
63
  * Returns a map of { propName => propInfo } so that platform adapter knows value of what class
55
64
  * does the propsetter expect.
@@ -1,5 +1,9 @@
1
1
  package expo.modules.core.interfaces;
2
2
 
3
+ import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
4
+
3
5
  public interface JavaScriptContextProvider {
4
6
  long getJavaScriptContextRef();
7
+
8
+ CallInvokerHolderImpl getJSCallInvokerHolder();
5
9
  }
@@ -1,12 +1,17 @@
1
1
  package expo.modules.core.interfaces;
2
2
 
3
3
  import android.app.Activity;
4
+ import android.view.KeyEvent;
5
+ import android.view.ViewGroup;
6
+
7
+ import com.facebook.react.ReactActivity;
8
+ import com.facebook.react.ReactActivityDelegate;
4
9
  import com.facebook.react.ReactRootView;
5
10
 
6
11
  import androidx.annotation.Nullable;
7
12
 
8
13
  /**
9
- * A handler API for modules to override default ReactActivity behaviors.
14
+ * A handler API for modules to override default ReactActivityDelegate behaviors.
10
15
  * Used by {@link ReactActivityDelegateWrapper}
11
16
  */
12
17
  public interface ReactActivityHandler {
@@ -18,4 +23,35 @@ public interface ReactActivityHandler {
18
23
  default ReactRootView createReactRootView(Activity activity) {
19
24
  return null;
20
25
  }
26
+
27
+ /**
28
+ * Gives modules a chance to create a ViewGroup that is used as a container for the ReactRootView,
29
+ * which is added as a child to the container if non-null.
30
+ * @return a ViewGroup to be used as a container, or null if no container is needed
31
+ */
32
+ @Nullable
33
+ default ViewGroup createReactRootViewContainer(Activity activity) {
34
+ return null;
35
+ }
36
+
37
+ /**
38
+ * Gives modules a chance to respond to `onKeyUp` events. Every listener will receive this
39
+ * callback, but the delegate will not receive the event unless if any of the listeners consume it
40
+ * (i.e. return `true` from this method).
41
+ * `ReactActivityDelegateWrapper.onKeyUp` will return `true` if any module returns `true`.
42
+ *
43
+ * @return true if this module wants to return `true` from `ReactActivityDelegateWrapper.onKeyUp`
44
+ */
45
+ default boolean onKeyUp(int keyCode, KeyEvent event) {
46
+ return false;
47
+ }
48
+
49
+ /**
50
+ * Gives modules a chance to override the wrapped ReactActivityDelegate instance.
51
+ * @return a new ReactActivityDelegate instance, or null if not to override
52
+ */
53
+ @Nullable
54
+ default ReactActivityDelegate onDidCreateReactActivityDelegate(ReactActivity activity, ReactActivityDelegate delegate) {
55
+ return null;
56
+ }
21
57
  }
@@ -2,6 +2,7 @@ package expo.modules.core.interfaces;
2
2
 
3
3
  import com.facebook.react.ReactInstanceManager;
4
4
  import com.facebook.react.bridge.JavaScriptContextHolder;
5
+ import com.facebook.react.bridge.JavaScriptExecutorFactory;
5
6
  import com.facebook.react.bridge.ReactApplicationContext;
6
7
 
7
8
  import androidx.annotation.Nullable;
@@ -42,6 +43,35 @@ public interface ReactNativeHostHandler {
42
43
  return null;
43
44
  }
44
45
 
46
+ /**
47
+ * Give modules a chance to override the value for useDeveloperSupport,
48
+ * e.g. for expo-dev-launcher
49
+ *
50
+ * @return value for useDeveloperSupport, or null if not to override
51
+ */
52
+ @Nullable
53
+ default Boolean getUseDeveloperSupport() {
54
+ return null;
55
+ }
56
+
57
+ /**
58
+ * Given chance for modules to override react dev support manager factory.
59
+ * e.g. for expo-dev-client
60
+ *
61
+ * Note: we can't specify the type here, because the `DevSupportManagerFactory`
62
+ * doesn't exist in the React Native 0.66 or below.
63
+ *
64
+ * @return custom DevSupportManagerFactory, or null if not to override
65
+ */
66
+ @Nullable
67
+ default Object getDevSupportManagerFactory() { return null; }
68
+
69
+ /**
70
+ * Given chance for modules to override the javascript executor factory.
71
+ */
72
+ @Nullable
73
+ default JavaScriptExecutorFactory getJavaScriptExecutorFactory() { return null; }
74
+
45
75
  //region event listeners
46
76
 
47
77
  /**
@@ -28,6 +28,8 @@ public interface UIManager {
28
28
 
29
29
  void runOnClientCodeQueueThread(Runnable runnable);
30
30
 
31
+ void runOnNativeModulesQueueThread(Runnable runnable);
32
+
31
33
  void registerLifecycleEventListener(LifecycleEventListener listener);
32
34
 
33
35
  void unregisterLifecycleEventListener(LifecycleEventListener listener);
@@ -5,7 +5,6 @@ import android.content.Context
5
5
  import android.content.Intent
6
6
  import com.facebook.react.bridge.ReactApplicationContext
7
7
  import expo.modules.core.interfaces.ActivityProvider
8
- import expo.modules.core.interfaces.services.EventEmitter
9
8
  import expo.modules.interfaces.barcodescanner.BarCodeScannerInterface
10
9
  import expo.modules.interfaces.camera.CameraViewInterface
11
10
  import expo.modules.interfaces.constants.ConstantsInterface
@@ -15,8 +14,11 @@ import expo.modules.interfaces.imageloader.ImageLoaderInterface
15
14
  import expo.modules.interfaces.permissions.Permissions
16
15
  import expo.modules.interfaces.sensors.SensorServiceInterface
17
16
  import expo.modules.interfaces.taskManager.TaskManagerInterface
17
+ import expo.modules.kotlin.defaultmodules.ErrorManagerModule
18
+ import expo.modules.kotlin.events.EventEmitter
18
19
  import expo.modules.kotlin.events.EventName
19
20
  import expo.modules.kotlin.events.KEventEmitterWrapper
21
+ import expo.modules.kotlin.events.KModuleEventEmitterWrapper
20
22
  import expo.modules.kotlin.events.OnActivityResultPayload
21
23
  import expo.modules.kotlin.modules.Module
22
24
  import java.lang.ref.WeakReference
@@ -26,7 +28,10 @@ class AppContext(
26
28
  val legacyModuleRegistry: expo.modules.core.ModuleRegistry,
27
29
  private val reactContextHolder: WeakReference<ReactApplicationContext>
28
30
  ) {
29
- val registry = ModuleRegistry(WeakReference(this)).register(modulesProvider)
31
+ val registry = ModuleRegistry(WeakReference(this)).apply {
32
+ register(ErrorManagerModule())
33
+ register(modulesProvider)
34
+ }
30
35
  private val reactLifecycleDelegate = ReactLifecycleDelegate(this)
31
36
 
32
37
  init {
@@ -119,18 +124,31 @@ class AppContext(
119
124
  * Provides access to the event emitter
120
125
  */
121
126
  fun eventEmitter(module: Module): EventEmitter? {
122
- val legacyEventEmitter = legacyModule<EventEmitter>() ?: return null
123
- return KEventEmitterWrapper(
127
+ val legacyEventEmitter = legacyModule<expo.modules.core.interfaces.services.EventEmitter>()
128
+ ?: return null
129
+ return KModuleEventEmitterWrapper(
124
130
  requireNotNull(registry.getModuleHolder(module)) {
125
131
  "Cannot create an event emitter for the module that isn't present in the module registry."
126
132
  },
127
- legacyEventEmitter
133
+ legacyEventEmitter,
134
+ reactContextHolder
128
135
  )
129
136
  }
130
137
 
138
+ internal val callbackInvoker: EventEmitter?
139
+ get() {
140
+ val legacyEventEmitter = legacyModule<expo.modules.core.interfaces.services.EventEmitter>()
141
+ ?: return null
142
+ return KEventEmitterWrapper(legacyEventEmitter, reactContextHolder)
143
+ }
144
+
145
+ internal val errorManager: ErrorManagerModule?
146
+ get() = registry.getModule()
147
+
131
148
  fun onDestroy() {
132
149
  reactContextHolder.get()?.removeLifecycleEventListener(reactLifecycleDelegate)
133
150
  registry.post(EventName.MODULE_DESTROY)
151
+ registry.cleanUp()
134
152
  }
135
153
 
136
154
  fun onHostResume() {
@@ -3,7 +3,9 @@ package expo.modules.kotlin
3
3
  import com.facebook.react.bridge.Dynamic
4
4
 
5
5
  inline fun <T> Dynamic.recycle(block: Dynamic.() -> T): T {
6
- val result = block(this)
7
- this.recycle()
8
- return result
6
+ try {
7
+ return block(this)
8
+ } finally {
9
+ this.recycle()
10
+ }
9
11
  }
@@ -1,20 +1,15 @@
1
1
  package expo.modules.kotlin
2
2
 
3
- import android.os.Bundle
4
- import com.facebook.react.bridge.Arguments
3
+ import expo.modules.kotlin.types.JSTypeConverter
5
4
 
6
5
  class KPromiseWrapper(
7
6
  private val bridgePromise: com.facebook.react.bridge.Promise
8
7
  ) : Promise {
9
8
 
9
+ @Suppress("UNCHECKED_CAST")
10
10
  override fun resolve(value: Any?) {
11
11
  bridgePromise.resolve(
12
- when (value) {
13
- is Unit -> null
14
- is Bundle -> Arguments.fromBundle(value as Bundle?)
15
- is List<*> -> Arguments.fromList(value as List<*>?)
16
- else -> value
17
- }
12
+ JSTypeConverter.convertToJSValue(value)
18
13
  )
19
14
  }
20
15
 
@@ -3,6 +3,8 @@ package expo.modules.kotlin
3
3
  import com.facebook.react.bridge.ReactApplicationContext
4
4
  import com.facebook.react.bridge.ReadableArray
5
5
  import com.facebook.react.uimanager.ViewManager
6
+ import expo.modules.kotlin.exception.CodedException
7
+ import expo.modules.kotlin.exception.UnexpectedException
6
8
  import expo.modules.kotlin.views.GroupViewManagerWrapper
7
9
  import expo.modules.kotlin.views.SimpleViewManagerWrapper
8
10
  import expo.modules.kotlin.views.ViewManagerWrapperDelegate
@@ -18,7 +20,7 @@ class KotlinInteropModuleRegistry(
18
20
  legacyModuleRegistry: expo.modules.core.ModuleRegistry,
19
21
  reactContext: WeakReference<ReactApplicationContext>
20
22
  ) {
21
- private val appContext = AppContext(modulesProvider, legacyModuleRegistry, reactContext)
23
+ internal val appContext = AppContext(modulesProvider, legacyModuleRegistry, reactContext)
22
24
 
23
25
  private val registry: ModuleRegistry
24
26
  get() = appContext.registry
@@ -26,9 +28,16 @@ class KotlinInteropModuleRegistry(
26
28
  fun hasModule(name: String): Boolean = registry.hasModule(name)
27
29
 
28
30
  fun callMethod(moduleName: String, method: String, arguments: ReadableArray, promise: Promise) {
29
- registry
30
- .getModuleHolder(moduleName)
31
- ?.call(method, arguments, promise)
31
+ try {
32
+ requireNotNull(
33
+ registry.getModuleHolder(moduleName)
34
+ ) { "Trying to call '$method' on the non-existing module '$moduleName'" }
35
+ .call(method, arguments, promise)
36
+ } catch (e: CodedException) {
37
+ promise.reject(e)
38
+ } catch (e: Throwable) {
39
+ promise.reject(UnexpectedException(e))
40
+ }
32
41
  }
33
42
 
34
43
  fun exportedModulesConstants(): Map<ModuleName, ModuleConstants> {
@@ -66,6 +75,17 @@ class KotlinInteropModuleRegistry(
66
75
  }
67
76
  }
68
77
 
78
+ fun viewManagersMetadata(): Map<String, Map<String, Any>> {
79
+ return registry
80
+ .filter { it.definition.viewManagerDefinition != null }
81
+ .map { holder ->
82
+ holder.name to mapOf(
83
+ "propsNames" to (holder.definition.viewManagerDefinition?.propsNames ?: emptyList())
84
+ )
85
+ }
86
+ .toMap()
87
+ }
88
+
69
89
  fun extractViewManagersDelegateHolders(viewManagers: List<ViewManager<*, *>>): List<ViewWrapperDelegateHolder> =
70
90
  viewManagers.filterIsInstance<ViewWrapperDelegateHolder>()
71
91
 
@@ -87,11 +107,6 @@ class KotlinInteropModuleRegistry(
87
107
  }
88
108
  }
89
109
 
90
- fun exportedViewManagersNames(): List<String> =
91
- registry
92
- .filter { it.definition.viewManagerDefinition != null }
93
- .map { it.definition.name }
94
-
95
110
  fun onDestroy() {
96
111
  appContext.onDestroy()
97
112
  }
@@ -1,25 +1,26 @@
1
1
  package expo.modules.kotlin
2
2
 
3
3
  import com.facebook.react.bridge.ReadableArray
4
- import expo.modules.core.utilities.ifNull
5
4
  import expo.modules.kotlin.events.BasicEventListener
6
5
  import expo.modules.kotlin.events.EventListenerWithPayload
7
6
  import expo.modules.kotlin.events.EventListenerWithSenderAndPayload
8
7
  import expo.modules.kotlin.events.EventName
8
+ import expo.modules.kotlin.exception.FunctionCallException
9
9
  import expo.modules.kotlin.exception.MethodNotFoundException
10
+ import expo.modules.kotlin.exception.exceptionDecorator
10
11
  import expo.modules.kotlin.modules.Module
11
12
 
12
13
  class ModuleHolder(val module: Module) {
13
14
  val definition = module.definition()
14
15
  val name get() = definition.name
15
16
 
16
- fun call(methodName: String, args: ReadableArray, promise: Promise) {
17
- val method = definition.methods[methodName].ifNull {
18
- promise.reject(MethodNotFoundException(methodName, definition.name))
19
- return
20
- }
17
+ fun call(methodName: String, args: ReadableArray, promise: Promise) = exceptionDecorator({
18
+ FunctionCallException(methodName, definition.name, it)
19
+ }) {
20
+ val method = definition.methods[methodName]
21
+ ?: throw MethodNotFoundException()
21
22
 
22
- method.call(args, promise)
23
+ method.call(this, args, promise)
23
24
  }
24
25
 
25
26
  fun post(eventName: EventName) {
@@ -38,4 +39,8 @@ class ModuleHolder(val module: Module) {
38
39
  val listener = definition.eventListeners[eventName] ?: return
39
40
  (listener as? EventListenerWithSenderAndPayload<Sender, Payload>)?.call(sender, payload)
40
41
  }
42
+
43
+ fun cleanUp() {
44
+ module.cleanUp()
45
+ }
41
46
  }
@@ -2,16 +2,28 @@ package expo.modules.kotlin
2
2
 
3
3
  import expo.modules.kotlin.events.EventName
4
4
  import expo.modules.kotlin.modules.Module
5
+ import kotlinx.coroutines.CoroutineName
6
+ import kotlinx.coroutines.CoroutineScope
7
+ import kotlinx.coroutines.Dispatchers
8
+ import kotlinx.coroutines.SupervisorJob
5
9
  import java.lang.ref.WeakReference
6
10
 
7
11
  class ModuleRegistry(
8
12
  private val appContext: WeakReference<AppContext>
9
13
  ) : Iterable<ModuleHolder> {
10
- private val registry = mutableMapOf<String, ModuleHolder>()
14
+ @PublishedApi
15
+ internal val registry = mutableMapOf<String, ModuleHolder>()
11
16
 
12
17
  fun register(module: Module) {
13
18
  val holder = ModuleHolder(module)
14
19
  module._appContext = requireNotNull(appContext.get()) { "Cannot create a module for invalid app context." }
20
+ module.coroutineScopeDelegate = lazy {
21
+ CoroutineScope(
22
+ Dispatchers.Default +
23
+ SupervisorJob() +
24
+ CoroutineName(holder.definition.name)
25
+ )
26
+ }
15
27
  holder.post(EventName.MODULE_CREATE)
16
28
  registry[holder.name] = holder
17
29
  }
@@ -27,6 +39,10 @@ class ModuleRegistry(
27
39
 
28
40
  fun getModule(name: String): Module? = registry[name]?.module
29
41
 
42
+ inline fun <reified T> getModule(): T? {
43
+ return registry.values.find { it.module is T }?.module as? T
44
+ }
45
+
30
46
  fun getModuleHolder(name: String): ModuleHolder? = registry[name]
31
47
 
32
48
  fun getModuleHolder(module: Module): ModuleHolder? =
@@ -53,4 +69,10 @@ class ModuleRegistry(
53
69
  }
54
70
 
55
71
  override fun iterator(): Iterator<ModuleHolder> = registry.values.iterator()
72
+
73
+ fun cleanUp() {
74
+ forEach {
75
+ it.cleanUp()
76
+ }
77
+ }
56
78
  }