expo-modules-core 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/android/build.gradle +26 -19
  3. package/android/src/main/cpp/JSIInteropModuleRegistry.cpp +19 -2
  4. package/android/src/main/cpp/JSIInteropModuleRegistry.h +11 -1
  5. package/android/src/main/cpp/JavaScriptModuleObject.cpp +14 -13
  6. package/android/src/main/cpp/JavaScriptModuleObject.h +4 -1
  7. package/android/src/main/cpp/JavaScriptObject.cpp +12 -27
  8. package/android/src/main/cpp/JavaScriptObject.h +2 -8
  9. package/android/src/main/cpp/JavaScriptRuntime.cpp +44 -17
  10. package/android/src/main/cpp/JavaScriptRuntime.h +9 -16
  11. package/android/src/main/cpp/MethodMetadata.cpp +12 -13
  12. package/android/src/main/cpp/types/FrontendConverter.cpp +20 -3
  13. package/android/src/main/cpp/types/JNIToJSIConverter.cpp +7 -8
  14. package/android/src/main/java/expo/modules/adapters/react/ModuleRegistryAdapter.java +1 -14
  15. package/android/src/main/java/expo/modules/adapters/react/NativeModulesProxy.java +1 -11
  16. package/android/src/main/java/expo/modules/adapters/react/views/ViewManagerAdapterUtils.java +0 -54
  17. package/android/src/main/java/expo/modules/core/ModuleRegistry.java +0 -16
  18. package/android/src/main/java/expo/modules/core/ViewManager.java +3 -130
  19. package/android/src/main/java/expo/modules/kotlin/AppContext.kt +21 -3
  20. package/android/src/main/java/expo/modules/kotlin/KotlinInteropModuleRegistry.kt +3 -2
  21. package/android/src/main/java/expo/modules/kotlin/Promise.kt +5 -1
  22. package/android/src/main/java/expo/modules/kotlin/activityresult/ActivityResultsManager.kt +1 -2
  23. package/android/src/main/java/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +18 -1
  24. package/android/src/main/java/expo/modules/kotlin/defaultmodules/ErrorManagerModule.kt +12 -1
  25. package/android/src/main/java/expo/modules/kotlin/functions/AnyFunction.kt +1 -0
  26. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunction.kt +1 -13
  27. package/android/src/main/java/expo/modules/kotlin/functions/AsyncFunctionBuilder.kt +106 -13
  28. package/android/src/main/java/expo/modules/kotlin/functions/FunctionBuilder.kt +103 -0
  29. package/android/src/main/java/expo/modules/kotlin/jni/JSIInteropModuleRegistry.kt +2 -1
  30. package/android/src/main/java/expo/modules/kotlin/jni/JavaScriptModuleObject.kt +10 -2
  31. package/android/src/main/java/expo/modules/kotlin/modules/Module.kt +32 -1
  32. package/android/src/main/java/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +43 -20
  33. package/android/src/main/java/expo/modules/kotlin/objects/PropertyComponent.kt +11 -7
  34. package/android/src/main/java/expo/modules/kotlin/objects/PropertyComponentBuilder.kt +35 -3
  35. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +12 -2
  36. package/android/src/main/java/expo/modules/kotlin/sharedobjects/SharedObjectTypeConverter.kt +11 -3
  37. package/android/src/main/java/expo/modules/kotlin/types/EnumTypeConverter.kt +0 -1
  38. package/android/src/main/java/expo/modules/kotlin/types/MapTypeConverter.kt +0 -2
  39. package/android/src/main/java/expo/modules/kotlin/types/ReadableArgumentsTypeConverter.kt +24 -0
  40. package/android/src/main/java/expo/modules/kotlin/types/TypeConverterProvider.kt +3 -2
  41. package/android/src/main/java/expo/modules/kotlin/viewevent/ViewEventDelegate.kt +0 -2
  42. package/android/src/main/java/expo/modules/kotlin/views/AnyViewProp.kt +2 -1
  43. package/android/src/main/java/expo/modules/kotlin/views/ConcreteViewProp.kt +3 -2
  44. package/android/src/main/java/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +1 -2
  45. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerDefinition.kt +3 -4
  46. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerType.kt +5 -0
  47. package/android/src/main/java/expo/modules/kotlin/views/ViewManagerWrapperDelegate.kt +1 -1
  48. package/android/src/main/java/expo/modules/kotlin/views/ViewTypeConverter.kt +3 -3
  49. package/android/src/reactnative/expo/modules/kotlin/ReactNativeCompatibleHelper.kt +12 -0
  50. package/android/src/reactnative72/expo/modules/kotlin/ReactNativeCompatibleHelper.kt +12 -0
  51. package/android-annotation/build.gradle +6 -3
  52. package/android-annotation-processor/build.gradle +6 -3
  53. package/build/errors/UnavailabilityError.d.ts.map +1 -1
  54. package/build/errors/UnavailabilityError.js +1 -1
  55. package/build/errors/UnavailabilityError.js.map +1 -1
  56. package/build/sweet/setUpErrorManager.fx.js +5 -1
  57. package/build/sweet/setUpErrorManager.fx.js.map +1 -1
  58. package/build/uuid/v4.js +2 -7
  59. package/build/uuid/v4.js.map +1 -1
  60. package/common/cpp/JSIUtils.cpp +23 -2
  61. package/common/cpp/JSIUtils.h +12 -2
  62. package/common/cpp/LazyObject.cpp +1 -1
  63. package/common/cpp/ObjectDeallocator.cpp +21 -0
  64. package/common/cpp/ObjectDeallocator.h +37 -0
  65. package/ios/JSI/EXJSIUtils.h +1 -12
  66. package/ios/JSI/EXJSIUtils.mm +5 -27
  67. package/ios/JSI/EXJavaScriptObject.mm +8 -21
  68. package/ios/ReactDelegates/EXReactCompatibleHelpers.m +7 -7
  69. package/ios/Swift/Views/ViewModuleWrapper.swift +3 -1
  70. package/package.json +2 -2
  71. package/src/errors/UnavailabilityError.ts +1 -1
  72. package/src/sweet/setUpErrorManager.fx.ts +6 -1
  73. package/src/uuid/v4.ts +2 -6
  74. package/tsconfig.json +1 -1
  75. package/android/src/main/cpp/ObjectDeallocator.h +0 -25
  76. package/android/src/main/java/expo/modules/adapters/react/views/SimpleViewManagerAdapter.java +0 -62
  77. package/android/src/main/java/expo/modules/adapters/react/views/ViewGroupManagerAdapter.java +0 -62
  78. package/ios/JSI/EXObjectDeallocator.h +0 -27
package/CHANGELOG.md CHANGED
@@ -10,6 +10,30 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 1.7.0 — 2023-09-04
14
+
15
+ ### 🎉 New features
16
+
17
+ - [Android] Surfaced errorManager to allow throwing errors and warnings from modules. ([#23848](https://github.com/expo/expo/pull/23848) by [@aleqsio](https://github.com/aleqsio))
18
+ - [Android] Enums can now be used to define events. ([#23875](https://github.com/expo/expo/pull/23875) by [@lukmccall](https://github.com/lukmccall))
19
+ - [Android] Promises can now be resolved without arguments. ([#23907](https://github.com/expo/expo/pull/23907) by [@lukmccall](https://github.com/lukmccall))
20
+ - Added support for React Native 0.73. ([#24018](https://github.com/expo/expo/pull/24018), [#24019](https://github.com/expo/expo/pull/24019) by [@kudo](https://github.com/kudo))
21
+ - [Android] `Property` component can now take the native shared object instance as the first argument. ([#24206](https://github.com/expo/expo/pull/24206) by [@lukmccall](https://github.com/lukmccall))
22
+
23
+ ### 🐛 Bug fixes
24
+
25
+ - [Android] Refresh NativeModulesProxy if app bundle is reloaded. ([#23824](https://github.com/expo/expo/pull/23824) by [@douglowder](https://github.com/douglowder))
26
+ - [Android] Fix nullability of parameter type in `List` and `Map` when converting from JS to native. ([#23942](https://github.com/expo/expo/pull/23942) by [@lukmccall](https://github.com/lukmccall))
27
+ - Fixed Fabric setup error on iOS. ([#24004](https://github.com/expo/expo/pull/24004) by [@kudo](https://github.com/kudo))
28
+ - Fixed uuid v4 generation. ([#24123](https://github.com/expo/expo/pull/24123) by [@tsapeta](https://github.com/tsapeta))
29
+ - [Android] Fixed owner type of view functions. ([#24135](https://github.com/expo/expo/pull/24135) by [@lukmccall](https://github.com/lukmccall))
30
+
31
+ ### 💡 Others
32
+
33
+ - [Android] Add type converter for the `ReadableArguments` class to allow backward compatibility with older modules. ([#24137](https://github.com/expo/expo/pull/24137) by [@lukmccall](https://github.com/lukmccall))
34
+ - [Android] `SharedObjectTypeConverter` now can work with the `Dynamic` class. ([#24207](https://github.com/expo/expo/pull/24207) by [@lukmccall](https://github.com/lukmccall))
35
+ - [Android] Expose a conversion between id and shared objects. ([#24220](https://github.com/expo/expo/pull/24220) by [@lukmccall](https://github.com/lukmccall))
36
+
13
37
  ## 1.6.0 — 2023-07-28
14
38
 
15
39
  ### 🐛 Bug fixes
@@ -6,7 +6,7 @@ apply plugin: 'maven-publish'
6
6
  apply plugin: "de.undercouch.download"
7
7
 
8
8
  group = 'host.exp.exponent'
9
- version = '1.6.0'
9
+ version = '1.7.0'
10
10
 
11
11
  buildscript {
12
12
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -64,7 +64,8 @@ def REACT_NATIVE_SO_DIR = REACT_NATIVE_BUILD_FROM_SOURCE
64
64
  def reactProperties = new Properties()
65
65
  file("$REACT_NATIVE_DIR/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) }
66
66
 
67
- def BOOST_VERSION = reactProperties.getProperty("BOOST_VERSION")
67
+ // TODO: Remove react-native < 0.71 support
68
+ def BOOST_VERSION = reactProperties.getProperty("BOOST_VERSION") ?: "1_76_0"
68
69
  def REACT_NATIVE_VERSION = System.getenv("REACT_NATIVE_OVERRIDE_VERSION") ?: reactProperties.getProperty("VERSION_NAME")
69
70
  def REACT_NATIVE_TARGET_VERSION = REACT_NATIVE_VERSION.split("\\.")[1].toInteger()
70
71
 
@@ -113,13 +114,16 @@ android {
113
114
  ndkVersion rootProject.ext.ndkVersion
114
115
  }
115
116
 
116
- compileOptions {
117
- sourceCompatibility JavaVersion.VERSION_11
118
- targetCompatibility JavaVersion.VERSION_11
119
- }
117
+ def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
118
+ if (agpVersion.tokenize('.')[0].toInteger() < 8) {
119
+ compileOptions {
120
+ sourceCompatibility JavaVersion.VERSION_11
121
+ targetCompatibility JavaVersion.VERSION_11
122
+ }
120
123
 
121
- kotlinOptions {
122
- jvmTarget = JavaVersion.VERSION_11.majorVersion
124
+ kotlinOptions {
125
+ jvmTarget = JavaVersion.VERSION_11.majorVersion
126
+ }
123
127
  }
124
128
 
125
129
  namespace "expo.modules"
@@ -128,7 +132,7 @@ android {
128
132
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
129
133
  consumerProguardFiles 'proguard-rules.pro'
130
134
  versionCode 1
131
- versionName "1.6.0"
135
+ versionName "1.7.0"
132
136
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
133
137
 
134
138
  testInstrumentationRunner "expo.modules.TestRunner"
@@ -161,7 +165,20 @@ android {
161
165
  }
162
166
  }
163
167
 
168
+ sourceSets {
169
+ main {
170
+ java {
171
+ if (REACT_NATIVE_TARGET_VERSION >= 73) {
172
+ srcDirs += "src/reactnative"
173
+ } else {
174
+ srcDirs += "src/reactnative72"
175
+ }
176
+ }
177
+ }
178
+ }
179
+
164
180
  buildFeatures {
181
+ buildConfig true
165
182
  prefab true
166
183
  }
167
184
 
@@ -277,16 +294,6 @@ dependencies {
277
294
  }
278
295
  }
279
296
 
280
- /**
281
- * To make the users of annotations @OptIn and @RequiresOptIn aware of their experimental status,
282
- * the compiler raises warnings when compiling the code with these annotations:
283
- * This class can only be used with the compiler argument '-Xopt-in=kotlin.RequiresOptIn'
284
- * To remove the warnings, we add the compiler argument -Xopt-in=kotlin.RequiresOptIn.
285
- */
286
- tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
287
- kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
288
- }
289
-
290
297
  def createNativeDepsDirectories = project.tasks.findByName('createNativeDepsDirectories') ?: project.tasks.register('createNativeDepsDirectories') {
291
298
  downloadsDir.mkdirs()
292
299
  thirdPartyNdkDir.mkdirs()
@@ -14,6 +14,23 @@ namespace jni = facebook::jni;
14
14
  namespace jsi = facebook::jsi;
15
15
 
16
16
  namespace expo {
17
+
18
+ namespace {
19
+
20
+ #if REACT_NATIVE_TARGET_VERSION >= 73
21
+ std::shared_ptr<NativeMethodCallInvokerCompatible> getNativeMethodCallInvokerHolderCompatible(
22
+ jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> holder) {
23
+ return holder->cthis()->getNativeMethodCallInvoker();
24
+ }
25
+ #else
26
+ std::shared_ptr<NativeMethodCallInvokerCompatible> getNativeMethodCallInvokerHolderCompatible(
27
+ jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> holder) {
28
+ return holder->cthis()->getCallInvoker();
29
+ }
30
+ #endif
31
+
32
+ } // namespace
33
+
17
34
  jni::local_ref<JSIInteropModuleRegistry::jhybriddata>
18
35
  JSIInteropModuleRegistry::initHybrid(jni::alias_ref<jhybridobject> jThis) {
19
36
  return makeCxxInstance(jThis);
@@ -39,7 +56,7 @@ void JSIInteropModuleRegistry::installJSI(
39
56
  jlong jsRuntimePointer,
40
57
  jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator,
41
58
  jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
42
- jni::alias_ref<react::CallInvokerHolder::javaobject> nativeInvokerHolder
59
+ jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> nativeInvokerHolder
43
60
  ) {
44
61
  this->jniDeallocator = jni::make_global(jniDeallocator);
45
62
 
@@ -51,7 +68,7 @@ void JSIInteropModuleRegistry::installJSI(
51
68
  this,
52
69
  runtime,
53
70
  jsInvokerHolder->cthis()->getCallInvoker(),
54
- nativeInvokerHolder->cthis()->getCallInvoker()
71
+ getNativeMethodCallInvokerHolderCompatible(nativeInvokerHolder)
55
72
  );
56
73
 
57
74
  auto expoModules = std::make_shared<ExpoModulesHostObject>(this);
@@ -14,6 +14,9 @@
14
14
  #include <jsi/jsi.h>
15
15
  #include <ReactCommon/CallInvokerHolder.h>
16
16
  #include <ReactCommon/CallInvoker.h>
17
+ #if REACT_NATIVE_TARGET_VERSION >= 73
18
+ #include <ReactCommon/NativeMethodCallInvokerHolder.h>
19
+ #endif
17
20
 
18
21
  #include <memory>
19
22
 
@@ -22,6 +25,13 @@ namespace jsi = facebook::jsi;
22
25
  namespace react = facebook::react;
23
26
 
24
27
  namespace expo {
28
+
29
+ #if REACT_NATIVE_TARGET_VERSION >= 73
30
+ using NativeMethodCallInvokerHolderCompatible = react::NativeMethodCallInvokerHolder;
31
+ #else
32
+ using NativeMethodCallInvokerHolderCompatible = react::CallInvokerHolder;
33
+ #endif
34
+
25
35
  /**
26
36
  * A JNI wrapper to initialize CPP part of modules and access all data from the module registry.
27
37
  */
@@ -42,7 +52,7 @@ public:
42
52
  jlong jsRuntimePointer,
43
53
  jni::alias_ref<JNIDeallocator::javaobject> jniDeallocator,
44
54
  jni::alias_ref<react::CallInvokerHolder::javaobject> jsInvokerHolder,
45
- jni::alias_ref<react::CallInvokerHolder::javaobject> nativeInvokerHolder
55
+ jni::alias_ref<NativeMethodCallInvokerHolderCompatible::javaobject> nativeInvokerHolder
46
56
  );
47
57
 
48
58
  /**
@@ -2,7 +2,7 @@
2
2
 
3
3
  #include "JavaScriptModuleObject.h"
4
4
  #include "JSIInteropModuleRegistry.h"
5
- #include "ObjectDeallocator.h"
5
+ #include "JSIUtils.h"
6
6
 
7
7
  #include <folly/dynamic.h>
8
8
  #include <jsi/JSIDynamic.h>
@@ -61,7 +61,7 @@ void decorateObjectWithProperties(
61
61
  jsi::Value(runtime, *setter.toJSFunction(runtime,
62
62
  jsiInteropModuleRegistry))
63
63
  );
64
- JavaScriptObject::defineProperty(runtime, jsObject, name, std::move(descriptor));
64
+ common::definePropertyOnJSIObject(runtime, jsObject, name.c_str(), std::move(descriptor));
65
65
  }
66
66
  }
67
67
 
@@ -215,8 +215,8 @@ std::shared_ptr<jsi::Object> JavaScriptModuleObject::getJSIObject(jsi::Runtime &
215
215
  auto descriptor = JavaScriptObject::preparePropertyDescriptor(runtime, 0);
216
216
  descriptor.setProperty(runtime, "value", jsi::Value(runtime, nativeConstructor));
217
217
 
218
- JavaScriptObject::defineProperty(runtime, &prototype, nativeConstructorKey,
219
- std::move(descriptor));
218
+ common::definePropertyOnJSIObject(runtime, &prototype, nativeConstructorKey.c_str(),
219
+ std::move(descriptor));
220
220
 
221
221
  moduleObject->setProperty(
222
222
  runtime,
@@ -321,29 +321,30 @@ void JavaScriptModuleObject::registerViewPrototype(
321
321
 
322
322
  void JavaScriptModuleObject::registerProperty(
323
323
  jni::alias_ref<jstring> name,
324
- jni::alias_ref<ExpectedType> expectedArgType,
324
+ jboolean getterTakesOwner,
325
+ jni::alias_ref<jni::JArrayClass<ExpectedType>> getterExpectedArgsTypes,
325
326
  jni::alias_ref<JNIFunctionBody::javaobject> getter,
327
+ jboolean setterTakesOwner,
328
+ jni::alias_ref<jni::JArrayClass<ExpectedType>> setterExpectedArgsTypes,
326
329
  jni::alias_ref<JNIFunctionBody::javaobject> setter
327
330
  ) {
328
331
  auto cName = name->toStdString();
329
332
 
330
333
  auto getterMetadata = MethodMetadata(
331
334
  cName,
335
+ getterTakesOwner,
336
+ getterExpectedArgsTypes->size(),
332
337
  false,
333
- 0,
334
- false,
335
- std::vector<std::unique_ptr<AnyType>>(),
338
+ jni::make_local(getterExpectedArgsTypes),
336
339
  jni::make_global(getter)
337
340
  );
338
341
 
339
- auto types = std::vector<std::unique_ptr<AnyType>>();
340
- types.push_back(std::make_unique<AnyType>(jni::make_local(expectedArgType)));
341
342
  auto setterMetadata = MethodMetadata(
342
343
  cName,
344
+ setterTakesOwner,
345
+ setterExpectedArgsTypes->size(),
343
346
  false,
344
- 1,
345
- false,
346
- std::move(types),
347
+ jni::make_local(setterExpectedArgsTypes),
347
348
  jni::make_global(setter)
348
349
  );
349
350
 
@@ -122,8 +122,11 @@ public:
122
122
  */
123
123
  void registerProperty(
124
124
  jni::alias_ref<jstring> name,
125
- jni::alias_ref<ExpectedType> expectedArgType,
125
+ jboolean getterTakesOwner,
126
+ jni::alias_ref<jni::JArrayClass<ExpectedType>> getterExpectedArgsTypes,
126
127
  jni::alias_ref<JNIFunctionBody::javaobject> getter,
128
+ jboolean setterTakesOwner,
129
+ jni::alias_ref<jni::JArrayClass<ExpectedType>> setterExpectedArgsTypes,
127
130
  jni::alias_ref<JNIFunctionBody::javaobject> setter
128
131
  );
129
132
 
@@ -112,7 +112,11 @@ jni::local_ref<jni::JArrayClass<jstring>> JavaScriptObject::jniGetPropertyNames(
112
112
  jni::local_ref<JavaScriptFunction::javaobject> JavaScriptObject::jniAsFunction() {
113
113
  auto &jsRuntime = runtimeHolder.getJSRuntime();
114
114
  auto jsFuncion = std::make_shared<jsi::Function>(jsObject->asFunction(jsRuntime));
115
- return JavaScriptFunction::newInstance(runtimeHolder.getModuleRegistry(), runtimeHolder, jsFuncion);
115
+ return JavaScriptFunction::newInstance(
116
+ runtimeHolder.getModuleRegistry(),
117
+ runtimeHolder,
118
+ jsFuncion
119
+ );
116
120
  }
117
121
 
118
122
  void JavaScriptObject::setProperty(const std::string &name, jsi::Value value) {
@@ -143,27 +147,6 @@ jsi::Object JavaScriptObject::preparePropertyDescriptor(
143
147
  return descriptor;
144
148
  }
145
149
 
146
- void JavaScriptObject::defineProperty(
147
- jsi::Runtime &runtime,
148
- jsi::Object *jsthis,
149
- const std::string &name,
150
- jsi::Object descriptor
151
- ) {
152
- jsi::Object global = runtime.global();
153
- jsi::Object objectClass = global.getPropertyAsObject(runtime, "Object");
154
- jsi::Function definePropertyFunction = objectClass.getPropertyAsFunction(
155
- runtime,
156
- "defineProperty"
157
- );
158
-
159
- // This call is basically the same as `Object.defineProperty(object, name, descriptor)` in JS
160
- definePropertyFunction.callWithThis(runtime, objectClass, {
161
- jsi::Value(runtime, *jsthis),
162
- jsi::String::createFromUtf8(runtime, name),
163
- std::move(descriptor),
164
- });
165
- }
166
-
167
150
  jni::local_ref<JavaScriptObject::javaobject> JavaScriptObject::newInstance(
168
151
  JSIInteropModuleRegistry *jsiInteropModuleRegistry,
169
152
  std::weak_ptr<JavaScriptRuntime> runtime,
@@ -179,7 +162,10 @@ void JavaScriptObject::defineNativeDeallocator(
179
162
  ) {
180
163
  auto &rt = runtimeHolder.getJSRuntime();
181
164
  jni::global_ref<JNIFunctionBody::javaobject> globalRef = jni::make_global(deallocator);
182
- std::shared_ptr<ObjectDeallocator> nativeDeallocator = std::make_shared<ObjectDeallocator>(
165
+
166
+ common::setDeallocator(
167
+ rt,
168
+ jsObject,
183
169
  [globalRef = std::move(globalRef)]() mutable {
184
170
  auto args = jni::Environment::current()->NewObjectArray(
185
171
  0,
@@ -188,9 +174,8 @@ void JavaScriptObject::defineNativeDeallocator(
188
174
  );
189
175
  globalRef->invoke(args);
190
176
  globalRef.reset();
191
- });
192
- auto descriptor = JavaScriptObject::preparePropertyDescriptor(rt, 0);
193
- descriptor.setProperty(rt, "value", jsi::Object::createFromHostObject(rt, nativeDeallocator));
194
- jsObject->setProperty(rt, "__expo_shared_object_deallocator__", std::move(descriptor));
177
+ },
178
+ "__expo_shared_object_deallocator__"
179
+ );
195
180
  }
196
181
  } // namespace expo
@@ -8,6 +8,7 @@
8
8
  #include "WeakRuntimeHolder.h"
9
9
  #include "JNIFunctionBody.h"
10
10
  #include "JNIDeallocator.h"
11
+ #include "JSIUtils.h"
11
12
 
12
13
  #include <fbjni/fbjni.h>
13
14
  #include <jsi/jsi.h>
@@ -71,13 +72,6 @@ public:
71
72
 
72
73
  static jsi::Object preparePropertyDescriptor(jsi::Runtime &jsRuntime, int options);
73
74
 
74
- static void defineProperty(
75
- jsi::Runtime &runtime,
76
- jsi::Object *jsthis,
77
- const std::string &name,
78
- jsi::Object descriptor
79
- );
80
-
81
75
  void defineNativeDeallocator(
82
76
  jni::alias_ref<JNIFunctionBody::javaobject> deallocator
83
77
  );
@@ -139,7 +133,7 @@ private:
139
133
  auto cName = name->toStdString();
140
134
  jsi::Object descriptor = preparePropertyDescriptor(jsRuntime, options);
141
135
  descriptor.setProperty(jsRuntime, "value", jsi_type_converter<T>::convert(jsRuntime, value));
142
- JavaScriptObject::defineProperty(jsRuntime, jsObject.get(), cName, std::move(descriptor));
136
+ common::definePropertyOnJSIObject(jsRuntime, jsObject.get(), cName.c_str(), std::move(descriptor));
143
137
  }
144
138
  };
145
139
  } // namespace expo
@@ -5,6 +5,7 @@
5
5
  #include "JavaScriptObject.h"
6
6
  #include "Exceptions.h"
7
7
  #include "JSIInteropModuleRegistry.h"
8
+ #include "JSIUtils.h"
8
9
 
9
10
  #if UNIT_TEST
10
11
 
@@ -30,19 +31,49 @@ namespace jsi = facebook::jsi;
30
31
 
31
32
  namespace expo {
32
33
 
33
- void SyncCallInvoker::invokeAsync(std::function<void()> &&func) {
34
- func();
35
- }
34
+ namespace {
36
35
 
37
- void SyncCallInvoker::invokeSync(std::function<void()> &&func) {
38
- func();
39
- }
36
+ /**
37
+ * Dummy CallInvoker that invokes everything immediately.
38
+ * Used in the test environment to check the async flow.
39
+ */
40
+ class SyncCallInvoker : public react::CallInvoker {
41
+ public:
42
+ void invokeAsync(std::function<void()> &&func) override {
43
+ func();
44
+ }
45
+
46
+ void invokeSync(std::function<void()> &&func) override {
47
+ func();
48
+ }
49
+
50
+ ~SyncCallInvoker() override = default;
51
+ };
52
+
53
+ #if REACT_NATIVE_TARGET_VERSION >= 73
54
+ class SyncNativeMethodCallInvoker : public react::NativeMethodCallInvoker {
55
+ public:
56
+ void invokeAsync(const std::string &methodName, std::function<void()> &&func) override {
57
+ func();
58
+ }
59
+
60
+ void invokeSync(const std::string &methodName, std::function<void()> &&func) override {
61
+ func();
62
+ }
63
+
64
+ ~SyncNativeMethodCallInvoker() override = default;
65
+ };
66
+ #else
67
+ using SyncNativeMethodCallInvoker = SyncCallInvoker;
68
+ #endif // REACT_NATIVE_TARGET_VERSION >= 73
69
+
70
+ } // namespace
40
71
 
41
72
  JavaScriptRuntime::JavaScriptRuntime(
42
73
  JSIInteropModuleRegistry *jsiInteropModuleRegistry
43
74
  )
44
75
  : jsInvoker(std::make_shared<SyncCallInvoker>()),
45
- nativeInvoker(std::make_shared<SyncCallInvoker>()),
76
+ nativeInvoker(std::make_shared<SyncNativeMethodCallInvoker>()),
46
77
  jsiInteropModuleRegistry(jsiInteropModuleRegistry) {
47
78
  #if !UNIT_TEST
48
79
  throw std::logic_error(
@@ -107,7 +138,7 @@ JavaScriptRuntime::JavaScriptRuntime(
107
138
  JSIInteropModuleRegistry *jsiInteropModuleRegistry,
108
139
  jsi::Runtime *runtime,
109
140
  std::shared_ptr<react::CallInvoker> jsInvoker,
110
- std::shared_ptr<react::CallInvoker> nativeInvoker
141
+ std::shared_ptr<NativeMethodCallInvokerCompatible> nativeInvoker
111
142
  ) : jsInvoker(std::move(jsInvoker)), nativeInvoker(std::move(nativeInvoker)),
112
143
  jsiInteropModuleRegistry(jsiInteropModuleRegistry) {
113
144
  // Creating a shared pointer that points to the runtime but doesn't own it, thus doesn't release it.
@@ -167,21 +198,17 @@ void JavaScriptRuntime::installMainObject() {
167
198
  mainObject = coreModule->cthis()->getJSIObject(*runtime);
168
199
 
169
200
  auto global = runtime->global();
170
- auto objectClass = global.getPropertyAsObject(*runtime, "Object");
171
- jsi::Function definePropertyFunction = objectClass.getPropertyAsFunction(
172
- *runtime,
173
- "defineProperty"
174
- );
175
201
 
176
202
  jsi::Object descriptor = JavaScriptObject::preparePropertyDescriptor(*runtime, 1 << 1);
177
203
 
178
204
  descriptor.setProperty(*runtime, "value", jsi::Value(*runtime, *mainObject));
179
205
 
180
- definePropertyFunction.callWithThis(*runtime, objectClass, {
181
- jsi::Value(*runtime, global),
182
- jsi::String::createFromUtf8(*runtime, "expo"),
206
+ common::definePropertyOnJSIObject(
207
+ *runtime,
208
+ &global,
209
+ "expo",
183
210
  std::move(descriptor)
184
- });
211
+ );
185
212
  }
186
213
 
187
214
  std::shared_ptr<jsi::Object> JavaScriptRuntime::getMainObject() {
@@ -13,24 +13,16 @@ namespace jni = facebook::jni;
13
13
  namespace react = facebook::react;
14
14
 
15
15
  namespace expo {
16
- class JavaScriptValue;
17
16
 
17
+ class JavaScriptValue;
18
18
  class JavaScriptObject;
19
-
20
19
  class JSIInteropModuleRegistry;
21
20
 
22
- /**
23
- * Dummy CallInvoker that invokes everything immediately.
24
- * Used in the test environment to check the async flow.
25
- */
26
- class SyncCallInvoker : public react::CallInvoker {
27
- public:
28
- void invokeAsync(std::function<void()> &&func) override;
29
-
30
- void invokeSync(std::function<void()> &&func) override;
31
-
32
- ~SyncCallInvoker() override = default;
33
- };
21
+ #if REACT_NATIVE_TARGET_VERSION >= 73
22
+ using NativeMethodCallInvokerCompatible = react::NativeMethodCallInvoker;
23
+ #else
24
+ using NativeMethodCallInvokerCompatible = react::CallInvoker;
25
+ #endif
34
26
 
35
27
  /**
36
28
  * A wrapper for the jsi::Runtime.
@@ -45,6 +37,7 @@ public:
45
37
  /**
46
38
  * Initializes a runtime that is independent from React Native and its runtime initialization.
47
39
  * This flow is mostly intended for tests. The JS call invoker is set to `SyncCallInvoker`.
40
+ * See **JavaScriptRuntime.cpp** for the `SyncCallInvoker` implementation.
48
41
  */
49
42
  JavaScriptRuntime(
50
43
  JSIInteropModuleRegistry *jsiInteropModuleRegistry
@@ -54,7 +47,7 @@ public:
54
47
  JSIInteropModuleRegistry *jsiInteropModuleRegistry,
55
48
  jsi::Runtime *runtime,
56
49
  std::shared_ptr<react::CallInvoker> jsInvoker,
57
- std::shared_ptr<react::CallInvoker> nativeInvoker
50
+ std::shared_ptr<NativeMethodCallInvokerCompatible> nativeInvoker
58
51
  );
59
52
 
60
53
  /**
@@ -87,7 +80,7 @@ public:
87
80
  void drainJSEventLoop();
88
81
 
89
82
  std::shared_ptr<react::CallInvoker> jsInvoker;
90
- std::shared_ptr<react::CallInvoker> nativeInvoker;
83
+ std::shared_ptr<NativeMethodCallInvokerCompatible> nativeInvoker;
91
84
 
92
85
  std::shared_ptr<jsi::Object> getMainObject();
93
86
 
@@ -134,7 +134,6 @@ jobjectArray MethodMetadata::convertJSIArgsToJNI(
134
134
  nullptr
135
135
  );
136
136
 
137
- std::vector<jobject> result(count);
138
137
 
139
138
  const auto getCurrentArg = [&thisValue, args, takesOwner = takesOwner](
140
139
  size_t index
@@ -155,19 +154,19 @@ jobjectArray MethodMetadata::convertJSIArgsToJNI(
155
154
  if (arg.isNull() || arg.isUndefined()) {
156
155
  // If value is null or undefined, we just passes a null
157
156
  // Kotlin code will check if expected type is nullable.
158
- result[argIndex] = nullptr;
157
+ continue;
158
+ }
159
+
160
+ if (type->converter->canConvert(rt, arg)) {
161
+ auto converterValue = type->converter->convert(rt, env, moduleRegistry, arg);
162
+ env->SetObjectArrayElement(argumentArray, argIndex, converterValue);
163
+ env->DeleteLocalRef(converterValue);
159
164
  } else {
160
- if (type->converter->canConvert(rt, arg)) {
161
- auto converterValue = type->converter->convert(rt, env, moduleRegistry, arg);
162
- env->SetObjectArrayElement(argumentArray, argIndex, converterValue);
163
- env->DeleteLocalRef(converterValue);
164
- } else {
165
- auto stringRepresentation = arg.toString(rt).utf8(rt);
166
- throwNewJavaException(
167
- UnexpectedException::create(
168
- "Cannot convert '" + stringRepresentation + "' to a Kotlin type.").get()
169
- );
170
- }
165
+ auto stringRepresentation = arg.toString(rt).utf8(rt);
166
+ throwNewJavaException(
167
+ UnexpectedException::create(
168
+ "Cannot convert '" + stringRepresentation + "' to a Kotlin type.").get()
169
+ );
171
170
  }
172
171
  }
173
172
 
@@ -398,8 +398,16 @@ jobject ListFrontendConverter::convert(
398
398
 
399
399
  auto arrayList = java::ArrayList<jobject>::create(size);
400
400
  for (size_t i = 0; i < size; i++) {
401
+ auto jsValue = jsArray.getValueAtIndex(rt, i);
402
+
403
+ // TODO(@lukmccall): pass information to CPP if the underlying type is nullable or not.
404
+ if (jsValue.isNull() || jsValue.isUndefined()) {
405
+ arrayList->add(nullptr);
406
+ continue;
407
+ }
408
+
401
409
  auto convertedElement = parameterConverter->convert(
402
- rt, env, moduleRegistry, jsArray.getValueAtIndex(rt, i)
410
+ rt, env, moduleRegistry, jsValue
403
411
  );
404
412
  arrayList->add(convertedElement);
405
413
  env->DeleteLocalRef(convertedElement);
@@ -433,11 +441,20 @@ jobject MapFrontendConverter::convert(
433
441
 
434
442
  for (size_t i = 0; i < size; i++) {
435
443
  auto key = propertyNames.getValueAtIndex(rt, i).getString(rt);
444
+ auto jsValue = jsObject.getProperty(rt, key);
445
+
446
+ auto convertedKey = env->NewStringUTF(key.utf8(rt).c_str());
447
+
448
+ // TODO(@lukmccall): pass information to CPP if the underlying type is nullable or not.
449
+ if (jsValue.isNull() || jsValue.isUndefined()) {
450
+ map->put(convertedKey, nullptr);
451
+ continue;
452
+ }
453
+
436
454
  auto convertedValue = valueConverter->convert(
437
- rt, env, moduleRegistry, jsObject.getProperty(rt, key)
455
+ rt, env, moduleRegistry, jsValue
438
456
  );
439
457
 
440
- auto convertedKey = env->NewStringUTF(key.utf8(rt).c_str());
441
458
  map->put(convertedKey, convertedValue);
442
459
 
443
460
  env->DeleteLocalRef(convertedKey);
@@ -2,7 +2,7 @@
2
2
 
3
3
  #include "JNIToJSIConverter.h"
4
4
  #include "../JavaReferencesCache.h"
5
- #include "../ObjectDeallocator.h"
5
+ #include "ObjectDeallocator.h"
6
6
 
7
7
  #include <react/jni/ReadableNativeMap.h>
8
8
  #include <react/jni/ReadableNativeArray.h>
@@ -70,15 +70,14 @@ jsi::Value convert(
70
70
  auto jsiObject = anonymousObject->getJSIObject(rt);
71
71
 
72
72
  jni::global_ref<jobject> globalRef = jni::make_global(value);
73
- std::shared_ptr<expo::ObjectDeallocator> deallocator = std::make_shared<ObjectDeallocator>(
73
+
74
+ common::setDeallocator(
75
+ rt,
76
+ jsiObject,
74
77
  [globalRef = std::move(globalRef)]() mutable {
75
78
  globalRef.reset();
76
- });
77
-
78
- auto descriptor = JavaScriptObject::preparePropertyDescriptor(rt, 0);
79
- descriptor.setProperty(rt, "value", jsi::Object::createFromHostObject(rt, deallocator));
80
- JavaScriptObject::defineProperty(rt, jsiObject.get(), "__expo_object_deallocator__",
81
- std::move(descriptor));
79
+ }
80
+ );
82
81
 
83
82
  return jsi::Value(rt, *jsiObject);
84
83
  }