expo-modules-core 0.9.2 → 0.11.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 (193) hide show
  1. package/CHANGELOG.md +33 -3
  2. package/README.md +3 -3
  3. package/android/CMakeLists.txt +163 -0
  4. package/android/build.gradle +343 -5
  5. package/android/src/main/cpp/CachedReferencesRegistry.cpp +65 -0
  6. package/android/src/main/cpp/CachedReferencesRegistry.h +80 -0
  7. package/android/src/main/cpp/Exceptions.cpp +22 -0
  8. package/android/src/main/cpp/Exceptions.h +38 -0
  9. package/android/src/main/cpp/ExpoModulesHostObject.cpp +47 -0
  10. package/android/src/main/cpp/ExpoModulesHostObject.h +32 -0
  11. package/android/src/main/cpp/JNIFunctionBody.cpp +44 -0
  12. package/android/src/main/cpp/JNIFunctionBody.h +50 -0
  13. package/android/src/main/cpp/JNIInjector.cpp +23 -0
  14. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +122 -0
  15. package/android/src/main/cpp/JSIInteropModuleRegistry.h +96 -0
  16. package/android/src/main/cpp/JSIObjectWrapper.h +33 -0
  17. package/android/src/main/cpp/JSITypeConverter.h +84 -0
  18. package/android/src/main/cpp/JavaScriptModuleObject.cpp +219 -0
  19. package/android/src/main/cpp/JavaScriptModuleObject.h +144 -0
  20. package/android/src/main/cpp/JavaScriptObject.cpp +125 -0
  21. package/android/src/main/cpp/JavaScriptObject.h +131 -0
  22. package/android/src/main/cpp/JavaScriptRuntime.cpp +127 -0
  23. package/android/src/main/cpp/JavaScriptRuntime.h +87 -0
  24. package/android/src/main/cpp/JavaScriptValue.cpp +172 -0
  25. package/android/src/main/cpp/JavaScriptValue.h +78 -0
  26. package/android/src/main/cpp/MethodMetadata.cpp +340 -0
  27. package/android/src/main/cpp/MethodMetadata.h +131 -0
  28. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +2 -0
  29. package/android/src/main/java/expo/modules/core/errors/ContextDestroyedException.kt +7 -0
  30. package/android/src/main/java/expo/modules/interfaces/permissions/Permissions.java +30 -0
  31. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +98 -3
  32. package/android/src/main/java/expo/modules/kotlin/ConcatIterator.kt +18 -0
  33. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +15 -12
  34. package/android/src/main/java/expo/modules/kotlin/ModuleHolder.kt +45 -3
  35. package/android/src/main/java/expo/modules/kotlin/activityaware/AppCompatActivityAware.kt +49 -0
  36. package/android/src/main/java/expo/modules/kotlin/activityaware/AppCompatActivityAwareHelper.kt +43 -0
  37. package/android/src/main/java/expo/modules/kotlin/activityaware/OnActivityAvailableListener.kt +18 -0
  38. package/android/src/main/java/expo/modules/kotlin/activityresult/ActivityResultsManager.kt +99 -0
  39. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultCaller.kt +25 -0
  40. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultContract.kt +27 -0
  41. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultFallbackCallback.kt +17 -0
  42. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultLauncher.kt +30 -0
  43. package/android/src/main/java/expo/modules/kotlin/activityresult/AppContextActivityResultRegistry.kt +358 -0
  44. package/android/src/main/java/expo/modules/kotlin/activityresult/DataPersistor.kt +135 -0
  45. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +2 -2
  46. package/android/src/main/java/expo/modules/kotlin/exception/CodedException.kt +13 -0
  47. package/android/src/main/java/expo/modules/kotlin/exception/ExceptionDecorator.kt +2 -0
  48. package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +53 -15
  49. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +35 -7
  50. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +13 -121
  51. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionComponent.kt +21 -0
  52. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromiseComponent.kt +21 -0
  53. package/android/src/main/java/expo/modules/kotlin/functions/SuspendFunctionComponent.kt +63 -0
  54. package/android/src/main/java/expo/modules/kotlin/functions/SyncFunctionComponent.kt +36 -0
  55. package/android/src/main/java/expo/modules/kotlin/jni/CppType.kt +19 -0
  56. package/android/src/main/java/expo/modules/kotlin/jni/JNIFunctionBody.kt +39 -0
  57. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +89 -0
  58. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +46 -0
  59. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptObject.kt +113 -0
  60. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptValue.kt +35 -0
  61. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +16 -6
  62. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionBuilder.kt +5 -500
  63. package/android/src/main/java/expo/modules/kotlin/modules/ModuleDefinitionData.kt +30 -5
  64. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +271 -0
  65. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionData.kt +21 -0
  66. package/android/src/main/java/expo/modules/kotlin/objects/PropertyComponent.kt +54 -0
  67. package/android/src/main/java/expo/modules/kotlin/objects/PropertyComponentBuilder.kt +32 -0
  68. package/android/src/main/java/expo/modules/kotlin/providers/AppContextProvider.kt +14 -0
  69. package/android/src/main/java/expo/modules/kotlin/providers/CurrentActivityProvider.kt +22 -0
  70. package/android/src/main/java/expo/modules/kotlin/records/RecordTypeConverter.kt +19 -2
  71. package/android/src/main/java/expo/modules/kotlin/types/AnyType.kt +3 -2
  72. package/android/src/main/java/expo/modules/kotlin/types/AnyTypeConverter.kt +36 -0
  73. package/android/src/main/java/expo/modules/kotlin/types/ArrayTypeConverter.kt +7 -2
  74. package/android/src/main/java/expo/modules/kotlin/types/BasicTypeConverters.kt +68 -20
  75. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +50 -22
  76. package/android/src/main/java/expo/modules/kotlin/types/ListTypeConverter.kt +18 -2
  77. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +18 -2
  78. package/android/src/main/java/expo/modules/kotlin/types/PairTypeConverter.kt +17 -2
  79. package/android/src/main/java/expo/modules/kotlin/types/TypeConverter.kt +43 -3
  80. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +12 -0
  81. package/android/src/main/java/expo/modules/kotlin/views/ViewGroupDefinitionBuilder.kt +0 -41
  82. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinitionBuilder.kt +0 -33
  83. package/build/NativeModulesProxy.native.d.ts.map +1 -1
  84. package/build/NativeModulesProxy.native.js +9 -3
  85. package/build/NativeModulesProxy.native.js.map +1 -1
  86. package/build/PermissionsInterface.d.ts +29 -0
  87. package/build/PermissionsInterface.d.ts.map +1 -1
  88. package/build/PermissionsInterface.js +9 -0
  89. package/build/PermissionsInterface.js.map +1 -1
  90. package/ios/AppDelegates/EXAppDelegatesLoader.m +1 -2
  91. package/ios/ExpoModulesCore.podspec +3 -2
  92. package/ios/JSI/EXJSIConversions.mm +6 -0
  93. package/ios/JSI/EXJSIInstaller.h +15 -21
  94. package/ios/JSI/EXJSIInstaller.mm +39 -3
  95. package/ios/JSI/EXJSIUtils.h +48 -3
  96. package/ios/JSI/EXJSIUtils.mm +88 -4
  97. package/ios/JSI/EXJavaScriptObject.h +11 -18
  98. package/ios/JSI/EXJavaScriptObject.mm +37 -18
  99. package/ios/JSI/EXJavaScriptRuntime.h +43 -9
  100. package/ios/JSI/EXJavaScriptRuntime.mm +70 -27
  101. package/ios/JSI/EXJavaScriptTypedArray.h +30 -0
  102. package/ios/JSI/EXJavaScriptTypedArray.mm +29 -0
  103. package/ios/JSI/EXJavaScriptValue.h +3 -2
  104. package/ios/JSI/EXJavaScriptValue.mm +17 -20
  105. package/ios/JSI/EXJavaScriptWeakObject.h +23 -0
  106. package/ios/JSI/EXJavaScriptWeakObject.mm +53 -0
  107. package/ios/JSI/EXObjectDeallocator.h +27 -0
  108. package/ios/JSI/ExpoModulesHostObject.h +3 -3
  109. package/ios/JSI/ExpoModulesHostObject.mm +4 -4
  110. package/ios/JSI/JavaScriptRuntime.swift +38 -1
  111. package/ios/JSI/JavaScriptValue.swift +7 -0
  112. package/ios/JSI/TypedArray.cpp +67 -0
  113. package/ios/JSI/TypedArray.h +46 -0
  114. package/ios/ModuleRegistryAdapter/EXModuleRegistryAdapter.m +0 -11
  115. package/ios/NativeModulesProxy/EXNativeModulesProxy.h +17 -10
  116. package/ios/NativeModulesProxy/EXNativeModulesProxy.mm +86 -77
  117. package/ios/NativeModulesProxy/NativeModulesProxyModule.swift +17 -0
  118. package/ios/Services/EXReactNativeEventEmitter.h +2 -2
  119. package/ios/Services/EXReactNativeEventEmitter.m +11 -6
  120. package/ios/Swift/AppContext.swift +206 -28
  121. package/ios/Swift/Arguments/AnyArgument.swift +18 -0
  122. package/ios/Swift/Arguments/{Types/EnumArgumentType.swift → EnumArgument.swift} +2 -17
  123. package/ios/Swift/Classes/ClassComponent.swift +95 -0
  124. package/ios/Swift/Classes/ClassComponentElement.swift +33 -0
  125. package/ios/Swift/Classes/ClassComponentElementsBuilder.swift +34 -0
  126. package/ios/Swift/Classes/ClassComponentFactories.swift +96 -0
  127. package/ios/Swift/DynamicTypes/AnyDynamicType.swift +44 -0
  128. package/ios/Swift/DynamicTypes/DynamicArrayType.swift +56 -0
  129. package/ios/Swift/DynamicTypes/DynamicConvertibleType.swift +27 -0
  130. package/ios/Swift/DynamicTypes/DynamicEnumType.swift +27 -0
  131. package/ios/Swift/DynamicTypes/DynamicOptionalType.swift +63 -0
  132. package/ios/Swift/DynamicTypes/DynamicRawType.swift +33 -0
  133. package/ios/Swift/DynamicTypes/DynamicSharedObjectType.swift +37 -0
  134. package/ios/Swift/DynamicTypes/DynamicType.swift +39 -0
  135. package/ios/Swift/DynamicTypes/DynamicTypedArrayType.swift +46 -0
  136. package/ios/Swift/Exceptions/ChainableException.swift +3 -3
  137. package/ios/Swift/Exceptions/CodedError.swift +1 -1
  138. package/ios/Swift/Exceptions/Exception.swift +8 -6
  139. package/ios/Swift/Exceptions/UnexpectedException.swift +2 -1
  140. package/ios/Swift/ExpoBridgeModule.m +5 -0
  141. package/ios/Swift/ExpoBridgeModule.swift +79 -0
  142. package/ios/Swift/Functions/AnyFunction.swift +33 -31
  143. package/ios/Swift/Functions/AsyncFunctionComponent.swift +196 -59
  144. package/ios/Swift/Functions/SyncFunctionComponent.swift +142 -58
  145. package/ios/Swift/JavaScriptUtils.swift +32 -57
  146. package/ios/Swift/Logging/LogHandlers.swift +39 -0
  147. package/ios/Swift/Logging/LogType.swift +62 -0
  148. package/ios/Swift/Logging/Logger.swift +201 -0
  149. package/ios/Swift/ModuleHolder.swift +19 -54
  150. package/ios/Swift/ModuleRegistry.swift +7 -1
  151. package/ios/Swift/Modules/AnyModule.swift +3 -3
  152. package/ios/Swift/ModulesProvider.swift +2 -0
  153. package/ios/Swift/Objects/JavaScriptObjectBuilder.swift +37 -0
  154. package/ios/Swift/Objects/ObjectDefinition.swift +74 -1
  155. package/ios/Swift/Objects/ObjectDefinitionComponents.swift +77 -68
  156. package/ios/Swift/Objects/PropertyComponent.swift +147 -0
  157. package/ios/Swift/Promise.swift +17 -4
  158. package/ios/Swift/Records/Field.swift +2 -2
  159. package/ios/Swift/SharedObjects/SharedObject.swift +20 -0
  160. package/ios/Swift/SharedObjects/SharedObjectRegistry.swift +129 -0
  161. package/ios/Swift/TypedArrays/AnyTypedArray.swift +11 -0
  162. package/ios/Swift/TypedArrays/ConcreteTypedArrays.swift +56 -0
  163. package/ios/Swift/TypedArrays/GenericTypedArray.swift +49 -0
  164. package/ios/Swift/TypedArrays/TypedArray.swift +80 -0
  165. package/ios/Swift/Utilities.swift +28 -0
  166. package/ios/Swift/Views/ConcreteViewProp.swift +3 -3
  167. package/ios/Swift/Views/ViewManagerDefinitionComponents.swift +2 -2
  168. package/ios/Tests/ClassComponentSpec.swift +210 -0
  169. package/ios/Tests/DynamicTypeSpec.swift +336 -0
  170. package/ios/Tests/EnumArgumentSpec.swift +48 -0
  171. package/ios/Tests/ExpoModulesSpec.swift +17 -3
  172. package/ios/Tests/FunctionSpec.swift +167 -118
  173. package/ios/Tests/Mocks/ModuleMocks.swift +1 -1
  174. package/ios/Tests/PropertyComponentSpec.swift +95 -0
  175. package/ios/Tests/SharedObjectRegistrySpec.swift +109 -0
  176. package/ios/Tests/TypedArraysSpec.swift +136 -0
  177. package/package.json +2 -2
  178. package/src/NativeModulesProxy.native.ts +13 -3
  179. package/src/PermissionsInterface.ts +29 -0
  180. package/src/ts-declarations/ExpoModules.d.ts +7 -0
  181. package/tsconfig.json +1 -1
  182. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionWithPromise.kt +0 -15
  183. package/android/src/main/java/expo/modules/kotlin/functions/AsyncSuspendFunction.kt +0 -36
  184. package/ios/Swift/Arguments/AnyArgumentType.swift +0 -13
  185. package/ios/Swift/Arguments/ArgumentType.swift +0 -28
  186. package/ios/Swift/Arguments/Types/ArrayArgumentType.swift +0 -42
  187. package/ios/Swift/Arguments/Types/ConvertibleArgumentType.swift +0 -16
  188. package/ios/Swift/Arguments/Types/OptionalArgumentType.swift +0 -49
  189. package/ios/Swift/Arguments/Types/PromiseArgumentType.swift +0 -15
  190. package/ios/Swift/Arguments/Types/RawArgumentType.swift +0 -25
  191. package/ios/Swift/Functions/ConcreteFunction.swift +0 -103
  192. package/ios/Swift/SwiftInteropBridge.swift +0 -155
  193. package/ios/Tests/ArgumentTypeSpec.swift +0 -143
@@ -1 +1 @@
1
- {"version":3,"file":"NativeModulesProxy.native.js","sourceRoot":"","sources":["../src/NativeModulesProxy.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,MAAM,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC;AACvD,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C,MAAM,kBAAkB,GAAgD,EAAE,CAAC;AAE3E,IAAI,WAAW,EAAE;IACf,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QAClE,kBAAkB,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACpF,WAAW,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAe,EAAgB,EAAE;gBACrF,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;gBAC3C,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE;oBAClC,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,iBAAiB,UAAU,IAAI,UAAU,CAAC,IAAI,YAAY,cAAc,IACtE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WACtC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAC/B,CACF,CAAC;iBACH;gBACD,OAAO,WAAW,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YACvD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,kFAAkF;QAClF,EAAE;QACF,wEAAwE;QACxE,gDAAgD;QAChD,EAAE;QACF,6GAA6G;QAC7G,gGAAgG;QAChG,4HAA4H;QAC5H,qCAAqC;QACrC,IAAI,aAAa,CAAC,yBAAyB,EAAE;YAC3C,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CACvD,aAAa,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAClF,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAC3D,aAAa,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;SACvF;aAAM;YACL,oBAAoB;YACpB,kHAAkH;YAClH,sHAAsH;YACtH,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;YACtD,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;SAC3D;IACH,CAAC,CAAC,CAAC;CACJ;KAAM;IACL,OAAO,CAAC,IAAI,CACV,gJAAgJ,CACjJ,CAAC;CACH;AAED,eAAe,kBAAkB,CAAC","sourcesContent":["import { NativeModules } from 'react-native';\n\nimport { ProxyNativeModule } from './NativeModulesProxy.types';\n\nconst NativeProxy = NativeModules.NativeUnimoduleProxy;\nconst modulesConstantsKey = 'modulesConstants';\nconst exportedMethodsKey = 'exportedMethods';\n\nconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};\n\nif (NativeProxy) {\n Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {\n NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};\n NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {\n NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {\n const { key, argumentsCount } = methodInfo;\n if (argumentsCount !== args.length) {\n return Promise.reject(\n new Error(\n `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${\n argumentsCount === 1 ? 'argument' : 'arguments'\n } but received ${args.length}`\n )\n );\n }\n return NativeProxy.callMethod(moduleName, key, args);\n };\n });\n\n // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)\n // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.\n //\n // On Android only {start,stop}Observing are called on the native module\n // and these should be exported as Expo methods.\n //\n // Before the RN 65, addListener/removeListeners weren't called on Android. However, it no longer stays true.\n // See https://github.com/facebook/react-native/commit/f5502fbda9fe271ff6e1d0da773a3a8ee206a453.\n // That's why, we check if the `EXReactNativeEventEmitter` exists and only if yes, we use it in the listener implementation.\n // Otherwise, those methods are NOOP.\n if (NativeModules.EXReactNativeEventEmitter) {\n NativeModulesProxy[moduleName].addListener = (...args) =>\n NativeModules.EXReactNativeEventEmitter.addProxiedListener(moduleName, ...args);\n NativeModulesProxy[moduleName].removeListeners = (...args) =>\n NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);\n } else {\n // Fixes on Android:\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.\n NativeModulesProxy[moduleName].addListener = () => {};\n NativeModulesProxy[moduleName].removeListeners = () => {};\n }\n });\n} else {\n console.warn(\n `The \"EXNativeModulesProxy\" native module is not exported through NativeModules; verify that expo-modules-core's native code is linked properly`\n );\n}\n\nexport default NativeModulesProxy;\n"]}
1
+ {"version":3,"file":"NativeModulesProxy.native.js","sourceRoot":"","sources":["../src/NativeModulesProxy.native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAI7C,MAAM,eAAe,GAAG,MAAM,CAAC,WAAW,EAAE,kBAAkB,CAAC;AAC/D,MAAM,iBAAiB,GAAG,aAAa,CAAC,oBAAoB,CAAC;AAE7D,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;AAC/C,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAE7C,MAAM,kBAAkB,GAAgD,EAAE,CAAC;AAE3E,IAAI,iBAAiB,EAAE;IACrB,0DAA0D;IAC1D,MAAM,WAAW,GAAG,eAAe,IAAI,iBAAiB,CAAC;IAEzD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;QAClE,iBAAiB;QACjB,kBAAkB,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC,mBAAmB,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAEpF,eAAe;QACf,WAAW,CAAC,kBAAkB,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,EAAE;YACjE,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAe,EAAgB,EAAE;gBACrF,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,UAAU,CAAC;gBAC3C,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE;oBAClC,OAAO,OAAO,CAAC,MAAM,CACnB,IAAI,KAAK,CACP,iBAAiB,UAAU,IAAI,UAAU,CAAC,IAAI,YAAY,cAAc,IACtE,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WACtC,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAC/B,CACF,CAAC;iBACH;gBAED,iEAAiE;gBACjE,OAAO,iBAAiB,CAAC,UAAU,CAAC,UAAU,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7D,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,kFAAkF;QAClF,EAAE;QACF,wEAAwE;QACxE,gDAAgD;QAChD,EAAE;QACF,6GAA6G;QAC7G,gGAAgG;QAChG,4HAA4H;QAC5H,qCAAqC;QACrC,IAAI,aAAa,CAAC,yBAAyB,EAAE;YAC3C,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CACvD,aAAa,CAAC,yBAAyB,CAAC,kBAAkB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAClF,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,CAC3D,aAAa,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;SACvF;aAAM;YACL,oBAAoB;YACpB,kHAAkH;YAClH,sHAAsH;YACtH,kBAAkB,CAAC,UAAU,CAAC,CAAC,WAAW,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;YACtD,kBAAkB,CAAC,UAAU,CAAC,CAAC,eAAe,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;SAC3D;IACH,CAAC,CAAC,CAAC;CACJ;KAAM;IACL,OAAO,CAAC,IAAI,CACV,gJAAgJ,CACjJ,CAAC;CACH;AAED,eAAe,kBAAkB,CAAC","sourcesContent":["import { NativeModules } from 'react-native';\n\nimport { ProxyNativeModule } from './NativeModulesProxy.types';\n\nconst ExpoNativeProxy = global.ExpoModules?.NativeModulesProxy;\nconst LegacyNativeProxy = NativeModules.NativeUnimoduleProxy;\n\nconst modulesConstantsKey = 'modulesConstants';\nconst exportedMethodsKey = 'exportedMethods';\n\nconst NativeModulesProxy: { [moduleName: string]: ProxyNativeModule } = {};\n\nif (LegacyNativeProxy) {\n // use JSI proxy if available, fallback to legacy RN proxy\n const NativeProxy = ExpoNativeProxy ?? LegacyNativeProxy;\n\n Object.keys(NativeProxy[exportedMethodsKey]).forEach((moduleName) => {\n // copy constants\n NativeModulesProxy[moduleName] = NativeProxy[modulesConstantsKey][moduleName] || {};\n\n // copy methods\n NativeProxy[exportedMethodsKey][moduleName].forEach((methodInfo) => {\n NativeModulesProxy[moduleName][methodInfo.name] = (...args: unknown[]): Promise<any> => {\n const { key, argumentsCount } = methodInfo;\n if (argumentsCount !== args.length) {\n return Promise.reject(\n new Error(\n `Native method ${moduleName}.${methodInfo.name} expects ${argumentsCount} ${\n argumentsCount === 1 ? 'argument' : 'arguments'\n } but received ${args.length}`\n )\n );\n }\n\n // We still want to call methods using the legacy proxy in SDK 46\n return LegacyNativeProxy.callMethod(moduleName, key, args);\n };\n });\n\n // These are called by EventEmitter (which is a wrapper for NativeEventEmitter)\n // only on iOS and they use iOS-specific native module, EXReactNativeEventEmitter.\n //\n // On Android only {start,stop}Observing are called on the native module\n // and these should be exported as Expo methods.\n //\n // Before the RN 65, addListener/removeListeners weren't called on Android. However, it no longer stays true.\n // See https://github.com/facebook/react-native/commit/f5502fbda9fe271ff6e1d0da773a3a8ee206a453.\n // That's why, we check if the `EXReactNativeEventEmitter` exists and only if yes, we use it in the listener implementation.\n // Otherwise, those methods are NOOP.\n if (NativeModules.EXReactNativeEventEmitter) {\n NativeModulesProxy[moduleName].addListener = (...args) =>\n NativeModules.EXReactNativeEventEmitter.addProxiedListener(moduleName, ...args);\n NativeModulesProxy[moduleName].removeListeners = (...args) =>\n NativeModules.EXReactNativeEventEmitter.removeProxiedListeners(moduleName, ...args);\n } else {\n // Fixes on Android:\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `addListener` method.\n // WARN `new NativeEventEmitter()` was called with a non-null argument without the required `removeListeners` method.\n NativeModulesProxy[moduleName].addListener = () => {};\n NativeModulesProxy[moduleName].removeListeners = () => {};\n }\n });\n} else {\n console.warn(\n `The \"EXNativeModulesProxy\" native module is not exported through NativeModules; verify that expo-modules-core's native code is linked properly`\n );\n}\n\nexport default NativeModulesProxy;\n"]}
@@ -1,13 +1,42 @@
1
1
  export declare enum PermissionStatus {
2
+ /**
3
+ * User has granted the permission.
4
+ */
2
5
  GRANTED = "granted",
6
+ /**
7
+ * User hasn't granted or denied the permission yet.
8
+ */
3
9
  UNDETERMINED = "undetermined",
10
+ /**
11
+ * User has denied the permission.
12
+ */
4
13
  DENIED = "denied"
5
14
  }
15
+ /**
16
+ * Permission expiration time. Currently, all permissions are granted permamently.
17
+ */
6
18
  export declare type PermissionExpiration = 'never' | number;
19
+ /**
20
+ * An object obtained by `getPermissionsAsync` and `requestPermissionsAsync` functions.
21
+ */
7
22
  export interface PermissionResponse {
23
+ /**
24
+ * Determines the status of the permission.
25
+ */
8
26
  status: PermissionStatus;
27
+ /**
28
+ * Determines time when the permission expires.
29
+ */
9
30
  expires: PermissionExpiration;
31
+ /**
32
+ * A convenience boolean that indicates if the permission is granted.
33
+ */
10
34
  granted: boolean;
35
+ /**
36
+ * Indicates if user can be asked again for specific permission.
37
+ * If not, one should be directed to the Settings app
38
+ * in order to enable/disable the permission.
39
+ */
11
40
  canAskAgain: boolean;
12
41
  }
13
42
  //# sourceMappingURL=PermissionsInterface.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionsInterface.d.ts","sourceRoot":"","sources":["../src/PermissionsInterface.ts"],"names":[],"mappings":"AAAA,oBAAY,gBAAgB;IAC1B,OAAO,YAAY;IACnB,YAAY,iBAAiB;IAC7B,MAAM,WAAW;CAClB;AAED,oBAAY,oBAAoB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"PermissionsInterface.d.ts","sourceRoot":"","sources":["../src/PermissionsInterface.ts"],"names":[],"mappings":"AAAA,oBAAY,gBAAgB;IAC1B;;OAEG;IACH,OAAO,YAAY;IACnB;;OAEG;IACH,YAAY,iBAAiB;IAC7B;;OAEG;IACH,MAAM,WAAW;CAClB;AAED;;GAEG;AACH,oBAAY,oBAAoB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;IACzB;;OAEG;IACH,OAAO,EAAE,oBAAoB,CAAC;IAC9B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB"}
@@ -1,7 +1,16 @@
1
1
  export var PermissionStatus;
2
2
  (function (PermissionStatus) {
3
+ /**
4
+ * User has granted the permission.
5
+ */
3
6
  PermissionStatus["GRANTED"] = "granted";
7
+ /**
8
+ * User hasn't granted or denied the permission yet.
9
+ */
4
10
  PermissionStatus["UNDETERMINED"] = "undetermined";
11
+ /**
12
+ * User has denied the permission.
13
+ */
5
14
  PermissionStatus["DENIED"] = "denied";
6
15
  })(PermissionStatus || (PermissionStatus = {}));
7
16
  //# sourceMappingURL=PermissionsInterface.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionsInterface.js","sourceRoot":"","sources":["../src/PermissionsInterface.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,uCAAmB,CAAA;IACnB,iDAA6B,CAAA;IAC7B,qCAAiB,CAAA;AACnB,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B","sourcesContent":["export enum PermissionStatus {\n GRANTED = 'granted',\n UNDETERMINED = 'undetermined',\n DENIED = 'denied',\n}\n\nexport type PermissionExpiration = 'never' | number;\n\nexport interface PermissionResponse {\n status: PermissionStatus;\n expires: PermissionExpiration;\n granted: boolean;\n canAskAgain: boolean;\n}\n"]}
1
+ {"version":3,"file":"PermissionsInterface.js","sourceRoot":"","sources":["../src/PermissionsInterface.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,gBAaX;AAbD,WAAY,gBAAgB;IAC1B;;OAEG;IACH,uCAAmB,CAAA;IACnB;;OAEG;IACH,iDAA6B,CAAA;IAC7B;;OAEG;IACH,qCAAiB,CAAA;AACnB,CAAC,EAbW,gBAAgB,KAAhB,gBAAgB,QAa3B","sourcesContent":["export enum PermissionStatus {\n /**\n * User has granted the permission.\n */\n GRANTED = 'granted',\n /**\n * User hasn't granted or denied the permission yet.\n */\n UNDETERMINED = 'undetermined',\n /**\n * User has denied the permission.\n */\n DENIED = 'denied',\n}\n\n/**\n * Permission expiration time. Currently, all permissions are granted permamently.\n */\nexport type PermissionExpiration = 'never' | number;\n\n/**\n * An object obtained by `getPermissionsAsync` and `requestPermissionsAsync` functions.\n */\nexport interface PermissionResponse {\n /**\n * Determines the status of the permission.\n */\n status: PermissionStatus;\n /**\n * Determines time when the permission expires.\n */\n expires: PermissionExpiration;\n /**\n * A convenience boolean that indicates if the permission is granted.\n */\n granted: boolean;\n /**\n * Indicates if user can be asked again for specific permission.\n * If not, one should be directed to the Settings app\n * in order to enable/disable the permission.\n */\n canAskAgain: boolean;\n}\n"]}
@@ -3,7 +3,6 @@
3
3
  #import <ExpoModulesCore/EXLegacyAppDelegateWrapper.h>
4
4
 
5
5
  #import <ExpoModulesCore/EXAppDelegatesLoader.h>
6
- #import <ExpoModulesCore/EXNativeModulesProxy.h>
7
6
  #import <ExpoModulesCore/Swift.h>
8
7
 
9
8
  // Make the legacy wrapper conform to the protocol for subscribers.
@@ -17,7 +16,7 @@
17
16
  // and before any code is executed, so we switch back to Objective-C just to do this one thing.
18
17
  + (void)load
19
18
  {
20
- ModulesProvider *modulesProvider = [EXNativeModulesProxy getExpoModulesProvider];
19
+ ModulesProvider *modulesProvider = [EXAppContext modulesProviderWithName:@"ExpoModulesProvider"];
21
20
  [EXExpoAppDelegate registerSubscriber:[[EXLegacyAppDelegateWrapper alloc] init]];
22
21
  [EXExpoAppDelegate registerSubscribersFromModulesProvider:modulesProvider];
23
22
  [EXExpoAppDelegate registerReactDelegateHandlersFromModulesProvider:modulesProvider];
@@ -22,9 +22,10 @@ Pod::Spec.new do |s|
22
22
  'DEFINES_MODULE' => 'YES',
23
23
  'CLANG_CXX_LANGUAGE_STANDARD' => 'c++14',
24
24
  'SWIFT_COMPILATION_MODE' => 'wholemodule',
25
+ 'HEADER_SEARCH_PATHS' => "\"$(PODS_ROOT)/Headers/Private/React-bridging/react/bridging\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-bridging/react_bridging.framework/Headers\"",
25
26
  }
26
27
  s.user_target_xcconfig = {
27
- "HEADER_SEARCH_PATHS" => "\"${PODS_CONFIGURATION_BUILD_DIR}/ExpoModulesCore/Swift Compatibility Header\"",
28
+ "HEADER_SEARCH_PATHS" => "\"${PODS_CONFIGURATION_BUILD_DIR}/ExpoModulesCore/Swift Compatibility Header\" \"$(PODS_ROOT)/Headers/Private/React-bridging/react/bridging\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-bridging/react_bridging.framework/Headers\"",
28
29
  }
29
30
 
30
31
  s.dependency 'React-Core'
@@ -34,7 +35,7 @@ Pod::Spec.new do |s|
34
35
  s.source_files = '**/*.h'
35
36
  s.vendored_frameworks = "#{s.name}.xcframework"
36
37
  else
37
- s.source_files = '**/*.{h,m,mm,swift}'
38
+ s.source_files = '**/*.{h,m,mm,swift,cpp}'
38
39
  end
39
40
 
40
41
  s.exclude_files = 'Tests/'
@@ -1,6 +1,9 @@
1
1
  // Copyright 2018-present 650 Industries. All rights reserved.
2
2
 
3
3
  #import <ReactCommon/TurboModuleUtils.h>
4
+ #import <ExpoModulesCore/EXJavaScriptValue.h>
5
+ #import <ExpoModulesCore/EXJavaScriptObject.h>
6
+ #import <ExpoModulesCore/EXJavaScriptWeakObject.h>
4
7
  #import <ExpoModulesCore/EXJSIConversions.h>
5
8
  #import <ExpoModulesCore/EXJavaScriptValue.h>
6
9
  #import <ExpoModulesCore/EXJavaScriptRuntime.h>
@@ -60,6 +63,9 @@ jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value)
60
63
  if ([value isKindOfClass:[EXJavaScriptObject class]]) {
61
64
  return jsi::Value(runtime, *[(EXJavaScriptObject *)value get]);
62
65
  }
66
+ if ([value isKindOfClass:[EXJavaScriptWeakObject class]]) {
67
+ return jsi::Value(runtime, *[[(EXJavaScriptWeakObject *)value lock] get]);
68
+ }
63
69
  if ([value isKindOfClass:[NSString class]]) {
64
70
  return convertNSStringToJSIString(runtime, (NSString *)value);
65
71
  } else if ([value isKindOfClass:[NSNumber class]]) {
@@ -1,29 +1,23 @@
1
1
  // Copyright 2018-present 650 Industries. All rights reserved.
2
2
 
3
- #ifdef __cplusplus
3
+ #import <React/RCTBridge.h>
4
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
20
-
21
- #import <ExpoModulesCore/EXJavaScriptRuntime.h>
22
-
23
- @class SwiftInteropBridge;
5
+ // Swift classes need forward-declaration in the headers.
6
+ @class EXAppContext;
7
+ @class EXJavaScriptRuntime;
24
8
 
25
9
  @interface EXJavaScriptRuntimeManager : NSObject
26
10
 
27
- + (void)installExpoModulesToRuntime:(nonnull EXJavaScriptRuntime *)runtime withSwiftInterop:(nonnull SwiftInteropBridge *)swiftInterop;
11
+ /**
12
+ Gets the JS runtime from the given bridge. May return `nil` when
13
+ the runtime is not available yet or the remote debugging is enabled.
14
+ */
15
+ + (nullable EXJavaScriptRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge NS_SWIFT_NAME(runtime(fromBridge:));
16
+
17
+ /**
18
+ Installs ExpoModules host object in the runtime of the given app context.
19
+ Returns a bool value whether the installation succeeded.
20
+ */
21
+ + (BOOL)installExpoModulesHostObject:(nonnull EXAppContext *)appContext;
28
22
 
29
23
  @end
@@ -4,14 +4,50 @@
4
4
  #import <ExpoModulesCore/ExpoModulesHostObject.h>
5
5
  #import <ExpoModulesCore/Swift.h>
6
6
 
7
+ namespace jsi = facebook::jsi;
8
+
9
+ /**
10
+ This name will be used as a property of the JS global object to which the host object is added.
11
+ */
12
+ static NSString *expoModulesHostObjectPropertyName = @"ExpoModules";
13
+
14
+ @interface RCTBridge (ExpoBridgeWithRuntime)
15
+
16
+ - (void *)runtime;
17
+
18
+ @end
19
+
7
20
  @implementation EXJavaScriptRuntimeManager
8
21
 
9
- + (void)installExpoModulesToRuntime:(nonnull EXJavaScriptRuntime *)runtime withSwiftInterop:(nonnull SwiftInteropBridge *)swiftInterop
22
+ + (nullable EXJavaScriptRuntime *)runtimeFromBridge:(nonnull RCTBridge *)bridge
10
23
  {
11
- std::shared_ptr<expo::ExpoModulesHostObject> hostObjectPtr = std::make_shared<expo::ExpoModulesHostObject>(swiftInterop);
24
+ jsi::Runtime *jsiRuntime = [bridge respondsToSelector:@selector(runtime)] ? reinterpret_cast<jsi::Runtime *>(bridge.runtime) : nullptr;
25
+ return jsiRuntime ? [[EXJavaScriptRuntime alloc] initWithRuntime:jsiRuntime callInvoker:bridge.jsCallInvoker] : nil;
26
+ }
27
+
28
+ + (BOOL)installExpoModulesHostObject:(nonnull EXAppContext *)appContext
29
+ {
30
+ EXJavaScriptRuntime *runtime = [appContext runtime];
31
+
32
+ // The runtime may be unavailable, e.g. remote debugger is enabled or it hasn't been set yet.
33
+ if (!runtime) {
34
+ return false;
35
+ }
36
+
12
37
  EXJavaScriptObject *global = [runtime global];
13
38
 
14
- [global setProperty:@"ExpoModules" value:[runtime createHostObject:hostObjectPtr]];
39
+ if ([global hasProperty:expoModulesHostObjectPropertyName]) {
40
+ return false;
41
+ }
42
+
43
+ std::shared_ptr<expo::ExpoModulesHostObject> hostObjectPtr = std::make_shared<expo::ExpoModulesHostObject>(appContext);
44
+ EXJavaScriptObject *hostObject = [runtime createHostObject:hostObjectPtr];
45
+
46
+ // Define the ExpoModules object as a non-configurable, read-only and enumerable property.
47
+ [global defineProperty:expoModulesHostObjectPropertyName
48
+ value:hostObject
49
+ options:EXJavaScriptObjectPropertyDescriptorEnumerable];
50
+ return true;
15
51
  }
16
52
 
17
53
  @end
@@ -2,17 +2,62 @@
2
2
 
3
3
  #ifdef __cplusplus
4
4
 
5
+ #import <functional>
6
+
5
7
  #import <jsi/jsi.h>
6
8
  #import <ReactCommon/RCTTurboModule.h>
9
+ #import <ReactCommon/TurboModuleUtils.h>
10
+ #import <ExpoModulesCore/EXObjectDeallocator.h>
7
11
 
8
- using namespace facebook;
9
- using namespace react;
12
+ namespace jsi = facebook::jsi;
13
+ namespace react = facebook::react;
10
14
 
11
15
  namespace expo {
12
16
 
17
+ #pragma mark - Promises
18
+
13
19
  using PromiseInvocationBlock = void (^)(RCTPromiseResolveBlock resolveWrapper, RCTPromiseRejectBlock rejectWrapper);
14
20
 
15
- void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> jsInvoker, std::shared_ptr<Promise> promise, PromiseInvocationBlock setupBlock);
21
+ void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<react::CallInvoker> jsInvoker, std::shared_ptr<react::Promise> promise, PromiseInvocationBlock setupBlock);
22
+
23
+ #pragma mark - Classes
24
+
25
+ using ClassConstructor = std::function<void(jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *args, size_t count)>;
26
+
27
+ std::shared_ptr<jsi::Function> createClass(jsi::Runtime &runtime, const char *name, ClassConstructor constructor);
28
+
29
+ #pragma mark - Weak objects
30
+
31
+ /**
32
+ Checks whether the `WeakRef` class is available in the given runtime.
33
+ According to the docs, it is unimplemented in JSC prior to iOS 14.5.
34
+ As of the time of writing this comment it's also unimplemented in Hermes
35
+ where you should use `jsi::WeakObject` instead.
36
+ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
37
+ */
38
+ bool isWeakRefSupported(jsi::Runtime &runtime);
39
+
40
+ /**
41
+ Creates the `WeakRef` with given JSI object. You should first use `isWeakRefSupported`
42
+ to check whether this feature is supported by the runtime.
43
+ */
44
+ std::shared_ptr<jsi::Object> createWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object);
45
+
46
+ /**
47
+ Returns the `WeakRef` object's target object, or an empty pointer if the target object has been reclaimed.
48
+ */
49
+ std::shared_ptr<jsi::Object> derefWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object);
50
+
51
+ #pragma mark - Define property
52
+
53
+ void defineProperty(jsi::Runtime &runtime, const jsi::Object *object, const char *name, jsi::Value value);
54
+
55
+ #pragma mark - Deallocator
56
+
57
+ /**
58
+ Sets the deallocator block on a given object, which is called when the object is being deallocated.
59
+ */
60
+ void setDeallocator(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object, ObjectDeallocatorBlock deallocatorBlock);
16
61
 
17
62
  } // namespace expo
18
63
 
@@ -1,17 +1,17 @@
1
1
  // Copyright 2022-present 650 Industries. All rights reserved.
2
2
 
3
+ #import <sstream>
4
+
3
5
  #import <React/RCTUtils.h>
4
6
  #import <ExpoModulesCore/EXJSIConversions.h>
5
7
  #import <ExpoModulesCore/EXJSIUtils.h>
6
8
 
7
- using namespace facebook;
8
-
9
9
  namespace expo {
10
10
 
11
11
  void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoker> jsInvoker, std::shared_ptr<Promise> promise, PromiseInvocationBlock setupBlock)
12
12
  {
13
- auto weakResolveWrapper = CallbackWrapper::createWeak(promise->resolve_.getFunction(runtime), runtime, jsInvoker);
14
- auto weakRejectWrapper = CallbackWrapper::createWeak(promise->reject_.getFunction(runtime), runtime, jsInvoker);
13
+ auto weakResolveWrapper = react::CallbackWrapper::createWeak(promise->resolve_.getFunction(runtime), runtime, jsInvoker);
14
+ auto weakRejectWrapper = react::CallbackWrapper::createWeak(promise->reject_.getFunction(runtime), runtime, jsInvoker);
15
15
 
16
16
  __block BOOL resolveWasCalled = NO;
17
17
  __block BOOL rejectWasCalled = NO;
@@ -86,4 +86,88 @@ void callPromiseSetupWithBlock(jsi::Runtime &runtime, std::shared_ptr<CallInvoke
86
86
  setupBlock(resolveBlock, rejectBlock);
87
87
  }
88
88
 
89
+ std::shared_ptr<jsi::Function> createClass(jsi::Runtime &runtime, const char *name, ClassConstructor constructor) {
90
+ std::string nativeConstructorKey("__native_constructor__");
91
+
92
+ // Create a string buffer of the source code to evaluate.
93
+ std::stringstream source;
94
+ source << "(function " << name << "(...args) { this." << nativeConstructorKey << "(...args); return this; })";
95
+ std::shared_ptr<jsi::StringBuffer> sourceBuffer = std::make_shared<jsi::StringBuffer>(source.str());
96
+
97
+ // Evaluate the code and obtain returned value (the constructor function).
98
+ jsi::Object klass = runtime.evaluateJavaScript(sourceBuffer, "").asObject(runtime);
99
+
100
+ // Set the native constructor in the prototype.
101
+ jsi::Object prototype = klass.getPropertyAsObject(runtime, "prototype");
102
+ jsi::PropNameID nativeConstructorPropId = jsi::PropNameID::forAscii(runtime, nativeConstructorKey);
103
+ jsi::Function nativeConstructor = jsi::Function::createFromHostFunction(
104
+ runtime,
105
+ nativeConstructorPropId,
106
+ // The paramCount is not obligatory to match, it only affects the `length` property of the function.
107
+ 0,
108
+ [constructor](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *args, size_t count) -> jsi::Value {
109
+ constructor(runtime, thisValue, args, count);
110
+ return jsi::Value::undefined();
111
+ });
112
+
113
+ defineProperty(runtime, &prototype, nativeConstructorKey.c_str(), jsi::Value(runtime, nativeConstructor));
114
+
115
+ return std::make_shared<jsi::Function>(klass.asFunction(runtime));
116
+ }
117
+
118
+ #pragma mark - Weak objects
119
+
120
+ bool isWeakRefSupported(jsi::Runtime &runtime) {
121
+ return runtime.global().hasProperty(runtime, "WeakRef");
122
+ }
123
+
124
+ std::shared_ptr<jsi::Object> createWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object) {
125
+ jsi::Object weakRef = runtime
126
+ .global()
127
+ .getProperty(runtime, "WeakRef")
128
+ .asObject(runtime)
129
+ .asFunction(runtime)
130
+ .callAsConstructor(runtime, jsi::Value(runtime, *object))
131
+ .asObject(runtime);
132
+ return std::make_shared<jsi::Object>(std::move(weakRef));
133
+ }
134
+
135
+ std::shared_ptr<jsi::Object> derefWeakRef(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object) {
136
+ jsi::Value ref = object->getProperty(runtime, "deref")
137
+ .asObject(runtime)
138
+ .asFunction(runtime)
139
+ .callWithThis(runtime, *object);
140
+
141
+ if (ref.isUndefined()) {
142
+ return nullptr;
143
+ }
144
+ return std::make_shared<jsi::Object>(ref.asObject(runtime));
145
+ }
146
+
147
+ #pragma mark - Define property
148
+
149
+ void defineProperty(jsi::Runtime &runtime, const jsi::Object *object, const char *name, jsi::Value value) {
150
+ jsi::Object global = runtime.global();
151
+ jsi::Object objectClass = global.getPropertyAsObject(runtime, "Object");
152
+ jsi::Function definePropertyFunction = objectClass.getPropertyAsFunction(runtime, "defineProperty");
153
+
154
+ jsi::Object descriptor(runtime);
155
+ descriptor.setProperty(runtime, "value", value);
156
+
157
+ definePropertyFunction.callWithThis(runtime, objectClass, {
158
+ jsi::Value(runtime, *object),
159
+ jsi::String::createFromUtf8(runtime, name),
160
+ std::move(descriptor),
161
+ });
162
+ }
163
+
164
+ #pragma mark - Deallocator
165
+
166
+ void setDeallocator(jsi::Runtime &runtime, std::shared_ptr<jsi::Object> object, ObjectDeallocatorBlock deallocatorBlock) {
167
+ std::shared_ptr<expo::ObjectDeallocator> hostObjectPtr = std::make_shared<ObjectDeallocator>(deallocatorBlock);
168
+ jsi::Object jsObject = jsi::Object::createFromHostObject(runtime, hostObjectPtr);
169
+
170
+ object->setProperty(runtime, "__expo_object_deallocator__", jsi::Value(runtime, jsObject));
171
+ }
172
+
89
173
  } // namespace expo
@@ -1,20 +1,16 @@
1
1
  // Copyright 2022-present 650 Industries. All rights reserved.
2
2
 
3
3
  #import <Foundation/Foundation.h>
4
- #import <React/RCTBridgeModule.h>
5
4
 
6
5
  #ifdef __cplusplus
7
6
  #import <jsi/jsi.h>
8
- #import <ReactCommon/CallInvoker.h>
9
7
 
10
8
  namespace jsi = facebook::jsi;
11
9
  #endif // __cplusplus
12
10
 
13
- typedef void (^JSAsyncFunctionBlock)(NSArray * _Nonnull, RCTPromiseResolveBlock _Nonnull, RCTPromiseRejectBlock _Nonnull);
14
- typedef id _Nullable (^JSSyncFunctionBlock)(NSArray * _Nonnull);
15
-
16
11
  @class EXJavaScriptRuntime;
17
12
  @class EXJavaScriptValue;
13
+ @class EXJavaScriptWeakObject;
18
14
 
19
15
  /**
20
16
  The property descriptor options for the property being defined or modified.
@@ -73,25 +69,22 @@ NS_SWIFT_NAME(JavaScriptObject)
73
69
  */
74
70
  - (void)setProperty:(nonnull NSString *)name value:(nullable id)value;
75
71
 
72
+ /**
73
+ Defines a new property or modifies an existing property on the object using the property descriptor.
74
+ */
75
+ - (void)defineProperty:(nonnull NSString *)name descriptor:(nonnull EXJavaScriptObject *)descriptor;
76
+
76
77
  /**
77
78
  Defines a new property or modifies an existing property on the object. Calls `Object.defineProperty` under the hood.
78
79
  */
79
80
  - (void)defineProperty:(nonnull NSString *)name value:(nullable id)value options:(EXJavaScriptObjectPropertyDescriptor)options;
80
81
 
81
- #pragma mark - Functions
82
+ #pragma mark - WeakObject
82
83
 
83
- /**
84
- Sets given function block on the object as a host function returning a promise.
85
- */
86
- - (void)setAsyncFunction:(nonnull NSString *)key
87
- argsCount:(NSInteger)argsCount
88
- block:(nonnull JSAsyncFunctionBlock)block;
84
+ - (nonnull EXJavaScriptWeakObject *)createWeak;
89
85
 
90
- /**
91
- Sets given synchronous function block as a host function on the object.
92
- */
93
- - (void)setSyncFunction:(nonnull NSString *)name
94
- argsCount:(NSInteger)argsCount
95
- block:(nonnull JSSyncFunctionBlock)block;
86
+ #pragma mark - Deallocator
87
+
88
+ - (void)setObjectDeallocator:(void (^ _Nonnull)(void))deallocatorBlock;
96
89
 
97
90
  @end
@@ -1,8 +1,11 @@
1
1
  // Copyright 2022-present 650 Industries. All rights reserved.
2
2
 
3
3
  #import <ExpoModulesCore/EXJSIConversions.h>
4
+ #import <ExpoModulesCore/EXJavaScriptValue.h>
4
5
  #import <ExpoModulesCore/EXJavaScriptObject.h>
5
6
  #import <ExpoModulesCore/EXJavaScriptRuntime.h>
7
+ #import <ExpoModulesCore/EXJavaScriptWeakObject.h>
8
+ #import <ExpoModulesCore/EXJSIUtils.h>
6
9
 
7
10
  @implementation EXJavaScriptObject {
8
11
  /**
@@ -62,6 +65,21 @@
62
65
  _jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], jsiValue);
63
66
  }
64
67
 
68
+ - (void)defineProperty:(nonnull NSString *)name descriptor:(nonnull EXJavaScriptObject *)descriptor
69
+ {
70
+ jsi::Runtime *runtime = [_runtime get];
71
+ jsi::Object global = runtime->global();
72
+ jsi::Object objectClass = global.getPropertyAsObject(*runtime, "Object");
73
+ jsi::Function definePropertyFunction = objectClass.getPropertyAsFunction(*runtime, "defineProperty");
74
+
75
+ // This call is basically the same as `Object.defineProperty(object, name, descriptor)` in JS
76
+ definePropertyFunction.callWithThis(*runtime, objectClass, {
77
+ jsi::Value(*runtime, *_jsObjectPtr.get()),
78
+ jsi::String::createFromUtf8(*runtime, [name UTF8String]),
79
+ std::move(*[descriptor get]),
80
+ });
81
+ }
82
+
65
83
  - (void)defineProperty:(nonnull NSString *)name value:(nullable id)value options:(EXJavaScriptObjectPropertyDescriptor)options
66
84
  {
67
85
  jsi::Runtime *runtime = [_runtime get];
@@ -80,30 +98,31 @@
80
98
  });
81
99
  }
82
100
 
83
- #pragma mark - Functions
101
+ #pragma mark - WeakObject
84
102
 
85
- - (void)setAsyncFunction:(nonnull NSString *)name
86
- argsCount:(NSInteger)argsCount
87
- block:(nonnull JSAsyncFunctionBlock)block
103
+ - (nonnull EXJavaScriptWeakObject *)createWeak
88
104
  {
89
- if (!_runtime) {
90
- NSLog(@"Cannot set '%@' async function when the EXJavaScript runtime is no longer available.", name);
91
- return;
92
- }
93
- jsi::Function function = [_runtime createAsyncFunction:name argsCount:argsCount block:block];
94
- _jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], function);
105
+ return [[EXJavaScriptWeakObject alloc] initWith:_jsObjectPtr runtime:_runtime];
95
106
  }
96
107
 
97
- - (void)setSyncFunction:(nonnull NSString *)name
98
- argsCount:(NSInteger)argsCount
99
- block:(nonnull JSSyncFunctionBlock)block
108
+ #pragma mark - Deallocator
109
+
110
+ - (void)setObjectDeallocator:(void (^)(void))deallocatorBlock
111
+ {
112
+ expo::setDeallocator(*[_runtime get], _jsObjectPtr, deallocatorBlock);
113
+ }
114
+
115
+ #pragma mark - Equality
116
+
117
+ - (BOOL)isEqual:(id)object
100
118
  {
101
- if (!_runtime) {
102
- NSLog(@"Cannot set '%@' sync function when the EXJavaScript runtime is no longer available.", name);
103
- return;
119
+ if ([object isKindOfClass:EXJavaScriptObject.class]) {
120
+ jsi::Runtime *runtime = [_runtime get];
121
+ jsi::Object *a = _jsObjectPtr.get();
122
+ jsi::Object *b = [object get];
123
+ return jsi::Object::strictEquals(*runtime, *a, *b);
104
124
  }
105
- jsi::Function function = [_runtime createSyncFunction:name argsCount:argsCount block:block];
106
- _jsObjectPtr->setProperty(*[_runtime get], [name UTF8String], function);
125
+ return false;
107
126
  }
108
127
 
109
128
  #pragma mark - Private helpers