react-native-nitro-modules 0.0.2 → 0.0.4

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 (120) hide show
  1. package/NitroModules.podspec +49 -0
  2. package/android/CMakeLists.txt +44 -7
  3. package/android/build.gradle +28 -24
  4. package/cpp/core/AnyMap.cpp +181 -0
  5. package/cpp/core/AnyMap.hpp +191 -0
  6. package/cpp/core/HybridContext.hpp +51 -0
  7. package/cpp/core/HybridObject.cpp +220 -0
  8. package/cpp/core/HybridObject.hpp +241 -0
  9. package/cpp/core/PointerHolder.hpp +93 -0
  10. package/cpp/jsi/ArrayBuffer.hpp +79 -0
  11. package/cpp/jsi/JSICache.hpp +145 -0
  12. package/cpp/jsi/JSIConverter.hpp +610 -0
  13. package/cpp/jsi/Promise.cpp +54 -0
  14. package/cpp/jsi/Promise.hpp +54 -0
  15. package/cpp/platform/ThreadUtils.hpp +23 -0
  16. package/cpp/registry/HybridObjectRegistry.cpp +57 -0
  17. package/cpp/registry/HybridObjectRegistry.hpp +44 -0
  18. package/cpp/test-object/TestHybridObject.cpp +37 -0
  19. package/cpp/test-object/TestHybridObject.hpp +87 -0
  20. package/cpp/threading/CallInvokerDispatcher.hpp +33 -0
  21. package/cpp/threading/Dispatcher.cpp +56 -0
  22. package/cpp/threading/Dispatcher.hpp +82 -0
  23. package/cpp/turbomodule/NativeNitroModules.cpp +70 -0
  24. package/cpp/turbomodule/NativeNitroModules.h +7 -0
  25. package/cpp/turbomodule/NativeNitroModules.hpp +35 -0
  26. package/cpp/turbomodule/RegisterNativeNitroModules.cpp +33 -0
  27. package/cpp/turbomodule/RegisterNativeNitroModules.hpp +21 -0
  28. package/cpp/utils/BorrowingReference+Owning.hpp +34 -0
  29. package/cpp/utils/BorrowingReference.hpp +115 -0
  30. package/cpp/utils/DoesClassExist.hpp +23 -0
  31. package/cpp/utils/GetRuntimeID.hpp +28 -0
  32. package/cpp/utils/NitroDefines.hpp +32 -0
  33. package/cpp/utils/NitroHash.hpp +42 -0
  34. package/cpp/utils/NitroLogger.hpp +55 -0
  35. package/cpp/utils/OwningLock.hpp +54 -0
  36. package/cpp/utils/OwningReference.hpp +214 -0
  37. package/cpp/utils/TypeInfo.hpp +81 -0
  38. package/ios/core/HybridObjectSpec.swift +52 -0
  39. package/ios/core/RuntimeError.swift +17 -0
  40. package/ios/platform/ThreadUtils.cpp +28 -0
  41. package/ios/turbomodule/NitroModuleOnLoad.mm +31 -0
  42. package/lib/AnyMap.d.ts +16 -0
  43. package/lib/AnyMap.js +1 -0
  44. package/lib/HybridObject.d.ts +57 -0
  45. package/lib/HybridObject.js +1 -0
  46. package/lib/ModuleNotFoundError.d.ts +6 -0
  47. package/lib/ModuleNotFoundError.js +61 -0
  48. package/lib/NativeNitro.d.ts +8 -0
  49. package/lib/NativeNitro.js +3 -0
  50. package/lib/NativeNitroModules.d.ts +7 -0
  51. package/lib/NativeNitroModules.js +17 -0
  52. package/lib/NitroModules.d.ts +17 -0
  53. package/lib/NitroModules.js +21 -0
  54. package/lib/__tests__/index.test.d.ts +0 -0
  55. package/lib/__tests__/index.test.js +2 -0
  56. package/lib/commonjs/AnyMap.js +2 -0
  57. package/lib/commonjs/AnyMap.js.map +1 -0
  58. package/lib/commonjs/HybridObject.js +2 -0
  59. package/lib/commonjs/HybridObject.js.map +1 -0
  60. package/lib/commonjs/ModuleNotFoundError.js +72 -0
  61. package/lib/commonjs/ModuleNotFoundError.js.map +1 -0
  62. package/lib/commonjs/NativeNitroModules.js +24 -0
  63. package/lib/commonjs/NativeNitroModules.js.map +1 -0
  64. package/lib/commonjs/NitroModules.js +32 -0
  65. package/lib/commonjs/NitroModules.js.map +1 -0
  66. package/lib/commonjs/createTestObject.js +15 -0
  67. package/lib/commonjs/createTestObject.js.map +1 -0
  68. package/lib/commonjs/index.js +44 -5
  69. package/lib/commonjs/index.js.map +1 -1
  70. package/lib/createTestObject.d.ts +22 -0
  71. package/lib/createTestObject.js +7 -0
  72. package/lib/index.d.ts +4 -0
  73. package/lib/index.js +4 -0
  74. package/lib/module/AnyMap.js +2 -0
  75. package/lib/module/AnyMap.js.map +1 -0
  76. package/lib/module/HybridObject.js +2 -0
  77. package/lib/module/HybridObject.js.map +1 -0
  78. package/lib/module/ModuleNotFoundError.js +65 -0
  79. package/lib/module/ModuleNotFoundError.js.map +1 -0
  80. package/lib/module/NativeNitroModules.js +18 -0
  81. package/lib/module/NativeNitroModules.js.map +1 -0
  82. package/lib/module/NitroModules.js +27 -0
  83. package/lib/module/NitroModules.js.map +1 -0
  84. package/lib/module/createTestObject.js +8 -0
  85. package/lib/module/createTestObject.js.map +1 -0
  86. package/lib/module/index.js +4 -4
  87. package/lib/module/index.js.map +1 -1
  88. package/lib/tsconfig.tsbuildinfo +1 -0
  89. package/package.json +76 -49
  90. package/react-native.config.js +16 -0
  91. package/src/AnyMap.ts +22 -0
  92. package/src/HybridObject.ts +58 -0
  93. package/src/ModuleNotFoundError.ts +90 -0
  94. package/src/NativeNitroModules.ts +26 -0
  95. package/src/NitroModules.ts +30 -0
  96. package/src/__tests__/index.test.tsx +1 -0
  97. package/src/createTestObject.ts +40 -0
  98. package/src/index.ts +4 -0
  99. package/LICENSE +0 -20
  100. package/README.md +0 -32
  101. package/android/cpp-adapter.cpp +0 -8
  102. package/android/src/main/AndroidManifest.xml +0 -3
  103. package/android/src/main/AndroidManifestNew.xml +0 -2
  104. package/android/src/main/java/com/nitro/NitroModule.java +0 -34
  105. package/android/src/main/java/com/nitro/NitroPackage.java +0 -44
  106. package/cpp/react-native-nitro.cpp +0 -7
  107. package/cpp/react-native-nitro.h +0 -8
  108. package/ios/Nitro.h +0 -15
  109. package/ios/Nitro.mm +0 -21
  110. package/lib/commonjs/NativeNitro.js +0 -9
  111. package/lib/commonjs/NativeNitro.js.map +0 -1
  112. package/lib/module/NativeNitro.js +0 -3
  113. package/lib/module/NativeNitro.js.map +0 -1
  114. package/lib/typescript/src/NativeNitro.d.ts +0 -7
  115. package/lib/typescript/src/NativeNitro.d.ts.map +0 -1
  116. package/lib/typescript/src/index.d.ts +0 -2
  117. package/lib/typescript/src/index.d.ts.map +0 -1
  118. package/react-native-nitro.podspec +0 -41
  119. package/src/NativeNitro.ts +0 -8
  120. package/src/index.tsx +0 -5
@@ -0,0 +1,54 @@
1
+ //
2
+ // Promise.hpp
3
+ // react-native-filament
4
+ //
5
+ // Created by Marc Rousavy on 11.03.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "OwningReference.hpp"
11
+ #include <functional>
12
+ #include <jsi/jsi.h>
13
+ #include <memory>
14
+
15
+ namespace margelo::nitro {
16
+
17
+ using namespace facebook;
18
+
19
+ /**
20
+ Represents a JS Promise.
21
+
22
+ `Promise` is not thread-safe: It has to be resolved/rejected
23
+ on the same thread and Runtime as it was created on.
24
+ */
25
+ class Promise final {
26
+ public:
27
+ Promise(jsi::Runtime& runtime, jsi::Function&& resolver, jsi::Function&& rejecter);
28
+
29
+ /**
30
+ Resolve the Promise with the given `jsi::Value`.
31
+ If the `jsi::Runtime` has already been deleted, this will do nothing.
32
+ */
33
+ void resolve(jsi::Runtime& runtime, jsi::Value&& result);
34
+ /**
35
+ Resolve the Promise with the given error message.
36
+ If the `jsi::Runtime` has already been deleted, this will do nothing.
37
+ */
38
+ void reject(jsi::Runtime& runtime, std::string error);
39
+
40
+ private:
41
+ OwningReference<jsi::Function> _resolver;
42
+ OwningReference<jsi::Function> _rejecter;
43
+ static constexpr auto TAG = "Promise";
44
+
45
+ public:
46
+ using RunPromise = std::function<void(jsi::Runtime& runtime, std::shared_ptr<Promise> promise)>;
47
+ /**
48
+ Create a new Promise using the JS `Promise` constructor and runs the given `run` function.
49
+ The resulting Promise should be returned to JS so it can be awaited.
50
+ */
51
+ static jsi::Value createPromise(jsi::Runtime& runtime, RunPromise&& run);
52
+ };
53
+
54
+ } // namespace margelo::nitro
@@ -0,0 +1,23 @@
1
+ //
2
+ // ThreadUtils.hpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 14.07.24.
6
+ //
7
+
8
+ #include <string>
9
+
10
+ namespace margelo::nitro {
11
+
12
+ class ThreadUtils final {
13
+ public:
14
+ ThreadUtils() = delete;
15
+
16
+ /**
17
+ * Get the current Thread's name.
18
+ * This is implemented differently on iOS and Android.
19
+ */
20
+ static std::string getThreadName();
21
+ };
22
+
23
+ } // namespace margelo::nitro
@@ -0,0 +1,57 @@
1
+ //
2
+ // HybridObjectRegistry.cpp
3
+ // DoubleConversion
4
+ //
5
+ // Created by Marc Rousavy on 22.07.24.
6
+ //
7
+
8
+ #include "HybridObjectRegistry.hpp"
9
+ #include "NitroLogger.hpp"
10
+
11
+ namespace margelo::nitro {
12
+
13
+ std::unordered_map<std::string, HybridObjectRegistry::HybridObjectConstructorFn>& HybridObjectRegistry::getRegistry() {
14
+ static std::unordered_map<std::string, HybridObjectRegistry::HybridObjectConstructorFn> _constructorsMap;
15
+ return _constructorsMap;
16
+ }
17
+
18
+ void HybridObjectRegistry::registerHybridObjectConstructor(std::string hybridObjectName, HybridObjectConstructorFn&& constructorFn) {
19
+ Logger::log(TAG, "Registering HybridObject \"%s\"...", hybridObjectName);
20
+ auto& map = HybridObjectRegistry::getRegistry();
21
+ if (map.contains(hybridObjectName)) [[unlikely]] {
22
+ auto message =
23
+ "HybridObject \"" + std::string(hybridObjectName) +
24
+ "\" has already been "
25
+ "registered in the Nitro Modules HybridObjectRegistry! Suggestions:\n"
26
+ "- If you just installed another library, maybe both libraries are using the same name?\n"
27
+ "- If you just registered your own HybridObject, maybe you accidentally called `registerHybridObjectConstructor(...)` twice?";
28
+ throw std::runtime_error(message);
29
+ }
30
+ map.insert({hybridObjectName, std::move(constructorFn)});
31
+ Logger::log(TAG, "Successfully registered HybridObject \"%s\"!", hybridObjectName);
32
+ }
33
+
34
+ std::shared_ptr<HybridObject> HybridObjectRegistry::createHybridObject(std::string hybridObjectName) {
35
+ auto& map = HybridObjectRegistry::getRegistry();
36
+ auto fn = map.find(hybridObjectName);
37
+ if (fn == map.end()) [[unlikely]] {
38
+ auto message = "Cannot create an instance of HybridObject \"" + std::string(hybridObjectName) +
39
+ "\" - "
40
+ "It has not yet been registered in the Nitro Modules HybridObjectRegistry!";
41
+ throw std::runtime_error(message);
42
+ }
43
+ std::shared_ptr<HybridObject> instance = fn->second();
44
+
45
+ #if DEBUG
46
+ if (instance->getName() != hybridObjectName) [[unlikely]] {
47
+ throw std::runtime_error("HybridObject's name (\"" + instance->getName() +
48
+ "\") does not match"
49
+ "the name it was registered with (\"" +
50
+ hybridObjectName + "\")!");
51
+ }
52
+ #endif
53
+
54
+ return instance;
55
+ }
56
+
57
+ } // namespace margelo::nitro
@@ -0,0 +1,44 @@
1
+ //
2
+ // HybridObjectRegistry.hpp
3
+ // DoubleConversion
4
+ //
5
+ // Created by Marc Rousavy on 22.07.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "HybridObject.hpp"
11
+ #include <functional>
12
+ #include <string>
13
+
14
+ namespace margelo::nitro {
15
+
16
+ /**
17
+ * A registry that holds initializers for HybridObjects.
18
+ * This will be used to initialize them from JS using `NitroModules.get<T>(name)`.
19
+ */
20
+ class HybridObjectRegistry {
21
+ public:
22
+ HybridObjectRegistry() = delete;
23
+
24
+ public:
25
+ using HybridObjectConstructorFn = std::function<std::shared_ptr<HybridObject>()>;
26
+
27
+ public:
28
+ /**
29
+ * Registers the given HybridObject in the `HybridObjectRegistry`.
30
+ * It will be uniquely identified via it's `hybridObjectName`, and can be initialized from
31
+ * JS using `NitroModules.get<T>(name)` - which will call the `constructorFn` here.
32
+ */
33
+ static void registerHybridObjectConstructor(std::string hybridObjectName, HybridObjectConstructorFn&& constructorFn);
34
+
35
+ static std::shared_ptr<HybridObject> createHybridObject(std::string hybridObjectName);
36
+
37
+ private:
38
+ static std::unordered_map<std::string, HybridObjectConstructorFn>& getRegistry();
39
+
40
+ private:
41
+ static constexpr auto TAG = "HybridObjectRegistry";
42
+ };
43
+
44
+ } // namespace margelo::nitro
@@ -0,0 +1,37 @@
1
+ //
2
+ // Created by Marc Rousavy on 20.02.24.
3
+ //
4
+
5
+ #include "TestHybridObject.hpp"
6
+
7
+ namespace margelo::nitro {
8
+
9
+ void TestHybridObject::loadHybridMethods() {
10
+ HybridObject::loadHybridMethods();
11
+
12
+ // this.int get & set
13
+ registerHybridGetter("int", &TestHybridObject::getInt, this);
14
+ registerHybridSetter("int", &TestHybridObject::setInt, this);
15
+ // this.string get & set
16
+ registerHybridGetter("string", &TestHybridObject::getString, this);
17
+ registerHybridSetter("string", &TestHybridObject::setString, this);
18
+ // this.nullableString get & set
19
+ registerHybridGetter("nullableString", &TestHybridObject::getNullableString, this);
20
+ registerHybridSetter("nullableString", &TestHybridObject::setNullableString, this);
21
+ // methods
22
+ registerHybridMethod("multipleArguments", &TestHybridObject::multipleArguments, this);
23
+ // callbacks
24
+ registerHybridMethod("getIntGetter", &TestHybridObject::getIntGetter, this);
25
+ registerHybridMethod("sayHelloCallback", &TestHybridObject::sayHelloCallback, this);
26
+ // custom types
27
+ registerHybridMethod("createNewHybridObject", &TestHybridObject::createNewHybridObject, this);
28
+ // Promises
29
+ registerHybridMethod("calculateFibonacci", &TestHybridObject::calculateFibonacci, this);
30
+ registerHybridMethod("calculateFibonacciAsync", &TestHybridObject::calculateFibonacciAsync, this);
31
+ registerHybridMethod("asyncVoidFunc", &TestHybridObject::asyncVoidFunc, this);
32
+ registerHybridMethod("syncVoidFunc", &TestHybridObject::syncVoidFunc, this);
33
+ // Error
34
+ registerHybridMethod("throwError", &TestHybridObject::throwError, this);
35
+ }
36
+
37
+ } // namespace margelo::nitro
@@ -0,0 +1,87 @@
1
+ //
2
+ // Created by Marc Rousavy on 22.02.24.
3
+ //
4
+
5
+ #pragma once
6
+
7
+ #include "HybridObject.hpp"
8
+ #include <optional>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ namespace margelo::nitro {
13
+
14
+ class TestHybridObject : public HybridObject {
15
+ public:
16
+ explicit TestHybridObject() : HybridObject("TestHybridObject") {}
17
+
18
+ public:
19
+ int getInt() {
20
+ return _int;
21
+ }
22
+ void setInt(int newValue) {
23
+ _int = newValue;
24
+ }
25
+ std::string getString() {
26
+ return _string;
27
+ }
28
+ void setString(const std::string& newValue) {
29
+ _string = newValue;
30
+ }
31
+ std::optional<std::string> getNullableString() {
32
+ return _nullableString;
33
+ }
34
+ void setNullableString(std::optional<std::string> string) {
35
+ _nullableString = string;
36
+ }
37
+
38
+ std::unordered_map<std::string, double> multipleArguments(int first, bool second, std::string third) {
39
+ return std::unordered_map<std::string, double>{{"first", 5312}, {"second", 532233}, {"third", 2786}};
40
+ }
41
+
42
+ std::function<int()> getIntGetter() {
43
+ return [this]() -> int { return this->_int; };
44
+ }
45
+ void sayHelloCallback(std::function<void(std::string)> callback) {
46
+ callback("Test Hybrid");
47
+ }
48
+ std::shared_ptr<TestHybridObject> createNewHybridObject() {
49
+ return std::make_shared<TestHybridObject>();
50
+ }
51
+
52
+ void throwError() {
53
+ throw std::runtime_error("This is an error!");
54
+ }
55
+
56
+ uint64_t calculateFibonacci(int count) {
57
+ if (count <= 0)
58
+ return 0;
59
+ if (count == 1)
60
+ return 1;
61
+
62
+ return calculateFibonacci(count - 1) + calculateFibonacci(count - 2);
63
+ }
64
+
65
+ std::future<uint64_t> calculateFibonacciAsync(int count) {
66
+ return std::async(std::launch::async, [count, this]() { return this->calculateFibonacci(count); });
67
+ }
68
+
69
+ void syncVoidFunc() {
70
+ // this function does nothing
71
+ }
72
+
73
+ std::future<void> asyncVoidFunc() {
74
+ return std::async(std::launch::async, []() {
75
+ // this function does nothing
76
+ });
77
+ }
78
+
79
+ private:
80
+ int _int;
81
+ std::string _string;
82
+ std::optional<std::string> _nullableString;
83
+
84
+ void loadHybridMethods() override;
85
+ };
86
+
87
+ } // namespace margelo::nitro
@@ -0,0 +1,33 @@
1
+ //
2
+ // Created by Marc Rousavy on 27.03.24.
3
+ //
4
+
5
+ #pragma once
6
+
7
+ #include "Dispatcher.hpp"
8
+ #include <ReactCommon/CallInvoker.h>
9
+
10
+ namespace margelo::nitro {
11
+
12
+ using namespace facebook;
13
+
14
+ /**
15
+ * A Dispatcher that uses react::CallInvoker for it's implementation
16
+ */
17
+ class CallInvokerDispatcher final : public Dispatcher {
18
+ public:
19
+ explicit CallInvokerDispatcher(std::shared_ptr<react::CallInvoker> callInvoker) : _callInvoker(callInvoker) {}
20
+
21
+ void runAsync(std::function<void()>&& function) override {
22
+ _callInvoker->invokeAsync(std::move(function));
23
+ }
24
+
25
+ void runSync(std::function<void()>&& function) override {
26
+ _callInvoker->invokeSync(std::move(function));
27
+ }
28
+
29
+ private:
30
+ std::shared_ptr<react::CallInvoker> _callInvoker;
31
+ };
32
+
33
+ } // namespace margelo::nitro
@@ -0,0 +1,56 @@
1
+ #include "Dispatcher.hpp"
2
+ #include "GetRuntimeID.hpp"
3
+ #include "NitroLogger.hpp"
4
+
5
+ namespace margelo::nitro {
6
+
7
+ using namespace facebook;
8
+
9
+ static constexpr auto GLOBAL_DISPATCHER_HOLDER_NAME = "__nitroDispatcher";
10
+
11
+ std::unordered_map<jsi::Runtime*, std::weak_ptr<Dispatcher>> Dispatcher::_globalCache;
12
+
13
+ void Dispatcher::installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher) {
14
+ Logger::log(TAG, "Installing global Dispatcher Holder into Runtime \"%s\"...", getRuntimeId(runtime));
15
+
16
+ // Store a weak reference in global cache
17
+ _globalCache[&runtime] = std::weak_ptr(dispatcher);
18
+
19
+ // Inject the dispatcher into Runtime global (runtime will hold a strong reference)
20
+ jsi::Object dispatcherHolder(runtime);
21
+ dispatcherHolder.setNativeState(runtime, dispatcher);
22
+ runtime.global().setProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME, dispatcherHolder);
23
+ }
24
+
25
+ std::shared_ptr<Dispatcher> Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime& runtime) {
26
+ if (_globalCache.contains(&runtime)) [[likely]] {
27
+ // the runtime is known - we have something in cache
28
+ std::weak_ptr<Dispatcher> weakDispatcher = _globalCache[&runtime];
29
+ std::shared_ptr<Dispatcher> strongDispatcher = weakDispatcher.lock();
30
+ if (strongDispatcher) {
31
+ // the weak reference we cached is still valid - return it!
32
+ return strongDispatcher;
33
+ }
34
+ }
35
+
36
+ Logger::log(TAG, "Unknown Runtime (%s), looking for Dispatcher through JSI global lookup...", getRuntimeId(runtime));
37
+ jsi::Value dispatcherHolderValue = getRuntimeGlobalDispatcherHolder(runtime);
38
+ jsi::Object dispatcherHolder = dispatcherHolderValue.getObject(runtime);
39
+ return dispatcherHolder.getNativeState<Dispatcher>(runtime);
40
+ }
41
+
42
+ jsi::Value Dispatcher::getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime) {
43
+ #if DEBUG
44
+ if (!runtime.global().hasProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME)) {
45
+ throw std::runtime_error("Failed to get current Dispatcher - the global Dispatcher "
46
+ "holder (global." +
47
+ std::string(GLOBAL_DISPATCHER_HOLDER_NAME) +
48
+ ") "
49
+ "does not exist! Was Dispatcher::installDispatcherIntoRuntime() called "
50
+ "for this jsi::Runtime?");
51
+ }
52
+ #endif
53
+ return runtime.global().getProperty(runtime, GLOBAL_DISPATCHER_HOLDER_NAME);
54
+ }
55
+
56
+ } // namespace margelo::nitro
@@ -0,0 +1,82 @@
1
+ //
2
+ // Created by Marc Rousavy on 12.03.24.
3
+ //
4
+
5
+ #pragma once
6
+
7
+ #include <functional>
8
+ #include <future>
9
+ #include <jsi/jsi.h>
10
+ #include <queue>
11
+ #include <unordered_map>
12
+
13
+ namespace margelo::nitro {
14
+
15
+ using namespace facebook;
16
+
17
+ class Dispatcher : public jsi::NativeState {
18
+ public:
19
+ /**
20
+ Installs the Dispatcher into the given Runtime.
21
+ It can be accessed using `getRuntimeGlobalDispatcher` later.
22
+ */
23
+ static void installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher);
24
+ /**
25
+ Gets the global Dispatcher in the given Runtime, or throws an error if not found.
26
+ */
27
+ static std::shared_ptr<Dispatcher> getRuntimeGlobalDispatcher(jsi::Runtime& runtime);
28
+
29
+ private:
30
+ static jsi::Value getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime);
31
+
32
+ public:
33
+ /**
34
+ * Run the given void function synchronously on the Thread this Dispatcher is managing.
35
+ */
36
+ virtual void runSync(std::function<void()>&& function) = 0;
37
+
38
+ /**
39
+ * Run the given void function asynchronously on the Thread this Dispatcher is managing.
40
+ */
41
+ virtual void runAsync(std::function<void()>&& function) = 0;
42
+
43
+ /**
44
+ * Run the given function asynchronously on the Thread this Dispatcher is managing,
45
+ * and return a future that will hold the result of the function.
46
+ */
47
+ template <typename T> std::future<T> runAsyncAwaitable(std::function<T()>&& function) {
48
+ // 1. Create Promise that can be shared between this and dispatcher thread
49
+ auto promise = std::make_shared<std::promise<T>>();
50
+ std::future<T> future = promise->get_future();
51
+
52
+ runAsync([function = std::move(function), promise]() {
53
+ try {
54
+ if constexpr (std::is_void_v<T>) {
55
+ // 4. Call the actual function on the new Thread
56
+ function();
57
+ // 5.a. Resolve the Promise if we succeeded
58
+ promise->set_value();
59
+ } else {
60
+ // 4. Call the actual function on the new Thread
61
+ T result = function();
62
+ // 5.a. Resolve the Promise if we succeeded
63
+ promise->set_value(std::move(result));
64
+ }
65
+ } catch (...) {
66
+ // 5.b. Reject the Promise if the call failed
67
+ promise->set_exception(std::current_exception());
68
+ }
69
+ });
70
+
71
+ // 3. Return an open future that gets resolved later by the dispatcher Thread
72
+ return future;
73
+ }
74
+
75
+ private:
76
+ static std::unordered_map<jsi::Runtime*, std::weak_ptr<Dispatcher>> _globalCache;
77
+
78
+ private:
79
+ static constexpr auto TAG = "Dispatcher";
80
+ };
81
+
82
+ } // namespace margelo::nitro
@@ -0,0 +1,70 @@
1
+ //
2
+ // NativeNitroModules.cpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 21.06.24.
6
+ //
7
+
8
+ #include "NativeNitroModules.hpp"
9
+ #include "CallInvokerDispatcher.hpp"
10
+ #include "Dispatcher.hpp"
11
+ #include "HybridObjectRegistry.hpp"
12
+ #include "TestHybridObject.hpp"
13
+
14
+ namespace facebook::react {
15
+
16
+ using namespace margelo::nitro;
17
+
18
+ NativeNitroModules::NativeNitroModules(std::shared_ptr<CallInvoker> jsInvoker)
19
+ : TurboModule(kModuleName, jsInvoker), _callInvoker(jsInvoker) {}
20
+
21
+ NativeNitroModules::~NativeNitroModules() {}
22
+
23
+ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
24
+ std::string name = propName.utf8(runtime);
25
+
26
+ if (name == "install") {
27
+ return jsi::Function::createFromHostFunction(
28
+ runtime, jsi::PropNameID::forUtf8(runtime, "install"), 0,
29
+ [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
30
+ install(runtime);
31
+ return jsi::Value::undefined();
32
+ });
33
+ }
34
+ if (name == "createHybridObject") {
35
+ return jsi::Function::createFromHostFunction(
36
+ runtime, jsi::PropNameID::forUtf8(runtime, "install"), 2,
37
+ [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
38
+ if (count != 1 && count != 2) {
39
+ throw jsi::JSError(runtime, "NitroModules.createHybridObject(..) expects 1 or 2 arguments, but " + std::to_string(count) +
40
+ " were supplied!");
41
+ }
42
+ jsi::String objectName = args[0].asString(runtime);
43
+ std::optional<jsi::Object> optionalArgs = std::nullopt;
44
+ if (count > 1) {
45
+ optionalArgs = args[1].asObject(runtime);
46
+ }
47
+
48
+ return createHybridObject(runtime, objectName, optionalArgs);
49
+ });
50
+ }
51
+
52
+ return jsi::Value::undefined();
53
+ }
54
+
55
+ void NativeNitroModules::install(jsi::Runtime& runtime) {
56
+ // Installs the global Dispatcher mechanism into this Runtime.
57
+ // This allows creating Promises and calling back to JS.
58
+ auto dispatcher = std::make_shared<CallInvokerDispatcher>(_callInvoker);
59
+ Dispatcher::installRuntimeGlobalDispatcher(runtime, dispatcher);
60
+ }
61
+
62
+ jsi::Object NativeNitroModules::createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName,
63
+ const std::optional<jsi::Object>& args) {
64
+ auto name = hybridObjectName.utf8(runtime);
65
+ // TODO: Pass args? Do we need that?
66
+ auto hybridObject = HybridObjectRegistry::createHybridObject(name.c_str());
67
+ return jsi::Object::createFromHostObject(runtime, hybridObject);
68
+ }
69
+
70
+ } // namespace facebook::react
@@ -0,0 +1,7 @@
1
+ //
2
+ // Created by Marc Rousavy on 26.07.24.
3
+ //
4
+
5
+ #pragma once
6
+
7
+ #include "NativeNitroModules.hpp"
@@ -0,0 +1,35 @@
1
+ //
2
+ // NativeNitroModules.hpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 21.06.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include <ReactCommon/TurboModule.h>
11
+
12
+ namespace facebook::react {
13
+
14
+ using namespace facebook;
15
+
16
+ // The base C++-based TurboModule. This is the entry point where all nitro modules get initialized.
17
+ class NativeNitroModules : public TurboModule {
18
+ public:
19
+ NativeNitroModules(std::shared_ptr<CallInvoker> jsInvoker);
20
+ ~NativeNitroModules();
21
+
22
+ public:
23
+ jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override;
24
+
25
+ void install(jsi::Runtime& runtime);
26
+ jsi::Object createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName, const std::optional<jsi::Object>& args);
27
+
28
+ public:
29
+ constexpr static auto kModuleName = "NitroModulesCxx";
30
+
31
+ private:
32
+ std::shared_ptr<CallInvoker> _callInvoker;
33
+ };
34
+
35
+ } // namespace facebook::react
@@ -0,0 +1,33 @@
1
+ //
2
+ // RegisterNativeNitroModules.cpp
3
+ // DoubleConversion
4
+ //
5
+ // Created by Marc Rousavy on 21.06.24.
6
+ //
7
+
8
+ #include "RegisterNativeNitroModules.hpp"
9
+ #include "NativeNitroModules.hpp"
10
+ #include <memory>
11
+ #include <string>
12
+
13
+ #if __has_include(<ReactCommon/CallInvoker.h>)
14
+ // Android style imports
15
+ #include <ReactCommon/CallInvoker.h>
16
+ #include <ReactCommon/CxxTurboModuleUtils.h>
17
+ #else
18
+ // iOS style imports
19
+ #include <React-callinvoker/ReactCommon/CallInvoker.h>
20
+ #include <ReactCommon/ReactCommon/CxxTurboModuleUtils.h>
21
+ #endif
22
+
23
+ namespace margelo::nitro {
24
+
25
+ using namespace facebook;
26
+
27
+ void RegisterNativeNitroModules::registerNativeNitroModules() {
28
+ react::registerCxxModuleToGlobalModuleMap(
29
+ std::string(react::NativeNitroModules::kModuleName),
30
+ [&](std::shared_ptr<react::CallInvoker> jsInvoker) { return std::make_shared<react::NativeNitroModules>(jsInvoker); });
31
+ }
32
+
33
+ } // namespace margelo::nitro
@@ -0,0 +1,21 @@
1
+ //
2
+ // RegisterNativeNitroModules.hpp
3
+ // DoubleConversion
4
+ //
5
+ // Created by Marc Rousavy on 21.06.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ namespace margelo::nitro {
11
+
12
+ class RegisterNativeNitroModules {
13
+ public:
14
+ /**
15
+ Registers the native NitroModules TurboModule into the React Runtime.
16
+ This can be called from Swift/Objective-C.
17
+ */
18
+ static void registerNativeNitroModules();
19
+ };
20
+
21
+ } // namespace margelo::nitro
@@ -0,0 +1,34 @@
1
+ //
2
+ // BorrowingReference+Owning.hpp
3
+ // react-native-nitro
4
+ //
5
+ // Created by Marc Rousavy on 23.06.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "OwningReference.hpp"
11
+
12
+ namespace margelo::nitro {
13
+
14
+ template <typename T> BorrowingReference<T>::BorrowingReference(const OwningReference<T>& ref) {
15
+ _value = ref._value;
16
+ _isDeleted = ref._isDeleted;
17
+ _strongRefCount = ref._strongRefCount;
18
+ _weakRefCount = ref._weakRefCount;
19
+ _mutex = ref._mutex;
20
+ (*_weakRefCount)++;
21
+ }
22
+
23
+ template <typename T> OwningReference<T> BorrowingReference<T>::lock() {
24
+ std::unique_lock lock(*_mutex);
25
+
26
+ if (*_isDeleted) {
27
+ // return nullptr
28
+ return OwningReference<T>();
29
+ }
30
+
31
+ return OwningReference(*this);
32
+ }
33
+
34
+ } // namespace margelo::nitro