react-native-nitro-modules 0.4.1 → 0.6.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 (109) hide show
  1. package/NitroModules.podspec +4 -1
  2. package/README.md +35 -16
  3. package/android/gradle.properties +5 -5
  4. package/android/src/main/cpp/JNIOnLoad.cpp +8 -0
  5. package/android/src/main/cpp/core/ByteBufferArrayBuffer.hpp +47 -0
  6. package/android/src/main/cpp/core/JAnyMap.hpp +193 -0
  7. package/android/src/main/cpp/core/JAnyValue.hpp +191 -0
  8. package/android/src/main/cpp/core/JArrayBuffer.hpp +119 -0
  9. package/android/src/main/cpp/core/JHybridObject.hpp +11 -4
  10. package/android/src/main/cpp/core/JPromise.hpp +88 -0
  11. package/android/src/main/cpp/platform/NitroLogger.cpp +36 -0
  12. package/android/src/main/cpp/registry/JHybridObjectInitializer.hpp +1 -1
  13. package/android/src/main/cpp/registry/JHybridObjectRegistry.cpp +1 -1
  14. package/android/src/main/cpp/registry/JHybridObjectRegistry.hpp +1 -1
  15. package/android/src/main/cpp/utils/{JNISharedPtr.h → JNISharedPtr.hpp} +13 -1
  16. package/android/src/main/java/com/margelo/nitro/JNIOnLoad.java +27 -0
  17. package/android/src/main/java/com/margelo/nitro/NitroModulesPackage.java +1 -9
  18. package/android/src/main/java/com/margelo/nitro/core/AnyMap.kt +61 -0
  19. package/android/src/main/java/com/margelo/nitro/core/AnyValue.kt +153 -0
  20. package/android/src/main/java/com/margelo/nitro/core/ArrayBuffer.kt +84 -0
  21. package/android/src/main/java/com/margelo/nitro/{HybridObject.kt → core/HybridObject.kt} +12 -15
  22. package/android/src/main/java/com/margelo/nitro/{HybridObjectInitializer.java → core/HybridObjectInitializer.java} +1 -1
  23. package/android/src/main/java/com/margelo/nitro/{HybridObjectRegistry.java → core/HybridObjectRegistry.java} +6 -4
  24. package/android/src/main/java/com/margelo/nitro/core/Promise.kt +115 -0
  25. package/cpp/core/AnyMap.hpp +2 -2
  26. package/cpp/core/ArrayBuffer.cpp +5 -5
  27. package/cpp/core/ArrayBuffer.hpp +12 -7
  28. package/cpp/core/HybridFunction.hpp +119 -45
  29. package/cpp/core/HybridObject.cpp +17 -6
  30. package/cpp/core/HybridObject.hpp +32 -8
  31. package/cpp/jsi/JSICache.cpp +5 -5
  32. package/cpp/jsi/JSICache.hpp +1 -3
  33. package/cpp/jsi/JSIConverter+AnyMap.hpp +2 -2
  34. package/cpp/jsi/JSIConverter+ArrayBuffer.hpp +2 -2
  35. package/cpp/jsi/JSIConverter+Function.hpp +7 -6
  36. package/cpp/jsi/JSIConverter+HybridObject.hpp +6 -5
  37. package/cpp/jsi/JSIConverter+Optional.hpp +1 -1
  38. package/cpp/jsi/JSIConverter+Promise.hpp +6 -4
  39. package/cpp/jsi/JSIConverter+Tuple.hpp +1 -1
  40. package/cpp/jsi/JSIConverter+UnorderedMap.hpp +1 -1
  41. package/cpp/jsi/JSIConverter+Variant.hpp +1 -3
  42. package/cpp/jsi/JSIConverter+Vector.hpp +1 -1
  43. package/cpp/jsi/JSIConverter.hpp +11 -11
  44. package/cpp/jsi/JSPromise.cpp +2 -2
  45. package/cpp/platform/NitroLogger.hpp +67 -0
  46. package/cpp/prototype/HybridObjectPrototype.cpp +2 -2
  47. package/cpp/prototype/Prototype.hpp +43 -22
  48. package/cpp/registry/HybridObjectRegistry.cpp +4 -4
  49. package/cpp/threading/Dispatcher.cpp +4 -3
  50. package/cpp/threading/ThreadPool.cpp +2 -2
  51. package/cpp/turbomodule/NativeNitroModules.cpp +26 -8
  52. package/cpp/turbomodule/NativeNitroModules.h +1 -0
  53. package/cpp/turbomodule/NativeNitroModules.hpp +2 -0
  54. package/cpp/utils/TypeInfo.hpp +14 -0
  55. package/ios/core/AnyMapHolder.hpp +91 -0
  56. package/ios/core/AnyMapHolder.swift +316 -0
  57. package/ios/core/ArrayBufferHolder.hpp +16 -5
  58. package/ios/core/{ArrayBuffer.swift → ArrayBufferHolder.swift} +15 -17
  59. package/ios/core/HybridContext.hpp +3 -3
  60. package/ios/core/Promise.swift +182 -0
  61. package/ios/core/PromiseHolder.hpp +86 -0
  62. package/ios/platform/NitroLogger.mm +36 -0
  63. package/ios/platform/ThreadUtils.cpp +1 -1
  64. package/ios/turbomodule/NitroModuleOnLoad.mm +6 -0
  65. package/ios/utils/SwiftClosure.hpp +63 -0
  66. package/ios/utils/SwiftClosure.swift +58 -0
  67. package/lib/AnyMap.d.ts +3 -0
  68. package/lib/HybridObject.d.ts +15 -0
  69. package/lib/NativeNitroModules.d.ts +2 -0
  70. package/lib/NitroModules.d.ts +18 -0
  71. package/lib/NitroModules.js +24 -0
  72. package/lib/commonjs/NativeNitroModules.js.map +1 -1
  73. package/lib/commonjs/NitroModules.js +24 -0
  74. package/lib/commonjs/NitroModules.js.map +1 -1
  75. package/lib/commonjs/package.json +1 -0
  76. package/lib/module/AnyMap.js +1 -1
  77. package/lib/module/HybridObject.js +1 -1
  78. package/lib/module/ModuleNotFoundError.js +2 -0
  79. package/lib/module/ModuleNotFoundError.js.map +1 -1
  80. package/lib/module/NativeNitroModules.js +2 -0
  81. package/lib/module/NativeNitroModules.js.map +1 -1
  82. package/lib/module/NativeNitroModules.web.js +2 -0
  83. package/lib/module/NativeNitroModules.web.js.map +1 -1
  84. package/lib/module/NitroModules.js +26 -0
  85. package/lib/module/NitroModules.js.map +1 -1
  86. package/lib/module/index.js +2 -0
  87. package/lib/module/index.js.map +1 -1
  88. package/lib/module/package.json +1 -0
  89. package/lib/tsconfig.tsbuildinfo +1 -1
  90. package/lib/typescript/AnyMap.d.ts +20 -0
  91. package/lib/typescript/AnyMap.d.ts.map +1 -1
  92. package/lib/typescript/HybridObject.d.ts +98 -0
  93. package/lib/typescript/HybridObject.d.ts.map +1 -1
  94. package/lib/typescript/NativeNitroModules.d.ts +2 -0
  95. package/lib/typescript/NativeNitroModules.d.ts.map +1 -1
  96. package/lib/typescript/NitroModules.d.ts +18 -0
  97. package/lib/typescript/NitroModules.d.ts.map +1 -1
  98. package/package.json +13 -12
  99. package/src/AnyMap.ts +3 -0
  100. package/src/HybridObject.ts +15 -0
  101. package/src/NativeNitroModules.ts +5 -0
  102. package/src/NitroModules.ts +24 -0
  103. package/android/src/main/cpp/core/JHybridObject.cpp +0 -8
  104. package/cpp/templates/IsInPack.hpp +0 -21
  105. package/cpp/utils/NitroLogger.hpp +0 -58
  106. package/ios/core/ClosureWrapper.swift +0 -25
  107. package/ios/core/HybridContext.cpp +0 -8
  108. package/ios/core/Promise.cpp +0 -10
  109. package/ios/core/Promise.hpp +0 -43
@@ -25,7 +25,7 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
25
25
  if (name == "install") {
26
26
  return jsi::Function::createFromHostFunction(
27
27
  runtime, jsi::PropNameID::forUtf8(runtime, "install"), 0,
28
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
28
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
29
29
  install(runtime);
30
30
  return jsi::Value::undefined();
31
31
  });
@@ -33,8 +33,8 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
33
33
  if (name == "createHybridObject") {
34
34
  return jsi::Function::createFromHostFunction(
35
35
  runtime, jsi::PropNameID::forUtf8(runtime, "createHybridObject"), 2,
36
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
37
- #if DEBUG
36
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
37
+ #ifndef NDEBUG
38
38
  if (count != 1 && count != 2) [[unlikely]] {
39
39
  throw jsi::JSError(runtime, "NitroModules.createHybridObject(..) expects 1 or 2 arguments, but " + std::to_string(count) +
40
40
  " were supplied!");
@@ -52,8 +52,8 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
52
52
  if (name == "hasHybridObject") {
53
53
  return jsi::Function::createFromHostFunction(
54
54
  runtime, jsi::PropNameID::forUtf8(runtime, "hasHybridObject"), 1,
55
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
56
- #if DEBUG
55
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
56
+ #ifndef NDEBUG
57
57
  if (count != 1) [[unlikely]] {
58
58
  throw jsi::JSError(runtime,
59
59
  "NitroModules.hasHybridObject(..) expects 1 argument (name), but received " + std::to_string(count) + "!");
@@ -65,8 +65,26 @@ jsi::Value NativeNitroModules::get(jsi::Runtime& runtime, const jsi::PropNameID&
65
65
  }
66
66
  if (name == "getAllHybridObjectNames") {
67
67
  return jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "getAllHybridObjectNames"), 0,
68
- [=](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args,
69
- size_t count) -> jsi::Value { return getAllHybridObjectNames(runtime); });
68
+ [this](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args,
69
+ size_t count) -> jsi::Value { return getAllHybridObjectNames(runtime); });
70
+ }
71
+ if (name == "hasNativeState") {
72
+ return jsi::Function::createFromHostFunction(
73
+ runtime, jsi::PropNameID::forUtf8(runtime, "hasNativeState"), 1,
74
+ [](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
75
+ jsi::Object object = args[0].asObject(runtime);
76
+ bool has = object.hasNativeState(runtime) && object.getNativeState(runtime) != nullptr;
77
+ return jsi::Value(has);
78
+ });
79
+ }
80
+ if (name == "removeNativeState") {
81
+ return jsi::Function::createFromHostFunction(
82
+ runtime, jsi::PropNameID::forUtf8(runtime, "removeNativeState"), 1,
83
+ [](jsi::Runtime& runtime, const jsi::Value& thisArg, const jsi::Value* args, size_t count) -> jsi::Value {
84
+ jsi::Object object = args[0].asObject(runtime);
85
+ object.setNativeState(runtime, nullptr);
86
+ return jsi::Value::undefined();
87
+ });
70
88
  }
71
89
 
72
90
  return jsi::Value::undefined();
@@ -80,7 +98,7 @@ void NativeNitroModules::install(jsi::Runtime& runtime) {
80
98
  }
81
99
 
82
100
  jsi::Value NativeNitroModules::createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName,
83
- const std::optional<jsi::Object>& args) {
101
+ const std::optional<jsi::Object>&) {
84
102
  auto name = hybridObjectName.utf8(runtime);
85
103
  // TODO: Pass args? Do we need that?
86
104
  auto hybridObject = HybridObjectRegistry::createHybridObject(name.c_str());
@@ -4,4 +4,5 @@
4
4
 
5
5
  #pragma once
6
6
 
7
+ // Forward include, because in react-native they use `.h` instead of `.hpp`
7
8
  #include "NativeNitroModules.hpp"
@@ -22,7 +22,9 @@ public:
22
22
  public:
23
23
  jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& propName) override;
24
24
 
25
+ // Setup
25
26
  void install(jsi::Runtime& runtime);
27
+ // Hybrid Objects stuff
26
28
  jsi::Value createHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName, const std::optional<jsi::Object>& args);
27
29
  jsi::Value hasHybridObject(jsi::Runtime& runtime, const jsi::String& hybridObjectName);
28
30
  jsi::Value getAllHybridObjectNames(jsi::Runtime& runtime);
@@ -71,6 +71,20 @@ public:
71
71
  return name;
72
72
  }
73
73
 
74
+ /**
75
+ * Get a friendly name of the type `T` (if possible, demangled), without any namespaces
76
+ */
77
+ template <typename T>
78
+ static inline std::string getFriendlyTypenameNoNamespace() {
79
+ std::string friendly = getFriendlyTypename<T>();
80
+ size_t lastColon = friendly.rfind(':');
81
+ if (lastColon == std::string::npos) {
82
+ // Type does not have any namespace (:), just return as is.
83
+ return friendly;
84
+ }
85
+ return friendly.substr(lastColon + 1);
86
+ }
87
+
74
88
  template <typename... Types>
75
89
  static inline std::string getFriendlyTypenames() {
76
90
  std::ostringstream stream;
@@ -0,0 +1,91 @@
1
+ //
2
+ // AnyMapHolder.hpp
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 20.08.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #include "AnyMap.hpp"
11
+
12
+ namespace margelo::nitro {
13
+
14
+ using TSharedMap = std::shared_ptr<AnyMap>;
15
+
16
+ inline AnyValue create_AnyValue() {
17
+ return AnyValue{std::monostate{}};
18
+ }
19
+ inline AnyValue create_AnyValue(bool boolValue) {
20
+ return AnyValue{boolValue};
21
+ }
22
+ inline AnyValue create_AnyValue(double doubleValue) {
23
+ return AnyValue{doubleValue};
24
+ }
25
+ inline AnyValue create_AnyValue(int64_t bigintValue) {
26
+ return AnyValue{bigintValue};
27
+ }
28
+ inline AnyValue create_AnyValue(const std::string& stringValue) {
29
+ return AnyValue{stringValue};
30
+ }
31
+ inline AnyValue create_AnyValue(const AnyArray& arrayValue) {
32
+ return AnyValue{arrayValue};
33
+ }
34
+ inline AnyValue create_AnyValue(const AnyObject& objectValue) {
35
+ return AnyValue{objectValue};
36
+ }
37
+
38
+ inline bool is_AnyValue_null(const AnyValue& value) {
39
+ return std::holds_alternative<std::monostate>(value);
40
+ }
41
+ inline bool is_AnyValue_bool(const AnyValue& value) {
42
+ return std::holds_alternative<bool>(value);
43
+ }
44
+ inline bool is_AnyValue_number(const AnyValue& value) {
45
+ return std::holds_alternative<double>(value);
46
+ }
47
+ inline bool is_AnyValue_bigint(const AnyValue& value) {
48
+ return std::holds_alternative<int64_t>(value);
49
+ }
50
+ inline bool is_AnyValue_string(const AnyValue& value) {
51
+ return std::holds_alternative<std::string>(value);
52
+ }
53
+ inline bool is_AnyValue_AnyArray(const AnyValue& value) {
54
+ return std::holds_alternative<AnyArray>(value);
55
+ }
56
+ inline bool is_AnyValue_AnyObject(const AnyValue& value) {
57
+ return std::holds_alternative<AnyObject>(value);
58
+ }
59
+
60
+ inline std::monostate get_AnyValue_null(const AnyValue& value) {
61
+ return std::get<std::monostate>(value);
62
+ }
63
+ inline bool get_AnyValue_bool(const AnyValue& value) {
64
+ return std::get<bool>(value);
65
+ }
66
+ inline double get_AnyValue_number(const AnyValue& value) {
67
+ return std::get<double>(value);
68
+ }
69
+ inline int64_t get_AnyValue_bigint(const AnyValue& value) {
70
+ return std::get<int64_t>(value);
71
+ }
72
+ inline std::string get_AnyValue_string(const AnyValue& value) {
73
+ return std::get<std::string>(value);
74
+ }
75
+ inline AnyArray get_AnyValue_AnyArray(const AnyValue& value) {
76
+ return std::get<AnyArray>(value);
77
+ }
78
+ inline AnyObject get_AnyValue_AnyObject(const AnyValue& value) {
79
+ return std::get<AnyObject>(value);
80
+ }
81
+
82
+ inline std::vector<std::string> getAnyObjectKeys(const AnyObject& object) {
83
+ std::vector<std::string> keys;
84
+ keys.reserve(object.size());
85
+ for (const auto& entry : object) {
86
+ keys.push_back(entry.first);
87
+ }
88
+ return keys;
89
+ }
90
+
91
+ } // namespace margelo::nitro
@@ -0,0 +1,316 @@
1
+ //
2
+ // AnyMapHolder.swift
3
+ // NitroModules
4
+ //
5
+ // Created by Marc Rousavy on 20.08.24.
6
+ //
7
+
8
+ import Foundation
9
+
10
+ /**
11
+ * Represents any value representable by the `AnyMap`.
12
+ * Note: Arrays are currently not implemented due to a Swift compiler bug https://github.com/swiftlang/swift/issues/75994
13
+ */
14
+ public enum AnyValue {
15
+ case null
16
+ case number(Double)
17
+ case bool(Bool)
18
+ case bigint(Int64)
19
+ case string(String)
20
+ case object(Dictionary<String, AnyValue>)
21
+
22
+ static func create(_ value: margelo.nitro.AnyValue) -> AnyValue {
23
+ if margelo.nitro.is_AnyValue_null(value) {
24
+ return .null
25
+ } else if margelo.nitro.is_AnyValue_bool(value) {
26
+ return .bool(margelo.nitro.get_AnyValue_bool(value))
27
+ } else if margelo.nitro.is_AnyValue_number(value) {
28
+ return .number(margelo.nitro.get_AnyValue_number(value))
29
+ } else if margelo.nitro.is_AnyValue_bigint(value) {
30
+ return .bigint(margelo.nitro.get_AnyValue_bigint(value))
31
+ } else if margelo.nitro.is_AnyValue_string(value) {
32
+ return .string(margelo.nitro.get_AnyValue_string(value).toSwift())
33
+ } else if margelo.nitro.is_AnyValue_AnyObject(value) {
34
+ return .object(margelo.nitro.get_AnyValue_AnyObject(value).toSwift())
35
+ } else {
36
+ fatalError("AnyValue has unknown type!")
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Represents an `AnyMap` that can be passed to Swift.
43
+ */
44
+ public class AnyMapHolder {
45
+ let _cppPart: margelo.nitro.TSharedMap
46
+
47
+ public var cppPart: margelo.nitro.TSharedMap {
48
+ return _cppPart
49
+ }
50
+
51
+ public init() {
52
+ _cppPart = margelo.nitro.AnyMap.make()
53
+ }
54
+
55
+ public init(withPreallocatedSize size: Int) {
56
+ _cppPart = margelo.nitro.AnyMap.make(size)
57
+ }
58
+
59
+ public init(withCppPart cppPart: margelo.nitro.TSharedMap) {
60
+ _cppPart = cppPart
61
+ }
62
+
63
+ // pragma MARK: Common Operations
64
+
65
+ /**
66
+ * Returns whether the given key exists in the map.
67
+ */
68
+ public func contains(key: String) -> Bool {
69
+ return _cppPart.pointee.contains(std.string(key))
70
+ }
71
+
72
+ /**
73
+ * Removes the given key from the map.
74
+ */
75
+ public func remove(key: String) {
76
+ _cppPart.pointee.remove(std.string(key))
77
+ }
78
+
79
+ /**
80
+ * Removes all keys in this map.
81
+ */
82
+ public func clear() {
83
+ _cppPart.pointee.clear()
84
+ }
85
+
86
+ // pragma MARK: Getters
87
+
88
+ /**
89
+ * Gets the double value at the given key.
90
+ * If no value exists at the given key, or if it is not a double,
91
+ * this function throws.
92
+ */
93
+ public func getDouble(key: String) -> Double {
94
+ return _cppPart.pointee.getDouble(std.string(key))
95
+ }
96
+
97
+ /**
98
+ * Gets the double value at the given key.
99
+ * If no value exists at the given key, or if it is not a double,
100
+ * this function throws.
101
+ */
102
+ public func getBoolean(key: String) -> Bool {
103
+ return _cppPart.pointee.getBoolean(std.string(key))
104
+ }
105
+
106
+ /**
107
+ * Gets the double value at the given key.
108
+ * If no value exists at the given key, or if it is not a double,
109
+ * this function throws.
110
+ */
111
+ public func getBigInt(key: String) -> Int64 {
112
+ return _cppPart.pointee.getBigInt(std.string(key))
113
+ }
114
+
115
+ /**
116
+ * Gets the double value at the given key.
117
+ * If no value exists at the given key, or if it is not a double,
118
+ * this function throws.
119
+ */
120
+ public func getString(key: String) -> String {
121
+ let value = _cppPart.pointee.getString(std.string(key))
122
+ return String(value)
123
+ }
124
+
125
+ /**
126
+ * Gets the double value at the given key.
127
+ * If no value exists at the given key, or if it is not a double,
128
+ * this function throws.
129
+ */
130
+ public func getObject(key: String) -> Dictionary<String, AnyValue> {
131
+ let value = _cppPart.pointee.getObject(std.string(key))
132
+ return value.toSwift()
133
+ }
134
+
135
+ // pragma MARK: Setters
136
+
137
+ /**
138
+ * Set the given key to `null`.
139
+ */
140
+ public func setNull(key: String) {
141
+ _cppPart.pointee.setNull(std.string(key))
142
+ }
143
+
144
+ /**
145
+ * Set the given key to the given double value.
146
+ */
147
+ public func setDouble(key: String, value: Double) {
148
+ _cppPart.pointee.setDouble(std.string(key), value)
149
+ }
150
+
151
+ /**
152
+ * Set the given key to the given boolean value.
153
+ */
154
+ public func setBoolean(key: String, value: Bool) {
155
+ _cppPart.pointee.setBoolean(std.string(key), value)
156
+ }
157
+
158
+ /**
159
+ * Set the given key to the given bigint value.
160
+ */
161
+ public func setBigInt(key: String, value: Int64) {
162
+ _cppPart.pointee.setBigInt(std.string(key), value)
163
+ }
164
+
165
+ /**
166
+ * Set the given key to the given string value.
167
+ */
168
+ public func setString(key: String, value: String) {
169
+ _cppPart.pointee.setString(std.string(key), std.string(value))
170
+ }
171
+
172
+ /**
173
+ * Set the given key to the given object value.
174
+ */
175
+ public func setObject(key: String, value: Dictionary<String, AnyValue>) {
176
+ _cppPart.pointee.setObject(std.string(key), margelo.nitro.AnyObject.create(value))
177
+ }
178
+
179
+ // pragma MARK: Is Getters
180
+
181
+ /**
182
+ * Gets whether the given `key` is holding a null value, or not.
183
+ */
184
+ public func isNull(key: String) -> Bool {
185
+ return _cppPart.pointee.isNull(std.string(key))
186
+ }
187
+
188
+ /**
189
+ * Gets whether the given `key` is holding a double value, or not.
190
+ */
191
+ public func isDouble(key: String) -> Bool {
192
+ return _cppPart.pointee.isDouble(std.string(key))
193
+ }
194
+
195
+ /**
196
+ * Gets whether the given `key` is holding a boolean value, or not.
197
+ */
198
+ public func isBool(key: String) -> Bool {
199
+ return _cppPart.pointee.isBoolean(std.string(key))
200
+ }
201
+
202
+ /**
203
+ * Gets whether the given `key` is holding a bigint value, or not.
204
+ */
205
+ public func isBigInt(key: String) -> Bool {
206
+ return _cppPart.pointee.isBigInt(std.string(key))
207
+ }
208
+
209
+ /**
210
+ * Gets whether the given `key` is holding a string value, or not.
211
+ */
212
+ public func isString(key: String) -> Bool {
213
+ return _cppPart.pointee.isString(std.string(key))
214
+ }
215
+
216
+ /**
217
+ * Gets whether the given `key` is holding a object value, or not.
218
+ */
219
+ public func isObject(key: String) -> Bool {
220
+ return _cppPart.pointee.isObject(std.string(key))
221
+ }
222
+ }
223
+
224
+ // pragma MARK: margelo.nitro.AnyValue extension
225
+
226
+ extension margelo.nitro.AnyValue {
227
+ static func create(_ value: AnyValue) -> margelo.nitro.AnyValue {
228
+ switch value {
229
+ case .null:
230
+ return create()
231
+ case .bool(let bool):
232
+ return create(bool)
233
+ case .number(let number):
234
+ return create(number)
235
+ case .bigint(let bigint):
236
+ return create(bigint)
237
+ case .string(let string):
238
+ return create(string)
239
+ case .object(let object):
240
+ return create(object)
241
+ }
242
+ }
243
+ static func create() -> margelo.nitro.AnyValue {
244
+ return margelo.nitro.create_AnyValue()
245
+ }
246
+ static func create(_ value: Bool) -> margelo.nitro.AnyValue {
247
+ return margelo.nitro.create_AnyValue(value)
248
+ }
249
+ static func create(_ value: Double) -> margelo.nitro.AnyValue {
250
+ return margelo.nitro.create_AnyValue(value)
251
+ }
252
+ static func create(_ value: Int64) -> margelo.nitro.AnyValue {
253
+ return margelo.nitro.create_AnyValue(value)
254
+ }
255
+ static func create(_ value: String) -> margelo.nitro.AnyValue {
256
+ return margelo.nitro.create_AnyValue(std.string(value))
257
+ }
258
+ static func create(_ value: [AnyValue]) -> margelo.nitro.AnyValue {
259
+ return margelo.nitro.create_AnyValue(margelo.nitro.AnyArray.create(value))
260
+ }
261
+ static func create(_ value: Dictionary<String, AnyValue>) -> margelo.nitro.AnyValue {
262
+ return margelo.nitro.create_AnyValue(margelo.nitro.AnyObject.create(value))
263
+ }
264
+ }
265
+
266
+ // pragma MARK: std.string extension
267
+
268
+ extension std.string {
269
+ func toSwift() -> String {
270
+ return String(self)
271
+ }
272
+ }
273
+
274
+ // pragma MARK: margelo.nitro.AnyArray extension
275
+
276
+ extension margelo.nitro.AnyArray {
277
+ static func create(_ array: [AnyValue]) -> margelo.nitro.AnyArray {
278
+ var vector = margelo.nitro.AnyArray()
279
+ vector.reserve(array.count)
280
+ for value in array {
281
+ vector.push_back(margelo.nitro.AnyValue.create(value))
282
+ }
283
+ return vector
284
+ }
285
+
286
+ func toSwift() -> [AnyValue] {
287
+ var array: [AnyValue] = []
288
+ array.reserveCapacity(self.size())
289
+ for value in self {
290
+ array.append(AnyValue.create(value))
291
+ }
292
+ return array
293
+ }
294
+ }
295
+
296
+ // pragma MARK: margelo.nitro.AnyObject extension
297
+
298
+ extension margelo.nitro.AnyObject {
299
+ static func create(_ dictionary: Dictionary<String, AnyValue>) -> margelo.nitro.AnyObject {
300
+ var object = margelo.nitro.AnyObject()
301
+ object.reserve(dictionary.count)
302
+ for (key, value) in dictionary {
303
+ object[std.string(key)] = margelo.nitro.AnyValue.create(value)
304
+ }
305
+ return object
306
+ }
307
+
308
+ func toSwift() -> Dictionary<String, AnyValue> {
309
+ let keys = margelo.nitro.getAnyObjectKeys(self)
310
+ var dictionary = Dictionary<String, AnyValue>(minimumCapacity: keys.size())
311
+ for key in keys {
312
+
313
+ }
314
+ return dictionary
315
+ }
316
+ }
@@ -8,8 +8,9 @@
8
8
  #pragma once
9
9
 
10
10
  #include "ArrayBuffer.hpp"
11
- #include "NitroDefines.hpp"
11
+ #include "SwiftClosure.hpp"
12
12
  #include <memory>
13
+ #include <swift/bridging>
13
14
 
14
15
  namespace margelo::nitro {
15
16
 
@@ -32,10 +33,11 @@ public:
32
33
  * Create a new `NativeArrayBuffer` that wraps the given data of the given size, without copying it.
33
34
  *
34
35
  * Once the `ArrayBuffer` is no longer in use, the given `deleteFunc` will be called with the given `deleteFuncContext`
35
- * as an argument. The caller is responsible for deleting `data` (and `deleteFuncContext`) once this is called.
36
+ * as an argument. The caller is responsible for deleting `data` once this is called.
36
37
  */
37
- static ArrayBufferHolder makeBuffer(uint8_t* data, size_t size, DeleteFn deleteFunc, void* deleteFuncContext) {
38
- auto arrayBuffer = ArrayBuffer::makeBuffer(data, size, deleteFunc, deleteFuncContext);
38
+ static ArrayBufferHolder makeBuffer(uint8_t* data, size_t size, SwiftClosure destroy) {
39
+ std::function<void()> deleteFunc = destroy.getFunction();
40
+ auto arrayBuffer = ArrayBuffer::makeBuffer(data, size, std::move(deleteFunc));
39
41
  return ArrayBufferHolder(arrayBuffer);
40
42
  }
41
43
 
@@ -53,7 +55,16 @@ public:
53
55
  return _arrayBuffer->size();
54
56
  }
55
57
 
56
- bool isOwner() const SWIFT_COMPUTED_PROPERTY {
58
+ /**
59
+ * Whether the underlying `ArrayBuffer` actually owns the data it points to, or not.
60
+ *
61
+ * - If an `ArrayBuffer` owns the data, it is likely an ArrayBuffer created on the native side (C++/Swift).
62
+ * This means the `ArrayBuffer` is safe to access as long as you have a reference to it, and cannot be deleted otherwise.
63
+ * - If an `ArrayBuffer` doesn't own the data, it is likely an ArrayBuffer coming from JS.
64
+ * This means the `ArrayBuffer` is **NOT** safe to access outside of the synchronous function's scope.
65
+ * If you plan on hopping do a different Thread, or storing a long-lived reference to it, make sure to **copy** the data.
66
+ */
67
+ bool getIsOwner() const SWIFT_COMPUTED_PROPERTY {
57
68
  return _arrayBuffer->isOwner();
58
69
  }
59
70
 
@@ -1,5 +1,5 @@
1
1
  //
2
- // ArrayBuffer.swift
2
+ // ArrayBufferHolder.swift
3
3
  // NitroModules
4
4
  //
5
5
  // Created by Marc Rousavy on 17.07.24.
@@ -7,6 +7,12 @@
7
7
 
8
8
  import Foundation
9
9
 
10
+ /**
11
+ * Holds instances of `std::shared_ptr<ArrayBuffer>`, which can be passed
12
+ * between native and JS **without copy**.
13
+ *
14
+ * See `data`, `size` and `isOwning`.
15
+ */
10
16
  public typealias ArrayBufferHolder = margelo.nitro.ArrayBufferHolder
11
17
 
12
18
  public extension ArrayBufferHolder {
@@ -16,22 +22,13 @@ public extension ArrayBufferHolder {
16
22
  * When the `ArrayBuffer` is no longer used, `onDelete` will be called, in which
17
23
  * you as a caller are responsible for deleting `data`.
18
24
  */
19
- static func wrap(wrappingDataWithoutCopy data: UnsafeMutablePointer<UInt8>,
25
+ static func wrap(dataWithoutCopy data: UnsafeMutablePointer<UInt8>,
20
26
  size: Int,
21
27
  onDelete delete: @escaping () -> Void) -> ArrayBufferHolder {
22
28
  // Convert escaping Swift closure to a `void*`
23
- let wrapper = ClosureWrapper(closure: delete)
24
- let wrappedClosure = Unmanaged.passRetained(wrapper).toOpaque()
25
-
26
- return ArrayBufferHolder.makeBuffer(data, size, { context in
27
- guard let context else {
28
- fatalError("Context was null, even though we created one!")
29
- }
30
- // Convert `void*` to a Swift closure
31
- let closure = Unmanaged<ClosureWrapper>.fromOpaque(context).takeRetainedValue()
32
- // Call it (deleteFunc)
33
- closure.invoke()
34
- }, wrappedClosure)
29
+ let swiftClosure = SwiftClosure(wrappingClosure: delete)
30
+ // Create ArrayBufferHolder with our wrapped Swift closure to make it callable as a C-function pointer
31
+ return ArrayBufferHolder.makeBuffer(data, size, swiftClosure)
35
32
  }
36
33
 
37
34
  /**
@@ -44,8 +41,9 @@ public extension ArrayBufferHolder {
44
41
  data.initialize(repeating: 0, count: size)
45
42
  }
46
43
 
47
- return ArrayBufferHolder.makeBuffer(data, size, { data in
48
- data?.deallocate()
49
- }, data)
44
+ let deleteFunc = SwiftClosure {
45
+ data.deallocate()
46
+ }
47
+ return ArrayBufferHolder.makeBuffer(data, size, deleteFunc)
50
48
  }
51
49
  }
@@ -32,15 +32,15 @@ public:
32
32
  template <typename THybridObject, typename TSwiftPart>
33
33
  static inline std::shared_ptr<THybridObject> getOrCreate(TSwiftPart swiftPart) noexcept {
34
34
  auto hybridContext = swiftPart.getHybridContext();
35
- auto hybridObject = std::static_pointer_cast<THybridObject>(hybridContext.cppPart.lock());
35
+ auto hybridObject = std::dynamic_pointer_cast<THybridObject>(hybridContext.cppPart.lock());
36
36
  if (hybridObject != nullptr) [[likely]] {
37
37
  // Fast path - an existing HybridObject is still in cache! (HybridContext)
38
38
  return hybridObject;
39
39
  }
40
40
 
41
41
  // Slow path - we need to create a new HybridObject that wraps our Swift implementation.
42
- Logger::log(TAG, "Creating new HybridObject<%s> for %s...", TypeInfo::getFriendlyTypename<THybridObject>(),
43
- TypeInfo::getFriendlyTypename<TSwiftPart>());
42
+ Logger::log(LogLevel::Info, TAG, "Creating new HybridObject<%s> for %s...", TypeInfo::getFriendlyTypename<THybridObject>().c_str(),
43
+ TypeInfo::getFriendlyTypename<TSwiftPart>().c_str());
44
44
  hybridObject = std::make_shared<THybridObject>(std::forward<decltype(swiftPart)>(swiftPart));
45
45
  hybridContext.cppPart = hybridObject;
46
46
  swiftPart.setHybridContext(hybridContext);