react-native-nitro-modules 0.21.0 → 0.22.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 (65) hide show
  1. package/NitroModules.podspec +4 -1
  2. package/README.md +1 -1
  3. package/android/CMakeLists.txt +1 -0
  4. package/android/build.gradle +4 -2
  5. package/android/gradle.properties +2 -2
  6. package/android/src/main/cpp/platform/ThreadUtils.cpp +4 -4
  7. package/android/src/main/cpp/registry/JHybridObjectRegistry.hpp +2 -0
  8. package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +10 -9
  9. package/android/src/main/java/com/margelo/nitro/core/HybridObjectInitializer.java +4 -0
  10. package/android/src/main/java/com/margelo/nitro/core/HybridObjectRegistry.java +2 -0
  11. package/android/src/main/java/com/margelo/nitro/views/HybridView.kt +23 -0
  12. package/cpp/core/HybridFunction.hpp +1 -1
  13. package/cpp/core/HybridObject.cpp +7 -6
  14. package/cpp/core/HybridObject.hpp +2 -2
  15. package/cpp/core/Promise.hpp +1 -1
  16. package/cpp/entrypoint/HybridNitroModulesProxy.cpp +8 -0
  17. package/cpp/entrypoint/HybridNitroModulesProxy.hpp +1 -0
  18. package/cpp/jsi/JSICache.cpp +1 -0
  19. package/cpp/jsi/JSICache.hpp +6 -0
  20. package/cpp/jsi/JSIConverter+Exception.hpp +1 -1
  21. package/cpp/jsi/JSIConverter+HostObject.hpp +1 -1
  22. package/cpp/jsi/JSIConverter+HybridObject.hpp +1 -1
  23. package/cpp/jsi/JSIConverter+Tuple.hpp +1 -1
  24. package/cpp/jsi/JSIConverter+Variant.hpp +1 -1
  25. package/cpp/jsi/JSIHelpers.hpp +1 -1
  26. package/cpp/prototype/HybridObjectPrototype.cpp +1 -1
  27. package/cpp/registry/HybridObjectRegistry.cpp +25 -12
  28. package/cpp/registry/HybridObjectRegistry.hpp +1 -0
  29. package/cpp/utils/AssertPromiseState.hpp +1 -1
  30. package/cpp/utils/BorrowingReference.hpp +4 -2
  31. package/cpp/utils/NitroDefines.hpp +13 -1
  32. package/cpp/utils/NitroHash.hpp +17 -0
  33. package/cpp/utils/{TypeInfo.hpp → NitroTypeInfo.hpp} +1 -1
  34. package/cpp/utils/OwningReference.hpp +15 -2
  35. package/cpp/views/CachedProp.hpp +43 -0
  36. package/ios/core/HybridContext.hpp +1 -1
  37. package/ios/core/{HybridObjectSpec.swift → HybridObject.swift} +10 -2
  38. package/ios/utils/RuntimeError.hpp +1 -1
  39. package/ios/views/HybridView.swift +41 -0
  40. package/lib/commonjs/index.js +11 -0
  41. package/lib/commonjs/index.js.map +1 -1
  42. package/lib/commonjs/views/HybridView.js +17 -0
  43. package/lib/commonjs/views/HybridView.js.map +1 -0
  44. package/lib/commonjs/views/getHostComponent.js +22 -0
  45. package/lib/commonjs/views/getHostComponent.js.map +1 -0
  46. package/lib/module/index.js +1 -0
  47. package/lib/module/index.js.map +1 -1
  48. package/lib/module/views/HybridView.js +30 -0
  49. package/lib/module/views/HybridView.js.map +1 -0
  50. package/lib/module/views/getHostComponent.js +15 -0
  51. package/lib/module/views/getHostComponent.js.map +1 -0
  52. package/lib/tsconfig.build.tsbuildinfo +1 -1
  53. package/lib/typescript/NitroModulesProxy.d.ts +7 -0
  54. package/lib/typescript/NitroModulesProxy.d.ts.map +1 -1
  55. package/lib/typescript/index.d.ts +1 -0
  56. package/lib/typescript/index.d.ts.map +1 -1
  57. package/lib/typescript/views/HybridView.d.ts +35 -0
  58. package/lib/typescript/views/HybridView.d.ts.map +1 -0
  59. package/lib/typescript/views/getHostComponent.d.ts +13 -0
  60. package/lib/typescript/views/getHostComponent.d.ts.map +1 -0
  61. package/package.json +3 -2
  62. package/src/NitroModulesProxy.ts +8 -0
  63. package/src/index.ts +1 -0
  64. package/src/views/HybridView.ts +37 -0
  65. package/src/views/getHostComponent.ts +26 -0
@@ -43,6 +43,7 @@ Pod::Spec.new do |s|
43
43
  "cpp/threading/Dispatcher.hpp",
44
44
  "cpp/utils/NitroHash.hpp",
45
45
  "cpp/utils/NitroDefines.hpp",
46
+ "cpp/views/CachedProp.hpp",
46
47
  # Public iOS-specific headers that will be exposed in modulemap (for Swift)
47
48
  "ios/core/ArrayBufferHolder.hpp",
48
49
  "ios/core/AnyMapHolder.hpp",
@@ -60,11 +61,13 @@ Pod::Spec.new do |s|
60
61
  "SWIFT_OBJC_INTEROP_MODE" => "objcxx",
61
62
  # Enables stricter modular headers
62
63
  "DEFINES_MODULE" => "YES",
63
- # C++ compiler flags, mainly for folly.
64
+ # C++ compiler flags, mainly for RN version and folly.
64
65
  "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
65
66
  }
66
67
 
68
+ # Nitro depends on JSI.
67
69
  s.dependency 'React-jsi'
70
+ # For React Native, we implement nitro::Dispatcher using react::CallInvoker
68
71
  s.dependency 'React-callinvoker'
69
72
  install_modules_dependencies(s)
70
73
  end
package/README.md CHANGED
@@ -208,7 +208,7 @@ The following C++ / JS types are supported out of the box:
208
208
  <tr>
209
209
  <td>..any <code><a href="./src/HybridObject.ts">HybridObject</a></code></td>
210
210
  <td><code>std::shared_ptr&lt;<a href="./cpp/core/HybridObject.hpp">HybridObject</a>&gt;</code></td>
211
- <td><code><a href="./ios/core/HybridObjectSpec.swift">HybridObjectSpec</a></code></td>
211
+ <td><code><a href="./ios/core/HybridObject.swift">HybridObject</a></code></td>
212
212
  <td><code><a href="./android/src/main/java/com/margelo/nitro/core/HybridObject.kt">HybridObject</a></code></td>
213
213
  </tr>
214
214
  <tr>
@@ -32,6 +32,7 @@ include_directories(
32
32
  ../cpp/threading
33
33
  ../cpp/turbomodule
34
34
  ../cpp/utils
35
+ ../cpp/views
35
36
  # Android-specific C++ includes
36
37
  src/main/cpp/core
37
38
  src/main/cpp/registry
@@ -1,3 +1,5 @@
1
+ import groovy.json.JsonSlurper
2
+
1
3
  buildscript {
2
4
  repositories {
3
5
  google()
@@ -5,7 +7,7 @@ buildscript {
5
7
  }
6
8
 
7
9
  dependencies {
8
- classpath "com.android.tools.build:gradle:8.7.3"
10
+ classpath "com.android.tools.build:gradle:8.8.0"
9
11
  }
10
12
  }
11
13
 
@@ -154,7 +156,7 @@ if (isNewArchitectureEnabled()) {
154
156
  }
155
157
  }
156
158
 
157
- task prepareHeaders(type: Copy) {
159
+ tasks.register('prepareHeaders', Copy) {
158
160
  from fileTree('./src/main/cpp').filter { it.isFile() }
159
161
  from fileTree('../cpp/').filter { it.isFile() }
160
162
  include "*.hpp"
@@ -1,5 +1,5 @@
1
- Nitro_kotlinVersion=1.9.24
1
+ Nitro_kotlinVersion=2.0.21
2
2
  Nitro_minSdkVersion=23
3
3
  Nitro_targetSdkVersion=34
4
4
  Nitro_compileSdkVersion=34
5
- Nitro_ndkVersion=26.1.10909125
5
+ Nitro_ndkVersion=27.1.12297006
@@ -17,12 +17,12 @@ namespace margelo::nitro {
17
17
  std::string ThreadUtils::getThreadName() {
18
18
  #ifdef HAVE_ANDROID_PTHREAD_SETNAME_NP
19
19
  // Try using pthread APIs
20
- pthread_t this_thread = pthread_self();
21
- char thread_name[16]; // Thread name length limit in Android is 16 characters
20
+ pthread_t thisThread = pthread_self();
21
+ char threadName[16]; // Thread name length limit in Android is 16 characters
22
22
 
23
- int result = pthread_getname_np(this_thread, thread_name, sizeof(thread_name));
23
+ int result = pthread_getname_np(thisThread, threadName, sizeof(threadName));
24
24
  if (result == 0) {
25
- return std::string(thread_name);
25
+ return std::string(threadName);
26
26
  }
27
27
  #endif
28
28
 
@@ -20,6 +20,8 @@ public:
20
20
  static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/HybridObjectRegistry;";
21
21
 
22
22
  public:
23
+ [[deprecated("HybridObjects should be registered from C++ instead. Either autolink them using `nitro.json`, "
24
+ "or add them manually in the C++ HybridObjectRegistry.")]]
23
25
  static void registerHybridObjectConstructor(jni::alias_ref<jni::JClass> clazz, std::string hybridObjectName,
24
26
  jni::alias_ref<JHybridObjectInitializer> constructorFn);
25
27
 
@@ -4,16 +4,12 @@ import androidx.annotation.Keep
4
4
  import com.facebook.jni.HybridData
5
5
  import com.facebook.proguard.annotations.DoNotStrip
6
6
 
7
- interface ExtendableHybridClass {
8
- fun updateNative(hybridData: HybridData)
9
- }
10
-
11
7
  /**
12
8
  * A base class for all Kotlin-based HybridObjects.
13
9
  */
14
10
  @Keep
15
11
  @DoNotStrip
16
- abstract class HybridObject: ExtendableHybridClass {
12
+ abstract class HybridObject {
17
13
  /**
18
14
  * Get the memory size of the Kotlin instance (plus any external heap allocations),
19
15
  * in bytes.
@@ -32,7 +28,8 @@ abstract class HybridObject: ExtendableHybridClass {
32
28
  */
33
29
  @get:DoNotStrip
34
30
  @get:Keep
35
- abstract val memorySize: Long
31
+ open val memorySize: Long
32
+ get() = 0L
36
33
 
37
34
  /**
38
35
  * Holds the native C++ instance.
@@ -42,10 +39,14 @@ abstract class HybridObject: ExtendableHybridClass {
42
39
  private var mHybridData: HybridData? = null
43
40
 
44
41
  /**
45
- * Must be called in the constructor of a subclass of `HybridObject`, to initialize the C++
46
- * `JHybridObject` with a subclass of it.
42
+ * If `HybridObject` is subclassed, the sub-class needs to create it's own `HybridData`
43
+ * with a C++ `jni::HybridClass` representing the subclass directly.
44
+ * Then, that `HybridData` must be passed upwards to `HybridObject` using `updateNative(..)`.
45
+ *
46
+ * This must happen for each sub/base class in the whole inheritance chain to ensure
47
+ * overrides and type-erasure works as expected.
47
48
  */
48
- override fun updateNative(hybridData: HybridData) {
49
+ protected open fun updateNative(hybridData: HybridData) {
49
50
  mHybridData = hybridData
50
51
  }
51
52
  }
@@ -4,8 +4,12 @@ import androidx.annotation.Keep;
4
4
 
5
5
  import com.facebook.proguard.annotations.DoNotStrip;
6
6
 
7
+ /**
8
+ * @deprecated HybridObjects should be registered from C++ instead. Either autolink them using `nitro.json`, or add them manually in the C++ `HybridObjectRegistry`.
9
+ */
7
10
  @Keep
8
11
  @DoNotStrip
12
+ @Deprecated(forRemoval = true)
9
13
  public interface HybridObjectInitializer {
10
14
  @Keep
11
15
  @DoNotStrip
@@ -20,6 +20,8 @@ public class HybridObjectRegistry {
20
20
  * Registers the given HybridObject in the `HybridObjectRegistry`.
21
21
  * It will be uniquely identified via it's `hybridObjectName`, and can be initialized from
22
22
  * JS using `NitroModules.createHybridObject<T>(name)` - which will call the `constructorFn` here.
23
+ * @deprecated HybridObjects should be registered from C++ instead. Either autolink them using `nitro.json`, or add them manually in the C++ `HybridObjectRegistry`.
23
24
  */
25
+ @Deprecated(forRemoval = true)
24
26
  public static native void registerHybridObjectConstructor(String hybridObjectName, HybridObjectInitializer initializer);
25
27
  }
@@ -0,0 +1,23 @@
1
+ package com.margelo.nitro.views
2
+
3
+ import android.view.View
4
+ import androidx.annotation.Keep
5
+ import com.facebook.jni.HybridData
6
+ import com.facebook.proguard.annotations.DoNotStrip
7
+ import com.margelo.nitro.core.HybridObject
8
+
9
+ /**
10
+ * A base class for all Kotlin-based Hybrid Views.
11
+ */
12
+ @Keep
13
+ @DoNotStrip
14
+ abstract class HybridView: HybridObject() {
15
+ /**
16
+ * Get the `UIView` this HybridView is holding.
17
+ *
18
+ * This value should not change during the lifetime of this `HybridView`.
19
+ */
20
+ @get:DoNotStrip
21
+ @get:Keep
22
+ abstract val view: View
23
+ }
@@ -15,7 +15,7 @@ struct JSIConverter;
15
15
  #include "CountTrailingOptionals.hpp"
16
16
  #include "JSIConverter.hpp"
17
17
  #include "NitroDefines.hpp"
18
- #include "TypeInfo.hpp"
18
+ #include "NitroTypeInfo.hpp"
19
19
  #include <exception>
20
20
  #include <functional>
21
21
  #include <jsi/jsi.h>
@@ -9,7 +9,6 @@
9
9
  namespace margelo::nitro {
10
10
 
11
11
  HybridObject::HybridObject(const char* name) : HybridObjectPrototype(), _name(name) {}
12
- HybridObject::~HybridObject() {}
13
12
 
14
13
  std::string HybridObject::toString() {
15
14
  return "[HybridObject " + std::string(_name) + "]";
@@ -19,7 +18,7 @@ std::string HybridObject::getName() {
19
18
  return _name;
20
19
  }
21
20
 
22
- bool HybridObject::equals(std::shared_ptr<HybridObject> other) {
21
+ bool HybridObject::equals(const std::shared_ptr<HybridObject>& other) {
23
22
  return this == other.get();
24
23
  }
25
24
 
@@ -48,10 +47,12 @@ jsi::Value HybridObject::toObject(jsi::Runtime& runtime) {
48
47
  if (cachedObject != _objectCache.end()) {
49
48
  // 1.1. We have a WeakObject, try to see if it is still alive
50
49
  OwningLock<jsi::WeakObject> lock = cachedObject->second.lock();
51
- jsi::Value object = cachedObject->second->lock(runtime);
52
- if (!object.isUndefined()) {
53
- // 1.2. It is still alive - we can use it instead of creating a new one!
54
- return object;
50
+ jsi::Value value = cachedObject->second->lock(runtime);
51
+ if (!value.isUndefined()) {
52
+ // 1.2. It is still alive - we can use it instead of creating a new one! But first, let's update memory-size
53
+ value.getObject(runtime).setExternalMemoryPressure(runtime, getExternalMemorySize());
54
+ // 1.3. Return it now
55
+ return value;
55
56
  }
56
57
  }
57
58
 
@@ -34,7 +34,7 @@ public:
34
34
  * Called when no more references to the given `HybridObject` exist in both C++ and JS.
35
35
  * JS might keep references for longer, as it is a garbage collected language.
36
36
  */
37
- virtual ~HybridObject();
37
+ ~HybridObject() override = default;
38
38
  /**
39
39
  * HybridObjects cannot be copied.
40
40
  */
@@ -80,7 +80,7 @@ public:
80
80
  * While two `jsi::Object`s of the same `HybridObject` might not be equal when compared with `==`,
81
81
  * they might still be the same `HybridObject` - in this case `equals(other)` will return true.
82
82
  */
83
- bool equals(std::shared_ptr<HybridObject> other);
83
+ bool equals(const std::shared_ptr<HybridObject>& other);
84
84
  /**
85
85
  * Get a string representation of this `HybridObject` - useful for logging or debugging.
86
86
  */
@@ -6,8 +6,8 @@
6
6
 
7
7
  #include "AssertPromiseState.hpp"
8
8
  #include "NitroDefines.hpp"
9
+ #include "NitroTypeInfo.hpp"
9
10
  #include "ThreadPool.hpp"
10
- #include "TypeInfo.hpp"
11
11
  #include <exception>
12
12
  #include <future>
13
13
  #include <jsi/jsi.h>
@@ -7,6 +7,7 @@
7
7
 
8
8
  #include "HybridNitroModulesProxy.hpp"
9
9
  #include "HybridObjectRegistry.hpp"
10
+ #include "JSIConverter.hpp"
10
11
  #include "NitroDefines.hpp"
11
12
 
12
13
  namespace margelo::nitro {
@@ -20,6 +21,7 @@ void HybridNitroModulesProxy::loadHybridMethods() {
20
21
  prototype.registerHybridMethod("getAllHybridObjectNames", &HybridNitroModulesProxy::getAllHybridObjectNames);
21
22
 
22
23
  prototype.registerHybridMethod("box", &HybridNitroModulesProxy::box);
24
+ prototype.registerHybridMethod("updateMemorySize", &HybridNitroModulesProxy::updateMemorySize);
23
25
 
24
26
  prototype.registerRawHybridMethod("hasNativeState", 1, &HybridNitroModulesProxy::hasNativeState);
25
27
 
@@ -53,6 +55,12 @@ jsi::Value HybridNitroModulesProxy::hasNativeState(jsi::Runtime& runtime, const
53
55
  return args[0].getObject(runtime).hasNativeState(runtime);
54
56
  }
55
57
 
58
+ std::shared_ptr<HybridObject> HybridNitroModulesProxy::updateMemorySize(const std::shared_ptr<HybridObject>& hybridObject) {
59
+ // If a hybridObject goes from Native -> JS, it will update it's memory size internally (in `HybridObject::toObject(..)`).
60
+ // This is all that function does.
61
+ return hybridObject;
62
+ }
63
+
56
64
  // Build Info
57
65
  std::string HybridNitroModulesProxy::getBuildType() {
58
66
  #ifdef NITRO_DEBUG
@@ -37,6 +37,7 @@ public:
37
37
 
38
38
  // Helpers
39
39
  std::shared_ptr<BoxedHybridObject> box(const std::shared_ptr<HybridObject>& hybridObject);
40
+ std::shared_ptr<HybridObject> updateMemorySize(const std::shared_ptr<HybridObject>& hybridObject);
40
41
  jsi::Value hasNativeState(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* args, size_t size);
41
42
 
42
43
  // Build Info
@@ -28,6 +28,7 @@ JSICache::~JSICache() {
28
28
  Logger::log(LogLevel::Info, TAG, "Destroying JSICache...");
29
29
  std::unique_lock lock(_mutex);
30
30
 
31
+ destroyReferences(_valueCache);
31
32
  destroyReferences(_objectCache);
32
33
  destroyReferences(_functionCache);
33
34
  destroyReferences(_weakObjectCache);
@@ -59,6 +59,7 @@ private:
59
59
 
60
60
  private:
61
61
  std::mutex _mutex;
62
+ std::vector<BorrowingReference<jsi::Value>> _valueCache;
62
63
  std::vector<BorrowingReference<jsi::Object>> _objectCache;
63
64
  std::vector<BorrowingReference<jsi::Function>> _functionCache;
64
65
  std::vector<BorrowingReference<jsi::WeakObject>> _weakObjectCache;
@@ -82,6 +83,11 @@ public:
82
83
  }
83
84
 
84
85
  public:
86
+ OwningReference<jsi::Value> makeShared(jsi::Value&& value) {
87
+ OwningReference<jsi::Value> owning(new jsi::Value(std::move(value)));
88
+ _strongCache->_valueCache.push_back(owning.weak());
89
+ return owning;
90
+ }
85
91
  OwningReference<jsi::Object> makeShared(jsi::Object&& value) {
86
92
  OwningReference<jsi::Object> owning(new jsi::Object(std::move(value)));
87
93
  _strongCache->_objectCache.push_back(owning.weak());
@@ -12,7 +12,7 @@ struct JSIConverter;
12
12
 
13
13
  #include "JSIConverter.hpp"
14
14
 
15
- #include "TypeInfo.hpp"
15
+ #include "NitroTypeInfo.hpp"
16
16
  #include <exception>
17
17
  #include <jsi/jsi.h>
18
18
 
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include "IsSharedPtrTo.hpp"
8
8
  #include "NitroDefines.hpp"
9
- #include "TypeInfo.hpp"
9
+ #include "NitroTypeInfo.hpp"
10
10
  #include <jsi/jsi.h>
11
11
  #include <type_traits>
12
12
 
@@ -11,7 +11,7 @@ class HybridObject;
11
11
 
12
12
  #include "IsSharedPtrTo.hpp"
13
13
  #include "NitroDefines.hpp"
14
- #include "TypeInfo.hpp"
14
+ #include "NitroTypeInfo.hpp"
15
15
  #include <jsi/jsi.h>
16
16
  #include <type_traits>
17
17
 
@@ -12,7 +12,7 @@ struct JSIConverter;
12
12
 
13
13
  #include "JSIConverter.hpp"
14
14
 
15
- #include "TypeInfo.hpp"
15
+ #include "NitroTypeInfo.hpp"
16
16
  #include <jsi/jsi.h>
17
17
  #include <memory>
18
18
  #include <tuple>
@@ -18,7 +18,7 @@ struct JSIConverter;
18
18
  #include "JSIConverter.hpp"
19
19
 
20
20
  #include "AnyMap.hpp"
21
- #include "TypeInfo.hpp"
21
+ #include "NitroTypeInfo.hpp"
22
22
  #include <jsi/jsi.h>
23
23
  #include <memory>
24
24
  #include <variant>
@@ -46,7 +46,7 @@ static inline bool isPlainObject(jsi::Runtime& runtime, const jsi::Object& objec
46
46
  */
47
47
  static inline std::string getRuntimeId(jsi::Runtime& runtime) {
48
48
  std::string threadName = ThreadUtils::getThreadName();
49
- return runtime.description() + std::string(" (") + threadName + std::string(")");
49
+ return runtime.description() + " (" + threadName + ")";
50
50
  }
51
51
 
52
52
  } // namespace margelo::nitro
@@ -8,7 +8,7 @@
8
8
  #include "HybridObjectPrototype.hpp"
9
9
  #include "NitroDefines.hpp"
10
10
  #include "NitroLogger.hpp"
11
- #include "TypeInfo.hpp"
11
+ #include "NitroTypeInfo.hpp"
12
12
 
13
13
  namespace margelo::nitro {
14
14
 
@@ -8,6 +8,7 @@
8
8
  #include "HybridObjectRegistry.hpp"
9
9
  #include "NitroDefines.hpp"
10
10
  #include "NitroLogger.hpp"
11
+ #include <numeric>
11
12
 
12
13
  namespace margelo::nitro {
13
14
 
@@ -29,17 +30,25 @@ std::vector<std::string> HybridObjectRegistry::getAllHybridObjectNames() {
29
30
  return keys;
30
31
  }
31
32
 
33
+ std::string HybridObjectRegistry::getAllRegisteredHybridObjectNamesToString() {
34
+ std::vector<std::string> names = getAllHybridObjectNames();
35
+ return std::accumulate(std::next(names.begin()), names.end(), names[0], [](std::string a, std::string b) { return a + ", " + b; });
36
+ }
37
+
32
38
  void HybridObjectRegistry::registerHybridObjectConstructor(const std::string& hybridObjectName, HybridObjectConstructorFn&& constructorFn) {
33
39
  Logger::log(LogLevel::Info, TAG, "Registering HybridObject \"%s\"...", hybridObjectName.c_str());
34
40
  auto& map = HybridObjectRegistry::getRegistry();
35
41
  #ifdef NITRO_DEBUG
36
42
  if (map.contains(hybridObjectName)) [[unlikely]] {
43
+ auto allObjectNames = getAllRegisteredHybridObjectNamesToString();
37
44
  auto message =
38
- "HybridObject \"" + std::string(hybridObjectName) +
45
+ "HybridObject \"" + hybridObjectName +
39
46
  "\" has already been "
40
47
  "registered in the Nitro Modules HybridObjectRegistry! Suggestions:\n"
41
48
  "- If you just installed another library, maybe both libraries are using the same name?\n"
42
- "- If you just registered your own HybridObject, maybe you accidentally called `registerHybridObjectConstructor(...)` twice?";
49
+ "- If you just registered your own HybridObject, maybe you accidentally called `registerHybridObjectConstructor(...)` twice?\n"
50
+ "- All registered HybridObjects: [" +
51
+ allObjectNames + "]";
43
52
  throw std::runtime_error(message);
44
53
  }
45
54
  #endif
@@ -57,16 +66,20 @@ std::shared_ptr<HybridObject> HybridObjectRegistry::createHybridObject(const std
57
66
  auto& map = HybridObjectRegistry::getRegistry();
58
67
  auto fn = map.find(hybridObjectName);
59
68
  if (fn == map.end()) [[unlikely]] {
60
- auto message = "Cannot create an instance of HybridObject \"" + std::string(hybridObjectName) +
61
- "\" - It has not yet been registered in the Nitro Modules HybridObjectRegistry! Suggestions:\n"
62
- "- If you use Nitrogen, make sure your `nitro.json` contains `" +
63
- std::string(hybridObjectName) +
64
- "` on this platform.\n"
65
- "- If you use Nitrogen, make sure your library (*Package.java)/app (MainApplication.java) calls "
66
- "`System.loadLibrary(\"$$androidCxxLibName$$\")` somewhere on app-startup.\n"
67
- "- If you use Nitrogen, make sure your cpp-adapter.cpp calls `margelo::nitro::$$cxxNamespace$$::initialize(vm)`.\n"
68
- "- If you use Nitrogen, inspect the generated `$$androidCxxLibName$$OnLoad.cpp` file.\n"
69
- "- If you don't use Nitrogen, make sure you called `HybridObjectRegistry.registerHybridObject(...)`.";
69
+ auto allObjectNames = getAllRegisteredHybridObjectNamesToString();
70
+ auto message =
71
+ "Cannot create an instance of HybridObject \"" + hybridObjectName +
72
+ "\" - It has not yet been registered in the Nitro Modules HybridObjectRegistry! Suggestions:\n"
73
+ "- If you use Nitrogen, make sure your `nitro.json` contains `" +
74
+ hybridObjectName +
75
+ "` on this platform.\n"
76
+ "- If you use Nitrogen, make sure your library (*Package.java)/app (MainApplication.java) calls "
77
+ "`$$androidCxxLibName$$OnLoad.initializeNative()` somewhere on app-startup.\n"
78
+ "- If you use Nitrogen, make sure your `cpp-adapter.cpp`/`OnLoad.cpp` calls `margelo::nitro::$$cxxNamespace$$::initialize(vm)`.\n"
79
+ "- If you use Nitrogen, inspect the generated `$$androidCxxLibName$$OnLoad.cpp` file.\n"
80
+ "- If you don't use Nitrogen, make sure you called `HybridObjectRegistry.registerHybridObject(...)`."
81
+ "- All registered HybridObjects: [" +
82
+ allObjectNames + "]";
70
83
  throw std::runtime_error(message);
71
84
  }
72
85
  std::shared_ptr<HybridObject> instance = fn->second();
@@ -44,6 +44,7 @@ public:
44
44
 
45
45
  private:
46
46
  static std::unordered_map<std::string, HybridObjectConstructorFn>& getRegistry();
47
+ static std::string getAllRegisteredHybridObjectNamesToString();
47
48
 
48
49
  private:
49
50
  static constexpr auto TAG = "HybridObjectRegistry";
@@ -12,8 +12,8 @@ template <typename TResult>
12
12
  class Promise;
13
13
  } // namespace margelo::nitro
14
14
 
15
+ #include "NitroTypeInfo.hpp"
15
16
  #include "Promise.hpp"
16
- #include "TypeInfo.hpp"
17
17
  #include <exception>
18
18
  #include <string>
19
19
 
@@ -32,8 +32,10 @@ public:
32
32
  BorrowingReference(const BorrowingReference& ref)
33
33
  : _value(ref._value), _isDeleted(ref._isDeleted), _strongRefCount(ref._strongRefCount), _weakRefCount(ref._weakRefCount),
34
34
  _mutex(ref._mutex) {
35
- // increment ref count after copy
36
- (*_weakRefCount)++;
35
+ if (_weakRefCount != nullptr) {
36
+ // increment ref count after copy
37
+ (*_weakRefCount)++;
38
+ }
37
39
  }
38
40
 
39
41
  BorrowingReference(BorrowingReference&& ref)
@@ -9,7 +9,7 @@
9
9
  #define NitroDefines_h
10
10
 
11
11
  // Sets the version of the native Nitro core library
12
- #define NITRO_VERSION "0.21.0"
12
+ #define NITRO_VERSION "0.22.0"
13
13
 
14
14
  // Sets whether to use debug or optimized production build flags
15
15
  #ifdef DEBUG
@@ -31,6 +31,7 @@
31
31
  #define _CXX_INTEROP_HAS_ATTRIBUTE(x) 0
32
32
  #endif
33
33
 
34
+ // Closed/Final Enums
34
35
  #if _CXX_INTEROP_HAS_ATTRIBUTE(enum_extensibility)
35
36
  // Enum is marked as closed/not extensible
36
37
  #define CLOSED_ENUM __attribute__((enum_extensibility(closed)))
@@ -38,6 +39,7 @@
38
39
  #define CLOSED_ENUM
39
40
  #endif
40
41
 
42
+ // Swift Support
41
43
  #if __has_include(<swift/bridging>)
42
44
  // Swift's bridging header defines those things
43
45
  #include <swift/bridging>
@@ -50,4 +52,14 @@
50
52
  #define SWIFT_NONCOPYABLE
51
53
  #endif
52
54
 
55
+ // React Native Support
56
+ #if __has_include(<cxxreact/ReactNativeVersion.h>)
57
+ #include <cxxreact/ReactNativeVersion.h>
58
+ #endif
59
+ #ifndef REACT_NATIVE_VERSION_MINOR
60
+ #define REACT_NATIVE_VERSION_MAJOR 0
61
+ #define REACT_NATIVE_VERSION_MINOR 0
62
+ #define REACT_NATIVE_VERSION_PATCH 0
63
+ #endif
64
+
53
65
  #endif /* NitroDefines_h */
@@ -9,6 +9,7 @@
9
9
 
10
10
  #include <cstddef>
11
11
  #include <cstdint>
12
+ #include <string>
12
13
 
13
14
  namespace margelo::nitro {
14
15
 
@@ -40,4 +41,20 @@ constexpr uint64_t hashString(const char (&str)[N]) {
40
41
  return hashString(str, N - 1); // N includes the null terminator, so subtract 1
41
42
  }
42
43
 
44
+ /**
45
+ * Hashes the given `string_view` using the FNV-1a hashing algorithm.
46
+ * This can be constexpr.
47
+ */
48
+ constexpr uint64_t hashString(const std::string_view& string) {
49
+ return hashString(string.data(), string.length());
50
+ }
51
+
52
+ /**
53
+ * Hashes the given `string` using the FNV-1a hashing algorithm.
54
+ * This happens at runtime.
55
+ */
56
+ inline uint64_t hashString(const std::string& string) {
57
+ return hashString(string.c_str(), string.length());
58
+ }
59
+
43
60
  } // namespace margelo::nitro
@@ -1,5 +1,5 @@
1
1
  //
2
- // TypeInfo.hpp
2
+ // NitroTypeInfo.hpp
3
3
  // Nitro
4
4
  //
5
5
  // Created by Marc Rousavy on 17.07.24.
@@ -8,6 +8,7 @@
8
8
  #pragma once
9
9
 
10
10
  #include "BorrowingReference.hpp"
11
+ #include "NitroDefines.hpp"
11
12
  #include "OwningLock.hpp"
12
13
  #include <atomic>
13
14
  #include <cstddef>
@@ -39,8 +40,10 @@ public:
39
40
  OwningReference(const OwningReference& ref)
40
41
  : _value(ref._value), _isDeleted(ref._isDeleted), _strongRefCount(ref._strongRefCount), _weakRefCount(ref._weakRefCount),
41
42
  _mutex(ref._mutex) {
42
- // increment ref count after copy
43
- (*_strongRefCount)++;
43
+ if (_strongRefCount != nullptr) {
44
+ // increment ref count after copy
45
+ (*_strongRefCount)++;
46
+ }
44
47
  }
45
48
 
46
49
  OwningReference(OwningReference&& ref)
@@ -161,10 +164,20 @@ public:
161
164
  }
162
165
 
163
166
  inline T& operator*() const {
167
+ #ifdef NITRO_DEBUG
168
+ if (!hasValue()) [[unlikely]] {
169
+ throw std::runtime_error("Tried to dereference (*) nullptr OwningReference<T>!");
170
+ }
171
+ #endif
164
172
  return *_value;
165
173
  }
166
174
 
167
175
  inline T* operator->() const {
176
+ #ifdef NITRO_DEBUG
177
+ if (!hasValue()) [[unlikely]] {
178
+ throw std::runtime_error("Tried to dereference (->) nullptr OwningReference<T>!");
179
+ }
180
+ #endif
168
181
  return _value;
169
182
  }
170
183