expo-modules-core 0.7.0 → 0.9.1

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 (129) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +1 -1
  3. package/android/ExpoModulesCorePlugin.gradle +15 -0
  4. package/android/build.gradle +46 -32
  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 +13 -5
  13. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +2 -13
  14. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +11 -5
  15. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +5 -1
  16. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +17 -0
  17. package/android/src/main/java/expo/modules/kotlin/callbacks/ViewCallback.kt +14 -3
  18. package/android/src/main/java/expo/modules/kotlin/events/EventEmitter.kt +13 -0
  19. package/android/src/main/java/expo/modules/kotlin/events/KModuleEventEmitterWrapper.kt +102 -0
  20. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +25 -1
  21. package/android/src/main/java/expo/modules/kotlin/{methods/AnyMethod.kt → functions/AnyFunction.kt} +6 -5
  22. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +15 -0
  23. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +170 -0
  24. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +15 -0
  25. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +36 -0
  26. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +14 -0
  27. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +374 -41
  28. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +2 -2
  29. package/android/src/main/java/expo/modules/kotlin/records/FieldValidator.kt +139 -0
  30. package/android/src/main/java/expo/modules/kotlin/records/Record.kt +0 -39
  31. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +59 -10
  32. package/android/src/main/java/expo/modules/kotlin/records/Required.kt +5 -0
  33. package/android/src/main/java/expo/modules/kotlin/records/ValidationBinder.kt +110 -0
  34. package/android/src/main/java/expo/modules/kotlin/records/Validators.kt +61 -0
  35. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverter.kt +35 -0
  36. package/android/src/main/java/expo/modules/kotlin/types/JSTypeConverterHelper.kt +148 -0
  37. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +9 -1
  38. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +49 -0
  39. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinition.kt +18 -0
  40. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +114 -0
  41. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +4 -1
  42. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +56 -5
  43. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +3 -0
  44. package/build/NativeModulesProxy.native.d.ts +0 -4
  45. package/build/NativeModulesProxy.native.d.ts.map +1 -1
  46. package/build/NativeModulesProxy.native.js +1 -14
  47. package/build/NativeModulesProxy.native.js.map +1 -1
  48. package/build/NativeModulesProxy.types.d.ts +0 -3
  49. package/build/NativeModulesProxy.types.d.ts.map +1 -1
  50. package/build/NativeModulesProxy.types.js.map +1 -1
  51. package/build/NativeViewManagerAdapter.native.d.ts.map +1 -1
  52. package/build/NativeViewManagerAdapter.native.js +9 -33
  53. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  54. package/build/sweet/NativeErrorManager.js +1 -1
  55. package/build/sweet/NativeErrorManager.js.map +1 -1
  56. package/ios/AppDelegates/EXAppDelegatesLoader.m +4 -8
  57. package/ios/AppDelegates/ExpoAppDelegate.swift +4 -10
  58. package/ios/EXAppDefines.h +1 -0
  59. package/ios/EXAppDefines.m +6 -0
  60. package/ios/EXUtilities.h +2 -0
  61. package/ios/EXUtilities.m +12 -0
  62. package/ios/ExpoModulesCore.h +4 -0
  63. package/ios/ExpoModulesCore.podspec +4 -2
  64. package/ios/Interfaces/FileSystem/EXFileSystemInterface.h +1 -1
  65. package/ios/Interfaces/TaskManager/EXTaskServiceInterface.h +1 -0
  66. package/ios/JSI/{JSIConversions.h → EXJSIConversions.h} +4 -1
  67. package/ios/JSI/{JSIConversions.mm → EXJSIConversions.mm} +16 -5
  68. package/ios/JSI/{JSIInstaller.h → EXJSIInstaller.h} +3 -3
  69. package/ios/JSI/EXJSIInstaller.mm +17 -0
  70. package/ios/JSI/{ExpoModulesProxySpec.h → EXJSIUtils.h} +0 -9
  71. package/ios/JSI/{ExpoModulesProxySpec.mm → EXJSIUtils.mm} +4 -48
  72. package/ios/JSI/EXJavaScriptObject.h +97 -0
  73. package/ios/JSI/EXJavaScriptObject.mm +121 -0
  74. package/ios/JSI/{JavaScriptRuntime.h → EXJavaScriptRuntime.h} +27 -8
  75. package/ios/JSI/EXJavaScriptRuntime.mm +153 -0
  76. package/ios/JSI/EXJavaScriptValue.h +57 -0
  77. package/ios/JSI/EXJavaScriptValue.mm +166 -0
  78. package/ios/JSI/ExpoModulesHostObject.mm +2 -1
  79. package/ios/JSI/JavaScriptRuntime.swift +32 -0
  80. package/ios/JSI/JavaScriptValue.swift +94 -0
  81. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -11
  82. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +2 -2
  83. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +24 -22
  84. package/ios/ReactDelegates/EXReactCompatibleHelpers.h +18 -0
  85. package/ios/ReactDelegates/EXReactCompatibleHelpers.m +19 -0
  86. package/ios/ReactDelegates/ExpoReactDelegate.swift +2 -2
  87. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +1 -1
  88. package/ios/Swift/AppContext.swift +21 -2
  89. package/ios/Swift/Arguments/AnyArgumentType.swift +1 -1
  90. package/ios/Swift/Functions/AnyFunction.swift +5 -0
  91. package/ios/Swift/Functions/AsyncFunctionComponent.swift +182 -0
  92. package/ios/Swift/Functions/ConcreteFunction.swift +40 -68
  93. package/ios/Swift/Functions/SyncFunctionComponent.swift +181 -0
  94. package/ios/Swift/JavaScriptUtils.swift +56 -0
  95. package/ios/Swift/ModuleHolder.swift +17 -5
  96. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +66 -44
  97. package/ios/Swift/ModulesProvider.swift +3 -10
  98. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +49 -0
  99. package/ios/Swift/SwiftInteropBridge.swift +14 -5
  100. package/ios/Swift/Views/ComponentData.swift +2 -1
  101. package/ios/Swift/Views/ExpoView.swift +8 -0
  102. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +23 -0
  103. package/ios/Swift.h +5 -0
  104. package/ios/Tests/ArgumentTypeSpec.swift +2 -3
  105. package/ios/Tests/ConstantsSpec.swift +6 -7
  106. package/ios/Tests/ConvertiblesSpec.swift +2 -3
  107. package/ios/Tests/ExceptionsSpec.swift +2 -3
  108. package/ios/Tests/ExpoModulesSpec.swift +75 -0
  109. package/ios/Tests/FunctionSpec.swift +13 -15
  110. package/ios/Tests/FunctionWithConvertiblesSpec.swift +4 -5
  111. package/ios/Tests/JavaScriptObjectSpec.swift +97 -0
  112. package/ios/Tests/JavaScriptRuntimeSpec.swift +94 -0
  113. package/ios/Tests/ModuleEventListenersSpec.swift +15 -16
  114. package/ios/Tests/ModuleRegistrySpec.swift +2 -3
  115. package/ios/Tests/RecordSpec.swift +2 -3
  116. package/package.json +2 -2
  117. package/src/NativeModulesProxy.native.ts +2 -22
  118. package/src/NativeModulesProxy.types.ts +0 -8
  119. package/src/NativeViewManagerAdapter.native.tsx +12 -28
  120. package/src/sweet/NativeErrorManager.ts +1 -1
  121. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +0 -26
  122. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +0 -14
  123. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +0 -15
  124. package/ios/JSI/JSIInstaller.mm +0 -34
  125. package/ios/JSI/JavaScriptObject.h +0 -60
  126. package/ios/JSI/JavaScriptObject.mm +0 -93
  127. package/ios/JSI/JavaScriptRuntime.mm +0 -102
  128. package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.h +0 -16
  129. package/ios/NativeModulesProxy/EXComponentDataCompatibleWrapper.m +0 -28
package/CHANGELOG.md CHANGED
@@ -10,6 +10,48 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.9.1 — 2022-05-05
14
+
15
+ ### 🐛 Bug fixes
16
+
17
+ - Fix modules have not been deallocated during the application reload on iOS. ([#17285](https://github.com/expo/expo/pull/17285) by [@lukmccall](https://github.com/lukmccall))
18
+
19
+ ## 0.9.0 — 2022-04-21
20
+
21
+ ### ⚠️ Notices
22
+
23
+ - 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))
24
+
25
+ ### 🎉 New features
26
+
27
+ - 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))
28
+
29
+ ## 0.8.0 — 2022-04-18
30
+
31
+ ### 🛠 Breaking changes
32
+
33
+ - 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))
34
+
35
+ ### ⚠️ Notices
36
+
37
+ - 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))
38
+ - 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))
39
+
40
+ ### 🎉 New features
41
+
42
+ - Add `getDevSupportManagerFactory` support to `ReactNativeHostHandler`. ([#16434](https://github.com/expo/expo/pull/16434) by [@lukmccall](https://github.com/lukmccall))
43
+ - 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))
44
+ - Stopped relying on deprecated `ViewPropTypes` from React Native. ([#16207](https://github.com/expo/expo/pull/16207) by [@tsapeta](https://github.com/tsapeta))
45
+ - 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))
46
+
47
+ ### 🐛 Bug fixes
48
+
49
+ - 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))
50
+
51
+ ### 💡 Others
52
+
53
+ - 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))
54
+
13
55
  ## 0.7.0 — 2022-01-26
14
56
 
15
57
  ### 🎉 New features
@@ -29,6 +71,13 @@
29
71
 
30
72
  - 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))
31
73
  - Fix compatibility with react-native 0.66. ([#15914](https://github.com/expo/expo/pull/15914) by [@kudo](https://github.com/kudo))
74
+ - 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))
75
+
76
+ ## 0.6.5 — 2022-02-01
77
+
78
+ ### 🐛 Bug fixes
79
+
80
+ - 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))
32
81
 
33
82
  ## 0.6.4 — 2022-01-05
34
83
 
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](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 — 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 — 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
+ }
@@ -1,71 +1,85 @@
1
1
  apply plugin: 'com.android.library'
2
2
  apply plugin: 'kotlin-android'
3
- apply plugin: 'maven'
3
+ apply plugin: 'maven-publish'
4
4
 
5
5
  group = 'host.exp.exponent'
6
- version = '0.7.0'
6
+ version = '0.9.1'
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.6.10')}")
34
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getKotlinVersion()}")
20
35
  }
21
36
  }
22
37
 
23
- //Upload android library to maven with javadoc and android sources
24
- configurations {
25
- deployerJars
26
- }
27
-
28
- //Creating sources with comments
38
+ // Creating sources with comments
29
39
  task androidSourcesJar(type: Jar) {
30
40
  classifier = 'sources'
31
41
  from android.sourceSets.main.java.srcDirs
32
42
  }
33
43
 
34
- //Put the androidSources and javadoc to the artifacts
35
- artifacts {
36
- archives androidSourcesJar
37
- }
38
-
39
- uploadArchives {
40
- repositories {
41
- mavenDeployer {
42
- configuration = configurations.deployerJars
43
- repository(url: mavenLocal().url)
44
+ afterEvaluate {
45
+ publishing {
46
+ publications {
47
+ release(MavenPublication) {
48
+ from components.release
49
+ // Add additional sourcesJar to artifacts
50
+ artifact(androidSourcesJar)
51
+ }
52
+ }
53
+ repositories {
54
+ maven {
55
+ url = mavenLocal().url
56
+ }
44
57
  }
45
58
  }
46
59
  }
47
60
 
48
61
  android {
49
- compileSdkVersion safeExtGet("compileSdkVersion", 30)
62
+ compileSdkVersion safeExtGet("compileSdkVersion", 31)
50
63
 
51
64
  compileOptions {
52
- sourceCompatibility JavaVersion.VERSION_1_8
53
- 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
54
71
  }
55
72
 
56
73
  defaultConfig {
57
74
  minSdkVersion safeExtGet("minSdkVersion", 21)
58
- targetSdkVersion safeExtGet("targetSdkVersion", 30)
75
+ targetSdkVersion safeExtGet("targetSdkVersion", 31)
59
76
  consumerProguardFiles 'proguard-rules.pro'
60
77
  versionCode 1
61
- versionName "0.7.0"
78
+ versionName "0.9.1"
62
79
  }
63
80
  lintOptions {
64
81
  abortOnError false
65
82
  }
66
- kotlinOptions {
67
- jvmTarget = JavaVersion.VERSION_1_8
68
- }
69
83
 
70
84
  testOptions {
71
85
  unitTests.all {
@@ -81,12 +95,10 @@ android {
81
95
  }
82
96
 
83
97
  dependencies {
84
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${safeExtGet('kotlinVersion', '1.6.10')}"
85
- implementation "org.jetbrains.kotlin:kotlin-reflect:${safeExtGet('kotlinVersion', '1.6.10')}"
98
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}"
99
+ implementation "org.jetbrains.kotlin:kotlin-reflect:${getKotlinVersion()}"
86
100
  implementation 'androidx.annotation:annotation:1.2.0'
87
-
88
- // used only in `expo.modules.core.errors.ModuleDestroyedException` for API export
89
- compileOnly("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3")
101
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0"
90
102
 
91
103
  //noinspection GradleDynamicVersion
92
104
  implementation 'com.facebook.react:react-native:+'
@@ -95,6 +107,8 @@ dependencies {
95
107
  testImplementation 'junit:junit:4.13.1'
96
108
  testImplementation 'io.mockk:mockk:1.10.6'
97
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"
98
112
  }
99
113
 
100
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
@@ -16,8 +15,10 @@ import expo.modules.interfaces.permissions.Permissions
16
15
  import expo.modules.interfaces.sensors.SensorServiceInterface
17
16
  import expo.modules.interfaces.taskManager.TaskManagerInterface
18
17
  import expo.modules.kotlin.defaultmodules.ErrorManagerModule
18
+ import expo.modules.kotlin.events.EventEmitter
19
19
  import expo.modules.kotlin.events.EventName
20
20
  import expo.modules.kotlin.events.KEventEmitterWrapper
21
+ import expo.modules.kotlin.events.KModuleEventEmitterWrapper
21
22
  import expo.modules.kotlin.events.OnActivityResultPayload
22
23
  import expo.modules.kotlin.modules.Module
23
24
  import java.lang.ref.WeakReference
@@ -123,17 +124,23 @@ class AppContext(
123
124
  * Provides access to the event emitter
124
125
  */
125
126
  fun eventEmitter(module: Module): EventEmitter? {
126
- val legacyEventEmitter = legacyModule<EventEmitter>() ?: return null
127
- return KEventEmitterWrapper(
127
+ val legacyEventEmitter = legacyModule<expo.modules.core.interfaces.services.EventEmitter>()
128
+ ?: return null
129
+ return KModuleEventEmitterWrapper(
128
130
  requireNotNull(registry.getModuleHolder(module)) {
129
131
  "Cannot create an event emitter for the module that isn't present in the module registry."
130
132
  },
131
- legacyEventEmitter
133
+ legacyEventEmitter,
134
+ reactContextHolder
132
135
  )
133
136
  }
134
137
 
135
138
  internal val callbackInvoker: EventEmitter?
136
- get() = legacyModule()
139
+ get() {
140
+ val legacyEventEmitter = legacyModule<expo.modules.core.interfaces.services.EventEmitter>()
141
+ ?: return null
142
+ return KEventEmitterWrapper(legacyEventEmitter, reactContextHolder)
143
+ }
137
144
 
138
145
  internal val errorManager: ErrorManagerModule?
139
146
  get() = registry.getModule()
@@ -141,6 +148,7 @@ class AppContext(
141
148
  fun onDestroy() {
142
149
  reactContextHolder.get()?.removeLifecycleEventListener(reactLifecycleDelegate)
143
150
  registry.post(EventName.MODULE_DESTROY)
151
+ registry.cleanUp()
144
152
  }
145
153
 
146
154
  fun onHostResume() {
@@ -1,9 +1,6 @@
1
1
  package expo.modules.kotlin
2
2
 
3
- import android.os.Bundle
4
- import com.facebook.react.bridge.Arguments
5
- import expo.modules.kotlin.records.Record
6
- import expo.modules.kotlin.records.toJSMap
3
+ import expo.modules.kotlin.types.JSTypeConverter
7
4
 
8
5
  class KPromiseWrapper(
9
6
  private val bridgePromise: com.facebook.react.bridge.Promise
@@ -12,15 +9,7 @@ class KPromiseWrapper(
12
9
  @Suppress("UNCHECKED_CAST")
13
10
  override fun resolve(value: Any?) {
14
11
  bridgePromise.resolve(
15
- when (value) {
16
- is Unit -> null
17
- is Bundle -> Arguments.fromBundle(value)
18
- is List<*> -> Arguments.fromList(value)
19
- is Array<*> -> Arguments.fromArray(value)
20
- is Map<*, *> -> Arguments.makeNativeMap(value as Map<String, Any?>) // TODO(@lukmccall): add more sophisticated conversion method
21
- is Record -> value.toJSMap()
22
- else -> value
23
- }
12
+ JSTypeConverter.convertToJSValue(value)
24
13
  )
25
14
  }
26
15
 
@@ -75,6 +75,17 @@ class KotlinInteropModuleRegistry(
75
75
  }
76
76
  }
77
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
+
78
89
  fun extractViewManagersDelegateHolders(viewManagers: List<ViewManager<*, *>>): List<ViewWrapperDelegateHolder> =
79
90
  viewManagers.filterIsInstance<ViewWrapperDelegateHolder>()
80
91
 
@@ -96,11 +107,6 @@ class KotlinInteropModuleRegistry(
96
107
  }
97
108
  }
98
109
 
99
- fun exportedViewManagersNames(): List<String> =
100
- registry
101
- .filter { it.definition.viewManagerDefinition != null }
102
- .map { it.definition.name }
103
-
104
110
  fun onDestroy() {
105
111
  appContext.onDestroy()
106
112
  }
@@ -20,7 +20,7 @@ class ModuleHolder(val module: Module) {
20
20
  val method = definition.methods[methodName]
21
21
  ?: throw MethodNotFoundException()
22
22
 
23
- method.call(args, promise)
23
+ method.call(this, args, promise)
24
24
  }
25
25
 
26
26
  fun post(eventName: EventName) {
@@ -39,4 +39,8 @@ class ModuleHolder(val module: Module) {
39
39
  val listener = definition.eventListeners[eventName] ?: return
40
40
  (listener as? EventListenerWithSenderAndPayload<Sender, Payload>)?.call(sender, payload)
41
41
  }
42
+
43
+ fun cleanUp() {
44
+ module.cleanUp()
45
+ }
42
46
  }
@@ -2,6 +2,10 @@ 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(
@@ -13,6 +17,13 @@ class ModuleRegistry(
13
17
  fun register(module: Module) {
14
18
  val holder = ModuleHolder(module)
15
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
+ }
16
27
  holder.post(EventName.MODULE_CREATE)
17
28
  registry[holder.name] = holder
18
29
  }
@@ -58,4 +69,10 @@ class ModuleRegistry(
58
69
  }
59
70
 
60
71
  override fun iterator(): Iterator<ModuleHolder> = registry.values.iterator()
72
+
73
+ fun cleanUp() {
74
+ forEach {
75
+ it.cleanUp()
76
+ }
77
+ }
61
78
  }
@@ -1,10 +1,12 @@
1
1
  package expo.modules.kotlin.callbacks
2
2
 
3
- import android.os.Bundle
4
3
  import android.view.View
5
4
  import com.facebook.react.bridge.ReactContext
5
+ import com.facebook.react.bridge.WritableMap
6
6
  import expo.modules.adapters.react.NativeModulesProxy
7
7
  import expo.modules.kotlin.modules.Module
8
+ import expo.modules.kotlin.types.JSTypeConverter
9
+ import expo.modules.kotlin.types.putGeneric
8
10
  import kotlin.reflect.KType
9
11
 
10
12
  class ViewCallback<T>(
@@ -22,7 +24,16 @@ class ViewCallback<T>(
22
24
  ?: return
23
25
  val appContext = nativeModulesProxy.kotlinInteropModuleRegistry.appContext
24
26
 
25
- // TODO(@lukmccall): handles other types
26
- appContext.callbackInvoker?.emit(view.id, name, arg as Bundle)
27
+ appContext.callbackInvoker?.emit(view.id, name, convertEventBody(arg))
28
+ }
29
+
30
+ private fun convertEventBody(arg: T): WritableMap? {
31
+ return when (val converted = JSTypeConverter.convertToJSValue(arg)) {
32
+ is Unit, null -> null
33
+ is WritableMap -> converted
34
+ else -> JSTypeConverter.DefaultContainerProvider.createMap().apply {
35
+ putGeneric("payload", converted)
36
+ }
37
+ }
27
38
  }
28
39
  }
@@ -0,0 +1,13 @@
1
+ package expo.modules.kotlin.events
2
+
3
+ import com.facebook.react.bridge.WritableMap
4
+ import expo.modules.kotlin.records.Record
5
+
6
+ // We want to decorate a legacy event emitter interface to support advanced conversion between types in events.
7
+ // For instance, users will be able to create `Callback<Record>` that will be converted to the `WritableMap`.
8
+ interface EventEmitter : expo.modules.core.interfaces.services.EventEmitter {
9
+ fun emit(eventName: String, eventBody: WritableMap?)
10
+ fun emit(eventName: String, eventBody: Record?)
11
+ fun emit(eventName: String, eventBody: Map<*, *>?)
12
+ fun emit(viewId: Int, eventName: String, eventBody: WritableMap?)
13
+ }