expo-modules-core 0.4.9 → 0.6.2

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 (145) hide show
  1. package/CHANGELOG.md +33 -2
  2. package/android/build.gradle +30 -2
  3. package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +42 -5
  4. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +49 -5
  5. package/android/src/main/java/expo/modules/core/BasePackage.java +6 -0
  6. package/android/src/main/java/expo/modules/core/ModulePriorities.kt +25 -0
  7. package/android/src/main/java/expo/modules/core/interfaces/ActivityEventListener.java +3 -1
  8. package/android/src/main/java/expo/modules/core/interfaces/Package.java +4 -0
  9. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityHandler.java +21 -0
  10. package/android/src/main/java/expo/modules/core/interfaces/ReactActivityLifecycleListener.java +23 -0
  11. package/android/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +14 -0
  12. package/android/src/main/java/expo/modules/core/utilities/KotlinUtilities.kt +23 -0
  13. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +166 -0
  14. package/android/src/main/java/expo/modules/kotlin/DynamicExtenstions.kt +9 -0
  15. package/android/src/main/java/expo/modules/kotlin/ExpoModulesHelper.kt +18 -0
  16. package/android/src/main/java/expo/modules/kotlin/KPromiseWrapper.kt +24 -0
  17. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +98 -0
  18. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +41 -0
  19. package/android/src/main/java/expo/modules/kotlin/ModuleRegistry.kt +56 -0
  20. package/android/src/main/java/expo/modules/kotlin/ModulesProvider.kt +7 -0
  21. package/android/src/main/java/expo/modules/kotlin/Promise.kt +13 -0
  22. package/android/src/main/java/expo/modules/kotlin/ReactLifecycleDelegate.kt +39 -0
  23. package/android/src/main/java/expo/modules/kotlin/ReadableArrayIterator.kt +14 -0
  24. package/android/src/main/java/expo/modules/kotlin/ReadableTypeExtensions.kt +18 -0
  25. package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructor.kt +5 -0
  26. package/android/src/main/java/expo/modules/kotlin/allocators/ObjectConstructorFactory.kt +31 -0
  27. package/android/src/main/java/expo/modules/kotlin/allocators/UnsafeAllocator.kt +49 -0
  28. package/android/src/main/java/expo/modules/kotlin/events/EventListener.kt +39 -0
  29. package/android/src/main/java/expo/modules/kotlin/events/EventName.kt +31 -0
  30. package/android/src/main/java/expo/modules/kotlin/events/EventsDefinition.kt +3 -0
  31. package/android/src/main/java/expo/modules/kotlin/events/KEventEmitterWrapper.kt +26 -0
  32. package/android/src/main/java/expo/modules/kotlin/events/OnActivityResultPayload.kt +8 -0
  33. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +70 -0
  34. package/android/src/main/java/expo/modules/kotlin/methods/AnyMethod.kt +50 -0
  35. package/android/src/main/java/expo/modules/kotlin/methods/Method.kt +14 -0
  36. package/android/src/main/java/expo/modules/kotlin/methods/PromiseMethod.kt +15 -0
  37. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +24 -0
  38. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +227 -0
  39. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +16 -0
  40. package/android/src/main/java/expo/modules/kotlin/records/Field.kt +5 -0
  41. package/android/src/main/java/expo/modules/kotlin/records/Record.kt +3 -0
  42. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +55 -0
  43. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +14 -0
  44. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +44 -0
  45. package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +60 -0
  46. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +84 -0
  47. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +25 -0
  48. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +39 -0
  49. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +28 -0
  50. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +19 -0
  51. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +107 -0
  52. package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +10 -0
  53. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +17 -0
  54. package/android/src/main/java/expo/modules/kotlin/views/GroupViewManagerWrapper.kt +22 -0
  55. package/android/src/main/java/expo/modules/kotlin/views/SimpleViewManagerWrapper.kt +21 -0
  56. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +41 -0
  57. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +40 -0
  58. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +21 -0
  59. package/android/src/main/java/expo/modules/kotlin/views/ViewWrapperDelegateHolder.kt +5 -0
  60. package/build/NativeModulesProxy.native.d.ts +4 -0
  61. package/build/NativeModulesProxy.native.js +14 -1
  62. package/build/NativeModulesProxy.native.js.map +1 -1
  63. package/build/NativeModulesProxy.types.d.ts +3 -0
  64. package/build/NativeModulesProxy.types.js.map +1 -1
  65. package/build/NativeViewManagerAdapter.native.js +1 -1
  66. package/build/NativeViewManagerAdapter.native.js.map +1 -1
  67. package/ios/AppDelegates/EXAppDelegateWrapper.h +19 -0
  68. package/ios/AppDelegates/EXAppDelegateWrapper.m +45 -0
  69. package/ios/AppDelegates/EXAppDelegatesLoader.h +15 -0
  70. package/ios/AppDelegates/EXAppDelegatesLoader.m +30 -0
  71. package/ios/AppDelegates/EXLegacyAppDelegateWrapper.h +16 -0
  72. package/ios/{EXAppDelegateWrapper.m → AppDelegates/EXLegacyAppDelegateWrapper.m} +2 -2
  73. package/ios/AppDelegates/ExpoAppDelegate.swift +282 -0
  74. package/ios/AppDelegates/ExpoAppDelegateSubscriber.swift +24 -0
  75. package/ios/EXAppDefines.h +26 -0
  76. package/ios/EXAppDefines.m +61 -0
  77. package/ios/ExpoModulesCore.podspec +8 -3
  78. package/ios/JSI/ExpoModulesProxySpec.h +24 -0
  79. package/ios/JSI/ExpoModulesProxySpec.mm +135 -0
  80. package/ios/JSI/JSIConversions.h +42 -0
  81. package/ios/JSI/JSIConversions.mm +164 -0
  82. package/ios/JSI/JSIInstaller.h +19 -0
  83. package/ios/JSI/JSIInstaller.mm +22 -0
  84. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +1 -6
  85. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +6 -0
  86. package/ios/NativeModulesProxy/{EXNativeModulesProxy.m → EXNativeModulesProxy.mm} +63 -17
  87. package/ios/ReactDelegates/EXRCTBridgeDelegateInterceptor.h +16 -0
  88. package/ios/ReactDelegates/EXRCTBridgeDelegateInterceptor.m +49 -0
  89. package/ios/ReactDelegates/EXReactDelegateWrapper+Private.h +18 -0
  90. package/ios/ReactDelegates/EXReactDelegateWrapper.h +25 -0
  91. package/ios/ReactDelegates/EXReactDelegateWrapper.m +40 -0
  92. package/ios/ReactDelegates/ExpoReactDelegate.swift +37 -0
  93. package/ios/ReactDelegates/ExpoReactDelegateHandler.swift +52 -0
  94. package/ios/ReactDelegates/ModulePriorities.swift +20 -0
  95. package/ios/Services/EXReactNativeEventEmitter.h +6 -0
  96. package/ios/Services/EXReactNativeEventEmitter.m +15 -0
  97. package/ios/Swift/AppContext.swift +14 -1
  98. package/ios/Swift/Arguments/AnyArgument.swift +14 -0
  99. package/ios/Swift/Arguments/AnyArgumentType.swift +13 -0
  100. package/ios/Swift/Arguments/ArgumentType.swift +24 -0
  101. package/ios/Swift/Arguments/ConvertibleArgument.swift +15 -0
  102. package/ios/Swift/Arguments/Convertibles.swift +107 -0
  103. package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +42 -0
  104. package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +16 -0
  105. package/ios/Swift/Arguments/Types/EnumArgumentType.swift +105 -0
  106. package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +49 -0
  107. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +15 -0
  108. package/ios/Swift/Arguments/Types/RawArgumentType.swift +25 -0
  109. package/ios/Swift/Conversions.swift +199 -7
  110. package/ios/Swift/EventListener.swift +37 -5
  111. package/ios/Swift/Functions/AnyFunction.swift +42 -0
  112. package/ios/Swift/{Methods/ConcreteMethod.swift → Functions/ConcreteFunction.swift} +32 -34
  113. package/ios/Swift/ModuleHolder.swift +86 -20
  114. package/ios/Swift/ModuleRegistry.swift +19 -8
  115. package/ios/Swift/Modules/AnyModule.swift +8 -8
  116. package/ios/Swift/Modules/Module.swift +11 -0
  117. package/ios/Swift/Modules/ModuleDefinition.swift +55 -15
  118. package/ios/Swift/Modules/ModuleDefinitionBuilder.swift +1 -1
  119. package/ios/Swift/Modules/ModuleDefinitionComponents.swift +149 -54
  120. package/ios/Swift/ModulesProvider.swift +19 -0
  121. package/ios/Swift/Promise.swift +1 -1
  122. package/ios/Swift/Records/Field.swift +1 -1
  123. package/ios/Swift/Records/Record.swift +8 -1
  124. package/ios/Swift/SwiftInteropBridge.swift +46 -17
  125. package/ios/Swift/Views/AnyViewProp.swift +2 -2
  126. package/ios/Swift/Views/ConcreteViewProp.swift +37 -10
  127. package/ios/Swift/Views/ViewModuleWrapper.swift +9 -4
  128. package/ios/Swift.h +9 -0
  129. package/ios/Tests/ArgumentTypeSpec.swift +145 -0
  130. package/ios/Tests/ConstantsSpec.swift +36 -0
  131. package/ios/Tests/ConvertiblesSpec.swift +265 -0
  132. package/ios/Tests/EXAppDefinesTest.m +99 -0
  133. package/ios/Tests/{MethodSpec.swift → FunctionSpec.swift} +69 -54
  134. package/ios/Tests/FunctionWithConvertiblesSpec.swift +66 -0
  135. package/ios/Tests/Mocks/ModuleMocks.swift +21 -7
  136. package/ios/Tests/ModuleEventListenersSpec.swift +17 -16
  137. package/ios/Tests/ModuleRegistrySpec.swift +4 -7
  138. package/package.json +3 -3
  139. package/src/NativeModulesProxy.native.ts +22 -2
  140. package/src/NativeModulesProxy.types.ts +8 -0
  141. package/src/NativeViewManagerAdapter.native.tsx +1 -1
  142. package/ios/EXAppDelegateWrapper.h +0 -13
  143. package/ios/Swift/Methods/AnyArgumentType.swift +0 -48
  144. package/ios/Swift/Methods/AnyMethod.swift +0 -31
  145. package/ios/Swift/Methods/AnyMethodArgument.swift +0 -13
@@ -0,0 +1,164 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <ReactCommon/TurboModuleUtils.h>
4
+ #import <ExpoModulesCore/JSIConversions.h>
5
+
6
+ namespace expo {
7
+
8
+ /**
9
+ * All static helper functions are ObjC++ specific.
10
+ */
11
+ jsi::Value convertNSNumberToJSIBoolean(jsi::Runtime &runtime, NSNumber *value)
12
+ {
13
+ return jsi::Value((bool)[value boolValue]);
14
+ }
15
+
16
+ jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *value)
17
+ {
18
+ return jsi::Value([value doubleValue]);
19
+ }
20
+
21
+ jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value)
22
+ {
23
+ return jsi::String::createFromUtf8(runtime, [value UTF8String] ?: "");
24
+ }
25
+
26
+ jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value)
27
+ {
28
+ jsi::Object result = jsi::Object(runtime);
29
+ for (NSString *k in value) {
30
+ result.setProperty(runtime, [k UTF8String], convertObjCObjectToJSIValue(runtime, value[k]));
31
+ }
32
+ return result;
33
+ }
34
+
35
+ jsi::Array convertNSArrayToJSIArray(jsi::Runtime &runtime, NSArray *value)
36
+ {
37
+ jsi::Array result = jsi::Array(runtime, value.count);
38
+ for (size_t i = 0; i < value.count; i++) {
39
+ result.setValueAtIndex(runtime, i, convertObjCObjectToJSIValue(runtime, value[i]));
40
+ }
41
+ return result;
42
+ }
43
+
44
+ std::vector<jsi::Value> convertNSArrayToStdVector(jsi::Runtime &runtime, NSArray *value)
45
+ {
46
+ std::vector<jsi::Value> result;
47
+ for (size_t i = 0; i < value.count; i++) {
48
+ result.emplace_back(convertObjCObjectToJSIValue(runtime, value[i]));
49
+ }
50
+ return result;
51
+ }
52
+
53
+ jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
54
+ {
55
+ if ([value isKindOfClass:[NSString class]]) {
56
+ return convertNSStringToJSIString(runtime, (NSString *)value);
57
+ } else if ([value isKindOfClass:[NSNumber class]]) {
58
+ if ([value isKindOfClass:[@YES class]]) {
59
+ return convertNSNumberToJSIBoolean(runtime, (NSNumber *)value);
60
+ }
61
+ return convertNSNumberToJSINumber(runtime, (NSNumber *)value);
62
+ } else if ([value isKindOfClass:[NSDictionary class]]) {
63
+ return convertNSDictionaryToJSIObject(runtime, (NSDictionary *)value);
64
+ } else if ([value isKindOfClass:[NSArray class]]) {
65
+ return convertNSArrayToJSIArray(runtime, (NSArray *)value);
66
+ } else if (value == (id)kCFNull) {
67
+ return jsi::Value::null();
68
+ }
69
+ return jsi::Value::undefined();
70
+ }
71
+
72
+ NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::String &value)
73
+ {
74
+ return [NSString stringWithUTF8String:value.utf8(runtime).c_str()];
75
+ }
76
+
77
+ NSArray *convertJSIArrayToNSArray(jsi::Runtime &runtime, const jsi::Array &value, std::shared_ptr<CallInvoker> jsInvoker)
78
+ {
79
+ size_t size = value.size(runtime);
80
+ NSMutableArray *result = [NSMutableArray new];
81
+ for (size_t i = 0; i < size; i++) {
82
+ // Insert kCFNull when it's `undefined` value to preserve the indices.
83
+ [result
84
+ addObject:convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker) ?: (id)kCFNull];
85
+ }
86
+ return [result copy];
87
+ }
88
+
89
+ NSDictionary *convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value, std::shared_ptr<CallInvoker> jsInvoker)
90
+ {
91
+ jsi::Array propertyNames = value.getPropertyNames(runtime);
92
+ size_t size = propertyNames.size(runtime);
93
+ NSMutableDictionary *result = [NSMutableDictionary new];
94
+ for (size_t i = 0; i < size; i++) {
95
+ jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
96
+ NSString *k = convertJSIStringToNSString(runtime, name);
97
+ id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker);
98
+ if (v) {
99
+ result[k] = v;
100
+ }
101
+ }
102
+ return [result copy];
103
+ }
104
+
105
+ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
106
+ {
107
+ if (value.isUndefined() || value.isNull()) {
108
+ return nil;
109
+ }
110
+ if (value.isBool()) {
111
+ return @(value.getBool());
112
+ }
113
+ if (value.isNumber()) {
114
+ return @(value.getNumber());
115
+ }
116
+ if (value.isString()) {
117
+ return convertJSIStringToNSString(runtime, value.getString(runtime));
118
+ }
119
+ if (value.isObject()) {
120
+ jsi::Object o = value.getObject(runtime);
121
+ if (o.isArray(runtime)) {
122
+ return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker);
123
+ }
124
+ if (o.isFunction(runtime)) {
125
+ return convertJSIFunctionToCallback(runtime, std::move(o.getFunction(runtime)), jsInvoker);
126
+ }
127
+ return convertJSIObjectToNSDictionary(runtime, o, jsInvoker);
128
+ }
129
+
130
+ throw std::runtime_error("Unsupported jsi::jsi::Value kind");
131
+ }
132
+
133
+ RCTResponseSenderBlock convertJSIFunctionToCallback(jsi::Runtime &runtime, const jsi::Function &value, std::shared_ptr<CallInvoker> jsInvoker)
134
+ {
135
+ auto weakWrapper = CallbackWrapper::createWeak(value.getFunction(runtime), runtime, jsInvoker);
136
+ BOOL __block wrapperWasCalled = NO;
137
+ RCTResponseSenderBlock callback = ^(NSArray *responses) {
138
+ if (wrapperWasCalled) {
139
+ throw std::runtime_error("callback arg cannot be called more than once");
140
+ }
141
+
142
+ auto strongWrapper = weakWrapper.lock();
143
+ if (!strongWrapper) {
144
+ return;
145
+ }
146
+
147
+ strongWrapper->jsInvoker().invokeAsync([weakWrapper, responses]() {
148
+ auto strongWrapper2 = weakWrapper.lock();
149
+ if (!strongWrapper2) {
150
+ return;
151
+ }
152
+
153
+ std::vector<jsi::Value> args = convertNSArrayToStdVector(strongWrapper2->runtime(), responses);
154
+ strongWrapper2->callback().call(strongWrapper2->runtime(), (const jsi::Value *)args.data(), args.size());
155
+ strongWrapper2->destroy();
156
+ });
157
+
158
+ wrapperWasCalled = YES;
159
+ };
160
+
161
+ return callback;
162
+ }
163
+
164
+ } // namespace expo
@@ -0,0 +1,19 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #ifdef __cplusplus
4
+
5
+ #import <jsi/jsi.h>
6
+ #import <ReactCommon/RCTTurboModule.h>
7
+
8
+ #import <ExpoModulesCore/EXNativeModulesProxy.h>
9
+
10
+ using namespace facebook;
11
+ using namespace react;
12
+
13
+ namespace expo {
14
+
15
+ void installRuntimeObjects(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> callInvoker, EXNativeModulesProxy *nativeModulesProxy);
16
+
17
+ } // namespace expo
18
+
19
+ #endif
@@ -0,0 +1,22 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <ExpoModulesCore/JSIInstaller.h>
4
+ #import <ExpoModulesCore/ExpoModulesProxySpec.h>
5
+
6
+ using namespace facebook;
7
+ using namespace react;
8
+
9
+ //using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper);
10
+
11
+ namespace expo {
12
+
13
+ void installRuntimeObjects(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> callInvoker, EXNativeModulesProxy *nativeModulesProxy)
14
+ {
15
+ auto expoModulesProxyModule = std::make_shared<ExpoModulesProxySpec>(callInvoker, nativeModulesProxy);
16
+
17
+ runtime
18
+ .global()
19
+ .setProperty(runtime, "ExpoModulesProxy", jsi::Object::createFromHostObject(runtime, expoModulesProxyModule));
20
+ }
21
+
22
+ } // namespace expo
@@ -7,12 +7,7 @@
7
7
  #import <ExpoModulesCore/EXViewManagerAdapterClassesRegistry.h>
8
8
  #import <ExpoModulesCore/EXModuleRegistryHolderReactModule.h>
9
9
  #import <ExpoModulesCore/EXReactNativeEventEmitter.h>
10
- #if __has_include(<ExpoModulesCore/ExpoModulesCore-Swift.h>)
11
- // For cocoapods framework, the generated swift header will be inside ExpoModulesCore module
12
- #import <ExpoModulesCore/ExpoModulesCore-Swift.h>
13
- #else
14
- #import "ExpoModulesCore-Swift.h"
15
- #endif
10
+ #import <ExpoModulesCore/Swift.h>
16
11
 
17
12
  @interface EXModuleRegistryAdapter ()
18
13
 
@@ -12,6 +12,7 @@
12
12
  // Swift compatibility headers (e.g. `ExpoModulesCore-Swift.h`) are not available in headers,
13
13
  // so we use class forward declaration here. Swift header must be imported in the `.m` file.
14
14
  @class SwiftInteropBridge;
15
+ @protocol ModulesProviderObjCProtocol;
15
16
 
16
17
  NS_SWIFT_NAME(NativeModulesProxy)
17
18
  @interface EXNativeModulesProxy : NSObject <RCTBridgeModule>
@@ -21,4 +22,9 @@ NS_SWIFT_NAME(NativeModulesProxy)
21
22
  - (nonnull instancetype)init;
22
23
  - (nonnull instancetype)initWithModuleRegistry:(nullable EXModuleRegistry *)moduleRegistry;
23
24
 
25
+ - (void)callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNameOrKey arguments:(NSArray *)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject;
26
+ - (id)callMethodSync:(NSString *)moduleName methodName:(NSString *)methodName arguments:(NSArray *)arguments;
27
+
28
+ + (id<ModulesProviderObjCProtocol>)getExpoModulesProvider;
29
+
24
30
  @end
@@ -8,6 +8,8 @@
8
8
  #import <React/RCTModuleData.h>
9
9
  #import <React/RCTEventDispatcherProtocol.h>
10
10
 
11
+ #import <jsi/jsi.h>
12
+
11
13
  #import <ExpoModulesCore/EXNativeModulesProxy.h>
12
14
  #import <ExpoModulesCore/EXEventEmitter.h>
13
15
  #import <ExpoModulesCore/EXViewManager.h>
@@ -15,12 +17,8 @@
15
17
  #import <ExpoModulesCore/EXViewManagerAdapterClassesRegistry.h>
16
18
  #import <ExpoModulesCore/EXModuleRegistryProvider.h>
17
19
  #import <ExpoModulesCore/EXReactNativeEventEmitter.h>
18
- #if __has_include(<ExpoModulesCore/ExpoModulesCore-Swift.h>)
19
- // For cocoapods framework, the generated swift header will be inside ExpoModulesCore module
20
- #import <ExpoModulesCore/ExpoModulesCore-Swift.h>
21
- #else
22
- #import "ExpoModulesCore-Swift.h"
23
- #endif
20
+ #import <ExpoModulesCore/JSIInstaller.h>
21
+ #import <ExpoModulesCore/Swift.h>
24
22
 
25
23
  static const NSString *exportedMethodsNamesKeyPath = @"exportedMethods";
26
24
  static const NSString *viewManagersNamesKeyPath = @"viewManagersNames";
@@ -37,6 +35,12 @@ static const NSString *methodInfoArgumentsCountKey = @"argumentsCount";
37
35
 
38
36
  @end
39
37
 
38
+ @interface RCTBridge (JSIRuntime)
39
+
40
+ - (void *)runtime;
41
+
42
+ @end
43
+
40
44
  @interface RCTComponentData (EXNativeModulesProxy)
41
45
 
42
46
  - (instancetype)initWithManagerClass:(Class)managerClass bridge:(RCTBridge *)bridge eventDispatcher:(id<RCTEventDispatcherProtocol>) eventDispatcher; // available in RN 0.65+
@@ -68,7 +72,7 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
68
72
  {
69
73
  if (self = [super init]) {
70
74
  _exModuleRegistry = moduleRegistry != nil ? moduleRegistry : [[EXModuleRegistryProvider new] moduleRegistry];
71
- _swiftInteropBridge = [[SwiftInteropBridge alloc] initWithModulesProvider:[self getExpoModulesProvider] legacyModuleRegistry:_exModuleRegistry];
75
+ _swiftInteropBridge = [[SwiftInteropBridge alloc] initWithModulesProvider:[EXNativeModulesProxy getExpoModulesProvider] legacyModuleRegistry:_exModuleRegistry];
72
76
  _exportedMethodsKeys = [NSMutableDictionary dictionary];
73
77
  _exportedMethodsReverseKeys = [NSMutableDictionary dictionary];
74
78
  _ownsModuleRegistry = moduleRegistry == nil;
@@ -93,6 +97,9 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
93
97
 
94
98
  - (NSDictionary *)constantsToExport
95
99
  {
100
+ // Install the TurboModule implementation of the proxy.
101
+ [self installExpoTurboModules];
102
+
96
103
  NSMutableDictionary <NSString *, id> *exportedModulesConstants = [NSMutableDictionary dictionary];
97
104
  // Grab all the constants exported by modules
98
105
  for (EXExportedModule *exportedModule in [_exModuleRegistry getAllExportedModules]) {
@@ -121,7 +128,7 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
121
128
  }
122
129
 
123
130
  // Add entries from Swift modules
124
- [exportedMethodsNamesAccumulator addEntriesFromDictionary:[_swiftInteropBridge exportedMethodNames]];
131
+ [exportedMethodsNamesAccumulator addEntriesFromDictionary:[_swiftInteropBridge exportedFunctionNames]];
125
132
 
126
133
  // Also, add `viewManagersNames` for sanity check and testing purposes -- with names we know what managers to mock on UIManager
127
134
  NSArray<EXViewManager *> *viewManagers = [_exModuleRegistry getAllViewManagers];
@@ -151,7 +158,7 @@ RCT_EXPORT_MODULE(NativeUnimoduleProxy)
151
158
  RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNameOrKey arguments:(NSArray *)arguments resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
152
159
  {
153
160
  if ([_swiftInteropBridge hasModule:moduleName]) {
154
- [_swiftInteropBridge callMethod:methodNameOrKey onModule:moduleName withArgs:arguments resolve:resolve reject:reject];
161
+ [_swiftInteropBridge callFunction:methodNameOrKey onModule:moduleName withArgs:arguments resolve:resolve reject:reject];
155
162
  return;
156
163
  }
157
164
  EXExportedModule *module = [_exModuleRegistry getExportedModuleForName:moduleName];
@@ -186,19 +193,44 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
186
193
  });
187
194
  }
188
195
 
189
- #pragma mark - Privates
196
+ - (id)callMethodSync:(NSString *)moduleName methodName:(NSString *)methodName arguments:(NSArray *)arguments
197
+ {
198
+ if ([_swiftInteropBridge hasModule:moduleName]) {
199
+ return [_swiftInteropBridge callFunctionSync:methodName onModule:moduleName withArgs:arguments];
200
+ }
201
+ return (id)kCFNull;
202
+ }
203
+
204
+ #pragma mark - Statics
190
205
 
191
- - (id<ModulesProviderObjCProtocol>)getExpoModulesProvider
206
+ + (id<ModulesProviderObjCProtocol>)getExpoModulesProvider
192
207
  {
193
- Class generatedExpoModulesProvider = NSClassFromString(@"ExpoModulesProvider");
194
- // Checks if `ExpoModulesProvider` was generated
195
- if (generatedExpoModulesProvider) {
208
+ // Dynamically gets the modules provider class.
209
+ // NOTE: This needs to be versioned in Expo Go.
210
+ Class generatedExpoModulesProvider;
211
+
212
+ // [0] When ExpoModulesCore is built as separated framework/module,
213
+ // we should explicitly load main bundle's `ExpoModulesProvider` class.
214
+ NSString *bundleName = NSBundle.mainBundle.infoDictionary[@"CFBundleName"];
215
+ if (bundleName != nil) {
216
+ generatedExpoModulesProvider = NSClassFromString([NSString stringWithFormat:@"%@.ExpoModulesProvider", bundleName]);
217
+ if (generatedExpoModulesProvider != nil) {
218
+ return [generatedExpoModulesProvider new];
219
+ }
220
+ }
221
+
222
+ // [1] Fallback to load `ExpoModulesProvider` class from the current module.
223
+ generatedExpoModulesProvider = NSClassFromString(@"ExpoModulesProvider");
224
+ if (generatedExpoModulesProvider != nil) {
196
225
  return [generatedExpoModulesProvider new];
197
- } else {
198
- return [ModulesProvider new];
199
226
  }
227
+
228
+ // [2] Fallback to load `ModulesProvider` if `ExpoModulesProvider` was not generated
229
+ return [ModulesProvider new];
200
230
  }
201
231
 
232
+ #pragma mark - Privates
233
+
202
234
  - (void)registerExpoModulesInBridge:(RCTBridge *)bridge
203
235
  {
204
236
  // Registering expo modules in bridge is needed only when the proxy module owns the registry
@@ -255,8 +287,10 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
255
287
  // components in UIManager — we need to register them on our own.
256
288
  [self registerComponentDataForModuleClasses:additionalModuleClasses inBridge:bridge];
257
289
 
258
- // Get the newly created instance of `EXReactEventEmitter` bridge module and register it in expo modules registry.
290
+ // Get the newly created instance of `EXReactEventEmitter` bridge module,
291
+ // pass event names supported by Swift modules and register it in legacy modules registry.
259
292
  EXReactNativeEventEmitter *eventEmitter = [bridge moduleForClass:[EXReactNativeEventEmitter class]];
293
+ [eventEmitter setSwiftInteropBridge:_swiftInteropBridge];
260
294
  [_exModuleRegistry registerInternalModule:eventEmitter];
261
295
 
262
296
  // Let the modules consume the registry :)
@@ -345,4 +379,16 @@ RCT_EXPORT_METHOD(callMethod:(NSString *)moduleName methodNameOrKey:(id)methodNa
345
379
  }
346
380
  }
347
381
 
382
+ /**
383
+ Installs expo modules in JSI runtime.
384
+ */
385
+ - (void)installExpoTurboModules
386
+ {
387
+ facebook::jsi::Runtime *runtime = [_bridge respondsToSelector:@selector(runtime)] ? reinterpret_cast<facebook::jsi::Runtime *>(_bridge.runtime) : NULL;
388
+
389
+ if (runtime) {
390
+ expo::installRuntimeObjects(*runtime, _bridge.jsCallInvoker, self);
391
+ }
392
+ }
393
+
348
394
  @end
@@ -0,0 +1,16 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <React/RCTBridgeDelegate.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ @interface EXRCTBridgeDelegateInterceptor : NSObject<RCTBridgeDelegate>
8
+
9
+ @property (nonatomic, weak) id<RCTBridgeDelegate> bridgeDelegate;
10
+ @property (nonatomic, weak) id<RCTBridgeDelegate> interceptor;
11
+
12
+ - (instancetype)initWithBridgeDelegate:(id<RCTBridgeDelegate>)bridgeDelegate interceptor:(id<RCTBridgeDelegate>)interceptor;
13
+
14
+ @end
15
+
16
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,49 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <ExpoModulesCore/EXRCTBridgeDelegateInterceptor.h>
4
+
5
+ @implementation EXRCTBridgeDelegateInterceptor
6
+
7
+ - (instancetype)initWithBridgeDelegate:(id<RCTBridgeDelegate>)bridgeDelegate interceptor:(id<RCTBridgeDelegate>)interceptor
8
+ {
9
+ if (self = [super init]) {
10
+ self.bridgeDelegate = bridgeDelegate;
11
+ self.interceptor = interceptor;
12
+ }
13
+ return self;
14
+ }
15
+
16
+ - (BOOL)conformsToProtocol:(Protocol *)protocol
17
+ {
18
+ return [self.bridgeDelegate conformsToProtocol:protocol];
19
+ }
20
+
21
+ - (id)forwardingTargetForSelector:(SEL)selector
22
+ {
23
+ if ([self isInterceptedSelector:selector]) {
24
+ return self;
25
+ }
26
+ return self.bridgeDelegate;
27
+ }
28
+
29
+ - (BOOL)respondsToSelector:(SEL)selector
30
+ {
31
+ if ([self isInterceptedSelector:selector]) {
32
+ return YES;
33
+ }
34
+ return [self.bridgeDelegate respondsToSelector:selector];
35
+ }
36
+
37
+ - (BOOL)isInterceptedSelector:(SEL)selector
38
+ {
39
+ if ([self.interceptor respondsToSelector:selector]) {
40
+ return YES;
41
+ }
42
+ return NO;
43
+ }
44
+
45
+ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
46
+ return [self.interceptor sourceURLForBridge:bridge];
47
+ }
48
+
49
+ @end
@@ -0,0 +1,18 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <ExpoModulesCore/Swift.h>
4
+
5
+ NS_ASSUME_NONNULL_BEGIN
6
+
7
+ /**
8
+ Internal `EXReactDelegateWrapper` interface for the designated initializer with `ExpoReactDelegate`.
9
+ Since `ExpoReactDelegate` implements in swift and requires the generated `ExpoModulesCore-Swift.h` header,
10
+ this header file should ONLY be imported from *.m or *.mm files.
11
+ */
12
+ @interface EXReactDelegateWrapper(Private)
13
+
14
+ - (instancetype)initWithExpoReactDelegate:(ExpoReactDelegate *)expoReactDelegate;
15
+
16
+ @end
17
+
18
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,25 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <UIKit/UIKit.h>
4
+ #import <React/RCTBridge.h>
5
+ #import <React/RCTRootView.h>
6
+
7
+ NS_ASSUME_NONNULL_BEGIN
8
+
9
+ /**
10
+ A wrapper of `ExpoReactDelegate` for Objective-C bindings.
11
+ */
12
+ @interface EXReactDelegateWrapper : NSObject
13
+
14
+ - (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate
15
+ launchOptions:(nullable NSDictionary *)launchOptions;
16
+
17
+ - (RCTRootView *)createRootViewWithBridge:(RCTBridge *)bridge
18
+ moduleName:(NSString *)moduleName
19
+ initialProperties:(nullable NSDictionary *)initialProperties;
20
+
21
+ - (UIViewController *)createRootViewController;
22
+
23
+ @end
24
+
25
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,40 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ #import <ExpoModulesCore/EXReactDelegateWrapper.h>
4
+ #import <ExpoModulesCore/EXReactDelegateWrapper+Private.h>
5
+
6
+ @interface EXReactDelegateWrapper()
7
+
8
+ @property (nonatomic, weak) ExpoReactDelegate *expoReactDelegate;
9
+
10
+ @end
11
+
12
+ @implementation EXReactDelegateWrapper
13
+
14
+ - (instancetype)initWithExpoReactDelegate:(ExpoReactDelegate *)expoReactDelegate
15
+ {
16
+ if (self = [super init]) {
17
+ _expoReactDelegate = expoReactDelegate;
18
+ }
19
+ return self;
20
+ }
21
+
22
+ - (RCTBridge *)createBridgeWithDelegate:(id<RCTBridgeDelegate>)delegate
23
+ launchOptions:(nullable NSDictionary *)launchOptions
24
+ {
25
+ return [_expoReactDelegate createBridgeWithDelegate:delegate launchOptions:launchOptions];
26
+ }
27
+
28
+ - (RCTRootView *)createRootViewWithBridge:(RCTBridge *)bridge
29
+ moduleName:(NSString *)moduleName
30
+ initialProperties:(nullable NSDictionary *)initialProperties
31
+ {
32
+ return [_expoReactDelegate createRootViewWithBridge:bridge moduleName:moduleName initialProperties:initialProperties];
33
+ }
34
+
35
+ - (UIViewController *)createRootViewController
36
+ {
37
+ return [_expoReactDelegate createRootViewController];
38
+ }
39
+
40
+ @end
@@ -0,0 +1,37 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ An extensible react instance creation delegate. This class will loop through each `ExpoReactDelegateHandler` to determine the winner to create the instance.
5
+ */
6
+ @objc
7
+ public class ExpoReactDelegate: NSObject {
8
+ private let handlers: [ExpoReactDelegateHandler]
9
+
10
+ public init(handlers: [ExpoReactDelegateHandler]) {
11
+ self.handlers = handlers
12
+ }
13
+
14
+ @objc
15
+ public func createBridge(delegate: RCTBridgeDelegate, launchOptions: [AnyHashable : Any]?) -> RCTBridge {
16
+ self.handlers.forEach { $0.bridgeWillCreate() }
17
+ let result = self.handlers.lazy
18
+ .compactMap { $0.createBridge(reactDelegate: self, bridgeDelegate: delegate, launchOptions: launchOptions) }
19
+ .first(where: { _ in true }) ?? RCTBridge(delegate: delegate, launchOptions: launchOptions)!
20
+ self.handlers.forEach { $0.bridgeDidCreate(bridge: result) }
21
+ return result
22
+ }
23
+
24
+ @objc
25
+ public func createRootView(bridge: RCTBridge, moduleName: String, initialProperties: [AnyHashable : Any]?) -> RCTRootView {
26
+ return self.handlers.lazy
27
+ .compactMap { $0.createRootView(reactDelegate: self, bridge: bridge, moduleName: moduleName, initialProperties: initialProperties) }
28
+ .first(where: { _ in true }) ?? RCTRootView(bridge: bridge, moduleName: moduleName, initialProperties: initialProperties)
29
+ }
30
+
31
+ @objc
32
+ public func createRootViewController() -> UIViewController {
33
+ return self.handlers.lazy
34
+ .compactMap { $0.createRootViewController(reactDelegate: self) }
35
+ .first(where: { _ in true }) ?? UIViewController()
36
+ }
37
+ }
@@ -0,0 +1,52 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ import Foundation
4
+
5
+ /**
6
+ The handler for `ExpoReactDelegate`. A module can implement a handler to process react instance creation.
7
+ */
8
+ @objc
9
+ open class ExpoReactDelegateHandler: NSObject {
10
+ public override required init() {}
11
+
12
+ /**
13
+ If this module wants to handle `RCTBridge` creation, it can return the instance.
14
+ Otherwise return nil.
15
+ */
16
+ @objc
17
+ open func createBridge(reactDelegate: ExpoReactDelegate, bridgeDelegate: RCTBridgeDelegate, launchOptions: [AnyHashable : Any]?) -> RCTBridge? {
18
+ return nil
19
+ }
20
+
21
+ /**
22
+ If this module wants to handle `RCTRootView` creation, it can return the instance.
23
+ Otherwise return nil.
24
+ */
25
+ @objc
26
+ open func createRootView(reactDelegate: ExpoReactDelegate, bridge: RCTBridge, moduleName: String, initialProperties: [AnyHashable : Any]?) -> RCTRootView? {
27
+ return nil
28
+ }
29
+
30
+ /**
31
+ If this module wants to handle `UIViewController` creation for `RCTRootView`, it can return the instance.
32
+ Otherwise return nil.
33
+ */
34
+ @objc
35
+ open func createRootViewController(reactDelegate: ExpoReactDelegate) -> UIViewController? {
36
+ return nil
37
+ }
38
+
39
+ // MARK - event callbacks
40
+
41
+ /**
42
+ Callback before bridge creation
43
+ */
44
+ @objc
45
+ open func bridgeWillCreate() {}
46
+
47
+ /**
48
+ Callback after bridge creation
49
+ */
50
+ @objc
51
+ open func bridgeDidCreate(bridge: RCTBridge) {}
52
+ }
@@ -0,0 +1,20 @@
1
+ // Copyright 2018-present 650 Industries. All rights reserved.
2
+
3
+ /**
4
+ This class determines the order of `ExpoReactDelegateHandler`.
5
+
6
+ The priority is only for internal use and we maintain a pre-defined `SUPPORTED_MODULE` map.
7
+ */
8
+ internal struct ModulePriorities {
9
+ static let SUPPORTED_MODULE = [
10
+ // {key}: {value}
11
+ // key: node package name
12
+ // value: priority value, the higher value takes precedence
13
+ "expo-screen-orientation": 10,
14
+ "expo-updates": 5,
15
+ ]
16
+
17
+ static func get(_ packageName: String) -> Int {
18
+ return SUPPORTED_MODULE[packageName] ?? 0
19
+ }
20
+ }
@@ -7,6 +7,12 @@
7
7
  #import <ExpoModulesCore/EXModuleRegistryConsumer.h>
8
8
  #import <ExpoModulesCore/EXBridgeModule.h>
9
9
 
10
+ // Swift compatibility headers (e.g. `ExpoModulesCore-Swift.h`) are not available in headers,
11
+ // so we use class forward declaration here. Swift header must be imported in the `.m` file.
12
+ @class SwiftInteropBridge;
13
+
10
14
  @interface EXReactNativeEventEmitter : RCTEventEmitter <EXInternalModule, EXBridgeModule, EXModuleRegistryConsumer, EXEventEmitterService>
11
15
 
16
+ @property (nonatomic, strong) SwiftInteropBridge *swiftInteropBridge;
17
+
12
18
  @end