react-native-nitro-modules 0.31.10 → 0.32.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.
- package/NitroModules.podspec +2 -1
- package/android/build.gradle +1 -1
- package/android/src/main/cpp/core/JAnyMap.cpp +218 -0
- package/android/src/main/cpp/core/JAnyMap.hpp +46 -56
- package/android/src/main/cpp/platform/NitroLogger.cpp +3 -1
- package/android/src/main/java/com/margelo/nitro/core/AnyMap.kt +22 -24
- package/android/src/main/java/com/margelo/nitro/core/ArrayBuffer.kt +2 -2
- package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +3 -3
- package/cpp/core/AnyMap.cpp +1 -1
- package/cpp/core/AnyMap.hpp +3 -3
- package/cpp/core/ArrayBuffer.hpp +3 -3
- package/cpp/core/HybridObject.cpp +10 -10
- package/cpp/core/HybridObject.hpp +3 -3
- package/cpp/entrypoint/HybridNitroModulesProxy.cpp +1 -1
- package/cpp/entrypoint/InstallNitro.cpp +2 -2
- package/cpp/jsi/JSICache.cpp +10 -5
- package/cpp/jsi/JSICache.hpp +6 -0
- package/cpp/jsi/JSIConverter+AnyMap.hpp +4 -3
- package/cpp/jsi/JSIConverter+ArrayBuffer.hpp +2 -2
- package/cpp/jsi/JSIConverter+Date.hpp +8 -10
- package/cpp/jsi/JSIConverter+Exception.hpp +5 -5
- package/cpp/jsi/JSIConverter+Function.hpp +4 -1
- package/cpp/jsi/JSIConverter+NativeState.hpp +1 -1
- package/cpp/jsi/JSIConverter+Promise.hpp +8 -14
- package/cpp/jsi/JSIConverter+UnorderedMap.hpp +2 -1
- package/cpp/jsi/JSIHelpers.hpp +1 -1
- package/cpp/platform/NitroLogger.hpp +3 -1
- package/cpp/prototype/HybridObjectPrototype.cpp +28 -28
- package/cpp/prototype/PrototypeChain.hpp +1 -1
- package/cpp/registry/HybridObjectRegistry.hpp +1 -1
- package/cpp/threading/CallInvokerDispatcher.hpp +1 -1
- package/cpp/threading/Dispatcher.cpp +5 -5
- package/cpp/utils/BorrowingReference.hpp +6 -6
- package/cpp/utils/CommonGlobals.cpp +215 -0
- package/cpp/utils/CommonGlobals.hpp +158 -0
- package/cpp/utils/JSCallback.hpp +1 -1
- package/cpp/utils/NitroDefines.hpp +1 -1
- package/cpp/utils/PropNameIDCache.cpp +38 -0
- package/cpp/utils/PropNameIDCache.hpp +44 -0
- package/cpp/utils/{WeakReference+Owning.hpp → WeakReference+Borrowing.hpp} +1 -1
- package/cpp/utils/WeakReference.hpp +1 -1
- package/ios/core/HybridObject.swift +1 -1
- package/ios/platform/NitroLogger.cpp +37 -0
- package/ios/platform/ThreadUtils.cpp +43 -0
- package/ios/utils/SwiftClosure.swift +1 -1
- package/package.json +1 -2
- package/cpp/utils/ObjectUtils.cpp +0 -172
- package/cpp/utils/ObjectUtils.hpp +0 -94
- package/ios/platform/NitroLogger.mm +0 -36
- package/ios/platform/ThreadUtils.mm +0 -46
package/NitroModules.podspec
CHANGED
|
@@ -48,6 +48,7 @@ Pod::Spec.new do |s|
|
|
|
48
48
|
"cpp/utils/FastVectorCopy.hpp",
|
|
49
49
|
"cpp/utils/NitroHash.hpp",
|
|
50
50
|
"cpp/utils/NitroDefines.hpp",
|
|
51
|
+
"cpp/utils/PropNameIDCache.hpp",
|
|
51
52
|
"cpp/views/CachedProp.hpp",
|
|
52
53
|
# Public iOS-specific headers that will be exposed in modulemap (for Swift)
|
|
53
54
|
"ios/core/ArrayBufferHolder.hpp",
|
|
@@ -63,7 +64,7 @@ Pod::Spec.new do |s|
|
|
|
63
64
|
xcconfig = {
|
|
64
65
|
# Use C++ 20
|
|
65
66
|
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
|
|
66
|
-
# Enables C++ <-> Swift interop (by default
|
|
67
|
+
# Enables C++ <-> Swift interop (by default its only ObjC)
|
|
67
68
|
"SWIFT_OBJC_INTEROP_MODE" => "objcxx",
|
|
68
69
|
# Enables stricter modular headers
|
|
69
70
|
"DEFINES_MODULE" => "YES",
|
package/android/build.gradle
CHANGED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
//
|
|
2
|
+
// JAnyMap.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.07.24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "JAnyMap.hpp"
|
|
9
|
+
|
|
10
|
+
namespace margelo::nitro {
|
|
11
|
+
|
|
12
|
+
using namespace facebook;
|
|
13
|
+
|
|
14
|
+
jni::local_ref<jni::JArrayClass<jni::JString>> JAnyMap::getAllKeys() {
|
|
15
|
+
auto& map = _map->getMap();
|
|
16
|
+
auto array = jni::JArrayClass<jni::JString>::newArray(map.size());
|
|
17
|
+
size_t index = 0;
|
|
18
|
+
for (const auto& pair : map) {
|
|
19
|
+
auto jKey = jni::make_jstring(pair.first);
|
|
20
|
+
array->setElement(index, *jKey);
|
|
21
|
+
index++;
|
|
22
|
+
}
|
|
23
|
+
return array;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
jni::local_ref<JAnyArray> JAnyMap::getAnyArray(const std::string& key) {
|
|
27
|
+
const auto& vector = _map->getArray(key);
|
|
28
|
+
auto javaArray = jni::JArrayClass<JAnyValue::javaobject>::newArray(vector.size());
|
|
29
|
+
for (size_t i = 0; i < vector.size(); i++) {
|
|
30
|
+
auto value = JAnyValue::create(vector[i]);
|
|
31
|
+
javaArray->setElement(i, value.get());
|
|
32
|
+
}
|
|
33
|
+
return javaArray;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
jni::local_ref<JAnyObject> JAnyMap::getAnyObject(const std::string& key) {
|
|
37
|
+
const auto& map = _map->getObject(key);
|
|
38
|
+
auto javaMap = jni::JHashMap<jni::JString, JAnyValue::javaobject>::create(map.size());
|
|
39
|
+
for (const auto& entry : map) {
|
|
40
|
+
auto string = jni::make_jstring(entry.first);
|
|
41
|
+
auto value = JAnyValue::create(entry.second);
|
|
42
|
+
javaMap->put(string, value);
|
|
43
|
+
}
|
|
44
|
+
return javaMap;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
jni::local_ref<JAnyValue::javaobject> JAnyMap::getAnyValue(const std::string& key) {
|
|
48
|
+
const auto& any = _map->getAny(key);
|
|
49
|
+
return JAnyValue::create(any);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void JAnyMap::setAnyArray(const std::string& key, jni::alias_ref<JAnyArray> value) {
|
|
53
|
+
std::vector<AnyValue> vector;
|
|
54
|
+
size_t size = value->size();
|
|
55
|
+
vector.reserve(size);
|
|
56
|
+
for (size_t i = 0; i < size; i++) {
|
|
57
|
+
auto anyValue = value->getElement(i);
|
|
58
|
+
vector.push_back(anyValue->cthis()->getValue());
|
|
59
|
+
}
|
|
60
|
+
_map->setArray(key, vector);
|
|
61
|
+
}
|
|
62
|
+
void JAnyMap::setAnyObject(const std::string& key, const jni::alias_ref<JAnyObject>& value) {
|
|
63
|
+
std::unordered_map<std::string, AnyValue> map;
|
|
64
|
+
map.reserve(value->size());
|
|
65
|
+
for (const auto& entry : *value) {
|
|
66
|
+
map.emplace(entry.first->toStdString(), entry.second->cthis()->getValue());
|
|
67
|
+
}
|
|
68
|
+
_map->setObject(key, map);
|
|
69
|
+
}
|
|
70
|
+
void JAnyMap::setAnyValue(const std::string& key, const jni::alias_ref<JAnyValue::javaobject>& value) {
|
|
71
|
+
_map->setAny(key, value->cthis()->getValue());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
jni::local_ref<jni::JHashMap<jni::JString, jni::JObject>> JAnyMap::toHashMap() {
|
|
75
|
+
const auto& map = _map->getMap();
|
|
76
|
+
auto javaMap = jni::JHashMap<jni::JString, jni::JObject>::create(map.size());
|
|
77
|
+
for (const auto& [key, value] : map) {
|
|
78
|
+
javaMap->put(jni::make_jstring(key), anyValueToJObject(value));
|
|
79
|
+
}
|
|
80
|
+
return javaMap;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
jni::local_ref<jni::JObject> JAnyMap::anyValueToJObject(const AnyValue& value) {
|
|
84
|
+
if (std::holds_alternative<NullType>(value)) {
|
|
85
|
+
return nullptr;
|
|
86
|
+
} else if (std::holds_alternative<double>(value)) {
|
|
87
|
+
return jni::JDouble::valueOf(std::get<double>(value));
|
|
88
|
+
} else if (std::holds_alternative<bool>(value)) {
|
|
89
|
+
return jni::JBoolean::valueOf(std::get<bool>(value));
|
|
90
|
+
} else if (std::holds_alternative<int64_t>(value)) {
|
|
91
|
+
return jni::JLong::valueOf(std::get<int64_t>(value));
|
|
92
|
+
} else if (std::holds_alternative<std::string>(value)) {
|
|
93
|
+
return jni::make_jstring(std::get<std::string>(value));
|
|
94
|
+
} else if (std::holds_alternative<AnyArray>(value)) {
|
|
95
|
+
return jni::static_ref_cast<jni::JObject>(anyArrayToJList(std::get<AnyArray>(value)));
|
|
96
|
+
} else if (std::holds_alternative<AnyObject>(value)) {
|
|
97
|
+
return jni::static_ref_cast<jni::JObject>(anyObjectToJHashMap(std::get<AnyObject>(value)));
|
|
98
|
+
}
|
|
99
|
+
return nullptr;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
jni::local_ref<jni::JArrayList<jni::JObject>> JAnyMap::anyArrayToJList(const AnyArray& array) {
|
|
103
|
+
auto jList = jni::JArrayList<jni::JObject>::create(static_cast<int>(array.size()));
|
|
104
|
+
for (const auto& item : array) {
|
|
105
|
+
jList->add(anyValueToJObject(item));
|
|
106
|
+
}
|
|
107
|
+
return jList;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
jni::local_ref<jni::JHashMap<jni::JString, jni::JObject>> JAnyMap::anyObjectToJHashMap(const AnyObject& object) {
|
|
111
|
+
auto jMap = jni::JHashMap<jni::JString, jni::JObject>::create(object.size());
|
|
112
|
+
for (const auto& [key, val] : object) {
|
|
113
|
+
jMap->put(jni::make_jstring(key), anyValueToJObject(val));
|
|
114
|
+
}
|
|
115
|
+
return jMap;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
AnyValue JAnyMap::jObjectToAnyValue(jni::alias_ref<jni::JObject> jObject) {
|
|
119
|
+
if (!jObject) {
|
|
120
|
+
return nitro::null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Check for Double
|
|
124
|
+
if (jObject->isInstanceOf(jni::JDouble::javaClassStatic())) {
|
|
125
|
+
auto jDouble = jni::static_ref_cast<jni::JDouble>(jObject);
|
|
126
|
+
return jDouble->doubleValue();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Check for Float
|
|
130
|
+
if (jObject->isInstanceOf(jni::JFloat::javaClassStatic())) {
|
|
131
|
+
auto jFloat = jni::static_ref_cast<jni::JFloat>(jObject);
|
|
132
|
+
return static_cast<double>(jFloat->floatValue());
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Check for Integer
|
|
136
|
+
if (jObject->isInstanceOf(jni::JInteger::javaClassStatic())) {
|
|
137
|
+
auto jInt = jni::static_ref_cast<jni::JInteger>(jObject);
|
|
138
|
+
return static_cast<double>(jInt->intValue());
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Check for Boolean
|
|
142
|
+
if (jObject->isInstanceOf(jni::JBoolean::javaClassStatic())) {
|
|
143
|
+
auto jBool = jni::static_ref_cast<jni::JBoolean>(jObject);
|
|
144
|
+
return jBool->booleanValue();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Check for Long (bigint)
|
|
148
|
+
if (jObject->isInstanceOf(jni::JLong::javaClassStatic())) {
|
|
149
|
+
auto jLong = jni::static_ref_cast<jni::JLong>(jObject);
|
|
150
|
+
return jLong->longValue();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Check for String
|
|
154
|
+
if (jObject->isInstanceOf(jni::JString::javaClassStatic())) {
|
|
155
|
+
auto jString = jni::static_ref_cast<jni::JString>(jObject);
|
|
156
|
+
return jString->toStdString();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Check for List (array)
|
|
160
|
+
if (jObject->isInstanceOf(jni::JList<jni::JObject>::javaClassStatic())) {
|
|
161
|
+
auto jList = jni::static_ref_cast<jni::JList<jni::JObject>>(jObject);
|
|
162
|
+
return jListToAnyArray(jList);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Check for Map (object)
|
|
166
|
+
if (jObject->isInstanceOf(jni::JMap<jni::JString, jni::JObject>::javaClassStatic())) {
|
|
167
|
+
auto jMap = jni::static_ref_cast<jni::JMap<jni::JString, jni::JObject>>(jObject);
|
|
168
|
+
return jHashMapToAnyObject(jMap);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
throw std::runtime_error("Cannot convert JObject to AnyValue - unsupported type!");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
AnyArray JAnyMap::jListToAnyArray(jni::alias_ref<jni::JList<jni::JObject>> jList) {
|
|
175
|
+
AnyArray array;
|
|
176
|
+
array.reserve(jList->size());
|
|
177
|
+
for (const auto& item : *jList) {
|
|
178
|
+
array.push_back(jObjectToAnyValue(item));
|
|
179
|
+
}
|
|
180
|
+
return array;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
AnyObject JAnyMap::jHashMapToAnyObject(jni::alias_ref<jni::JMap<jni::JString, jni::JObject>> jMap) {
|
|
184
|
+
AnyObject object;
|
|
185
|
+
object.reserve(jMap->size());
|
|
186
|
+
for (const auto& entry : *jMap) {
|
|
187
|
+
object.emplace(entry.first->toStdString(), jObjectToAnyValue(entry.second));
|
|
188
|
+
}
|
|
189
|
+
return object;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
jni::local_ref<JAnyMap::javaobject> JAnyMap::fromMap(jni::alias_ref<jclass>, jni::alias_ref<jni::JMap<jni::JString, jni::JObject>> javaMap,
|
|
193
|
+
bool ignoreIncompatible) {
|
|
194
|
+
size_t size = javaMap->size();
|
|
195
|
+
jni::local_ref<JAnyMap::javaobject> anyMap = JAnyMap::create(size);
|
|
196
|
+
|
|
197
|
+
auto& map = anyMap->cthis()->_map->getMap();
|
|
198
|
+
|
|
199
|
+
// Bulk convert all entries from Java to C++
|
|
200
|
+
for (const auto& entry : *javaMap) {
|
|
201
|
+
try {
|
|
202
|
+
std::string key = entry.first->toStdString();
|
|
203
|
+
AnyValue value = jObjectToAnyValue(entry.second);
|
|
204
|
+
map.emplace(std::move(key), std::move(value));
|
|
205
|
+
} catch (...) {
|
|
206
|
+
if (ignoreIncompatible) {
|
|
207
|
+
// encountered an incompatible key. Ignore it.
|
|
208
|
+
} else {
|
|
209
|
+
// encountered an incompatible key - we now throw!
|
|
210
|
+
throw;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return anyMap;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
} // namespace margelo::nitro
|
|
@@ -41,6 +41,18 @@ public:
|
|
|
41
41
|
static jni::local_ref<JAnyMap::javaobject> create(const std::shared_ptr<AnyMap>& map) {
|
|
42
42
|
return newObjectCxxArgs(map);
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a new `JAnyMap` from the given preallocated size.
|
|
46
|
+
*/
|
|
47
|
+
static jni::local_ref<JAnyMap::javaobject> create(int preallocatedSize) {
|
|
48
|
+
return newObjectCxxArgs(preallocatedSize);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create a new empty `JAnyMap`.
|
|
52
|
+
*/
|
|
53
|
+
static jni::local_ref<JAnyMap::javaobject> create() {
|
|
54
|
+
return newObjectCxxArgs();
|
|
55
|
+
}
|
|
44
56
|
|
|
45
57
|
private:
|
|
46
58
|
JAnyMap() {
|
|
@@ -61,17 +73,7 @@ protected:
|
|
|
61
73
|
void clear() {
|
|
62
74
|
_map->clear();
|
|
63
75
|
}
|
|
64
|
-
jni::local_ref<jni::JArrayClass<jni::JString>> getAllKeys()
|
|
65
|
-
auto& map = _map->getMap();
|
|
66
|
-
auto array = jni::JArrayClass<jni::JString>::newArray(map.size());
|
|
67
|
-
size_t index = 0;
|
|
68
|
-
for (const auto& pair : map) {
|
|
69
|
-
auto jKey = jni::make_jstring(pair.first);
|
|
70
|
-
array->setElement(index, *jKey);
|
|
71
|
-
index++;
|
|
72
|
-
}
|
|
73
|
-
return array;
|
|
74
|
-
}
|
|
76
|
+
jni::local_ref<jni::JArrayClass<jni::JString>> getAllKeys();
|
|
75
77
|
|
|
76
78
|
protected:
|
|
77
79
|
bool isNull(const std::string& key) {
|
|
@@ -109,29 +111,9 @@ protected:
|
|
|
109
111
|
std::string getString(const std::string& key) {
|
|
110
112
|
return _map->getString(key);
|
|
111
113
|
}
|
|
112
|
-
jni::local_ref<JAnyArray> getAnyArray(const std::string& key)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
for (size_t i = 0; i < vector.size(); i++) {
|
|
116
|
-
auto value = JAnyValue::create(vector[i]);
|
|
117
|
-
javaArray->setElement(i, value.get());
|
|
118
|
-
}
|
|
119
|
-
return javaArray;
|
|
120
|
-
}
|
|
121
|
-
jni::local_ref<JAnyObject> getAnyObject(const std::string& key) {
|
|
122
|
-
const auto& map = _map->getObject(key);
|
|
123
|
-
auto javaMap = jni::JHashMap<jni::JString, JAnyValue::javaobject>::create(map.size());
|
|
124
|
-
for (const auto& entry : map) {
|
|
125
|
-
auto string = jni::make_jstring(entry.first);
|
|
126
|
-
auto value = JAnyValue::create(entry.second);
|
|
127
|
-
javaMap->put(string, value);
|
|
128
|
-
}
|
|
129
|
-
return javaMap;
|
|
130
|
-
}
|
|
131
|
-
jni::local_ref<JAnyValue::javaobject> getAnyValue(const std::string& key) {
|
|
132
|
-
const auto& any = _map->getAny(key);
|
|
133
|
-
return JAnyValue::create(any);
|
|
134
|
-
}
|
|
114
|
+
jni::local_ref<JAnyArray> getAnyArray(const std::string& key);
|
|
115
|
+
jni::local_ref<JAnyObject> getAnyObject(const std::string& key);
|
|
116
|
+
jni::local_ref<JAnyValue::javaobject> getAnyValue(const std::string& key);
|
|
135
117
|
|
|
136
118
|
protected:
|
|
137
119
|
void setNull(const std::string& key) {
|
|
@@ -149,33 +131,38 @@ protected:
|
|
|
149
131
|
void setString(const std::string& key, const std::string& value) {
|
|
150
132
|
_map->setString(key, value);
|
|
151
133
|
}
|
|
152
|
-
void setAnyArray(const std::string& key, jni::alias_ref<JAnyArray> value)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
vector.reserve(size);
|
|
156
|
-
for (size_t i = 0; i < size; i++) {
|
|
157
|
-
auto anyValue = value->getElement(i);
|
|
158
|
-
vector.push_back(anyValue->cthis()->getValue());
|
|
159
|
-
}
|
|
160
|
-
_map->setArray(key, vector);
|
|
161
|
-
}
|
|
162
|
-
void setAnyObject(const std::string& key, const jni::alias_ref<JAnyObject>& value) {
|
|
163
|
-
std::unordered_map<std::string, AnyValue> map;
|
|
164
|
-
map.reserve(value->size());
|
|
165
|
-
for (const auto& entry : *value) {
|
|
166
|
-
map.emplace(entry.first->toStdString(), entry.second->cthis()->getValue());
|
|
167
|
-
}
|
|
168
|
-
_map->setObject(key, map);
|
|
169
|
-
}
|
|
170
|
-
void setAnyValue(const std::string& key, const jni::alias_ref<JAnyValue::javaobject>& value) {
|
|
171
|
-
_map->setAny(key, value->cthis()->getValue());
|
|
172
|
-
}
|
|
134
|
+
void setAnyArray(const std::string& key, jni::alias_ref<JAnyArray> value);
|
|
135
|
+
void setAnyObject(const std::string& key, const jni::alias_ref<JAnyObject>& value);
|
|
136
|
+
void setAnyValue(const std::string& key, const jni::alias_ref<JAnyValue::javaobject>& value);
|
|
173
137
|
|
|
174
138
|
protected:
|
|
175
139
|
void merge(jni::alias_ref<JAnyMap::javaobject> other) {
|
|
176
140
|
_map->merge(other->cthis()->_map);
|
|
177
141
|
}
|
|
178
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Bulk-converts the entire `JAnyMap` to a Java `HashMap<String, Object>` in a single JNI call.
|
|
145
|
+
*/
|
|
146
|
+
jni::local_ref<jni::JHashMap<jni::JString, jni::JObject>> toHashMap();
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Bulk-converts a Java `Map<String, Object>` into this `JAnyMap` in a single JNI call.
|
|
150
|
+
*
|
|
151
|
+
* When `ignoreIncompatible` is `true`, this will drop keys that can't be converted.
|
|
152
|
+
* When `ignoreIncompatible` is `false`, this will throw when a key cannot be converted.
|
|
153
|
+
*/
|
|
154
|
+
static jni::local_ref<JAnyMap::javaobject> fromMap(jni::alias_ref<jclass>, jni::alias_ref<jni::JMap<jni::JString, jni::JObject>> javaMap,
|
|
155
|
+
bool ignoreIncompatible);
|
|
156
|
+
|
|
157
|
+
private:
|
|
158
|
+
static jni::local_ref<jni::JObject> anyValueToJObject(const AnyValue& value);
|
|
159
|
+
static jni::local_ref<jni::JArrayList<jni::JObject>> anyArrayToJList(const AnyArray& array);
|
|
160
|
+
static jni::local_ref<jni::JHashMap<jni::JString, jni::JObject>> anyObjectToJHashMap(const AnyObject& object);
|
|
161
|
+
|
|
162
|
+
static AnyValue jObjectToAnyValue(jni::alias_ref<jni::JObject> jObject);
|
|
163
|
+
static AnyArray jListToAnyArray(jni::alias_ref<jni::JList<jni::JObject>> jList);
|
|
164
|
+
static AnyObject jHashMapToAnyObject(jni::alias_ref<jni::JMap<jni::JString, jni::JObject>> jMap);
|
|
165
|
+
|
|
179
166
|
public:
|
|
180
167
|
[[nodiscard]]
|
|
181
168
|
std::shared_ptr<AnyMap> getMap() const {
|
|
@@ -225,8 +212,11 @@ public:
|
|
|
225
212
|
makeNativeMethod("setAnyValue", JAnyMap::setAnyValue),
|
|
226
213
|
// merge
|
|
227
214
|
makeNativeMethod("merge", JAnyMap::merge),
|
|
215
|
+
// bulk conversion
|
|
216
|
+
makeNativeMethod("toHashMap", JAnyMap::toHashMap),
|
|
217
|
+
makeNativeMethod("fromMap", JAnyMap::fromMap),
|
|
228
218
|
});
|
|
229
219
|
}
|
|
230
220
|
};
|
|
231
221
|
|
|
232
|
-
} // namespace margelo::nitro
|
|
222
|
+
} // namespace margelo::nitro
|
|
@@ -26,7 +26,9 @@ int levelToAndroidLevel(LogLevel level) {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
void Logger::nativeLog([[maybe_unused]] LogLevel level,
|
|
29
|
+
void Logger::nativeLog([[maybe_unused]] LogLevel level, //
|
|
30
|
+
[[maybe_unused]] const char* tag, //
|
|
31
|
+
[[maybe_unused]] const std::string& message) {
|
|
30
32
|
#ifdef NITRO_DEBUG
|
|
31
33
|
int logLevel = levelToAndroidLevel(level);
|
|
32
34
|
std::string combinedTag = "Nitro." + std::string(tag);
|
|
@@ -39,33 +39,26 @@ class AnyMap {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
companion object {
|
|
42
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Converts the given [map] to a new [AnyMap].
|
|
44
|
+
* @param map The map of keys/value types. Only a number of value types
|
|
45
|
+
* are supported in [AnyMap] - see Nitro docs for more information.
|
|
46
|
+
* @param ignoreIncompatible Whether to throw when an incompatible
|
|
47
|
+
* type is found, or not. If this is `false`, all incompatible key/value
|
|
48
|
+
* pairs will just be ignored.
|
|
49
|
+
*/
|
|
50
|
+
@JvmStatic
|
|
51
|
+
external fun fromMap(
|
|
43
52
|
map: Map<String, Any?>,
|
|
44
|
-
ignoreIncompatible: Boolean
|
|
45
|
-
): AnyMap
|
|
46
|
-
val anyMap = AnyMap(map.size)
|
|
47
|
-
for ((key, value) in map) {
|
|
48
|
-
try {
|
|
49
|
-
anyMap.setAny(key, value)
|
|
50
|
-
} catch (error: Throwable) {
|
|
51
|
-
if (ignoreIncompatible) {
|
|
52
|
-
continue
|
|
53
|
-
} else {
|
|
54
|
-
throw error
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return anyMap
|
|
59
|
-
}
|
|
53
|
+
ignoreIncompatible: Boolean,
|
|
54
|
+
): AnyMap
|
|
60
55
|
}
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return map
|
|
68
|
-
}
|
|
57
|
+
/**
|
|
58
|
+
* Converts this [AnyMap] to a new [HashMap] by
|
|
59
|
+
* copying each key/value.
|
|
60
|
+
*/
|
|
61
|
+
external fun toHashMap(): HashMap<String, Any?>
|
|
69
62
|
|
|
70
63
|
fun setAny(
|
|
71
64
|
key: String,
|
|
@@ -78,6 +71,11 @@ class AnyMap {
|
|
|
78
71
|
return getAnyValue(key).toAny()
|
|
79
72
|
}
|
|
80
73
|
|
|
74
|
+
private external fun fromHashMap(
|
|
75
|
+
map: Map<String, Any?>,
|
|
76
|
+
ignoreIncompatible: Boolean,
|
|
77
|
+
)
|
|
78
|
+
|
|
81
79
|
@FastNative
|
|
82
80
|
external fun contains(key: String): Boolean
|
|
83
81
|
|
|
@@ -43,7 +43,7 @@ class ArrayBuffer {
|
|
|
43
43
|
* - If the `ArrayBuffer` holds a `ByteBuffer`, `getBuffer(false)` can safely be called to
|
|
44
44
|
* get shared access to the underlying data, without performing any copies.
|
|
45
45
|
* - If the `ArrayBuffer` doesn't hold a `ByteBuffer`, it can still be accessed via `getBuffer(false)`,
|
|
46
|
-
* but the returned `ByteBuffer` is only valid as long as
|
|
46
|
+
* but the returned `ByteBuffer` is only valid as long as its parent `ArrayBuffer` is alive.
|
|
47
47
|
*/
|
|
48
48
|
val isByteBuffer: Boolean
|
|
49
49
|
get() = getIsByteBuffer()
|
|
@@ -104,7 +104,7 @@ class ArrayBuffer {
|
|
|
104
104
|
// The ByteBuffer is 1:1 mapped to a byte array - return as is!
|
|
105
105
|
return array
|
|
106
106
|
}
|
|
107
|
-
// we had a CPU-backed array, but
|
|
107
|
+
// we had a CPU-backed array, but its size differs from our ArrayBuffer size.
|
|
108
108
|
// This might be because the ArrayBuffer has a smaller view of the data, so we need
|
|
109
109
|
// to resort back to a good ol' copy.
|
|
110
110
|
}
|
|
@@ -35,7 +35,7 @@ abstract class HybridObject {
|
|
|
35
35
|
* Eagerly- (and manually-) dispose all native resources this `HybridObject` holds.
|
|
36
36
|
* This method can only be manually called from JS using `dispose()`.
|
|
37
37
|
*
|
|
38
|
-
* If this method is never manually called, a `HybridObject` is expected to disposes
|
|
38
|
+
* If this method is never manually called, a `HybridObject` is expected to disposes its
|
|
39
39
|
* resources as usual via the object's destructor (`~HybridObject()`, `deinit` or `finalize()`).
|
|
40
40
|
*
|
|
41
41
|
* By default, this method does nothing. It can be overridden to perform actual disposing/cleanup
|
|
@@ -58,13 +58,13 @@ abstract class HybridObject {
|
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
60
|
* Holds the native C++ instance.
|
|
61
|
-
* In `HybridObject`, the C++ instance is a sub-class of `JHybridObject`, such as one of
|
|
61
|
+
* In `HybridObject`, the C++ instance is a sub-class of `JHybridObject`, such as one of its specs.
|
|
62
62
|
* This is `null`, until `updateNative(..)` is called.
|
|
63
63
|
*/
|
|
64
64
|
private var mHybridData: HybridData? = null
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
* If `HybridObject` is subclassed, the sub-class needs to create
|
|
67
|
+
* If `HybridObject` is subclassed, the sub-class needs to create its own `HybridData`
|
|
68
68
|
* with a C++ `jni::HybridClass` representing the subclass directly.
|
|
69
69
|
* Then, that `HybridData` must be passed upwards to `HybridObject` using `updateNative(..)`.
|
|
70
70
|
*
|
package/cpp/core/AnyMap.cpp
CHANGED
|
@@ -189,7 +189,7 @@ void AnyMap::setAny(const std::string& key, const AnyValue& value) {
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
// C++ getter
|
|
192
|
-
|
|
192
|
+
std::unordered_map<std::string, AnyValue>& AnyMap::getMap() {
|
|
193
193
|
return _map;
|
|
194
194
|
}
|
|
195
195
|
|
package/cpp/core/AnyMap.hpp
CHANGED
|
@@ -38,8 +38,8 @@ struct AnyValue : VariantType {
|
|
|
38
38
|
*/
|
|
39
39
|
class AnyMap final {
|
|
40
40
|
private:
|
|
41
|
-
|
|
42
|
-
AnyMap(size_t size) {
|
|
41
|
+
AnyMap() = default;
|
|
42
|
+
explicit AnyMap(size_t size) {
|
|
43
43
|
_map.reserve(size);
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -201,7 +201,7 @@ public:
|
|
|
201
201
|
/**
|
|
202
202
|
* Get the actual C++ map that holds all keys and variant values.
|
|
203
203
|
*/
|
|
204
|
-
|
|
204
|
+
std::unordered_map<std::string, AnyValue>& getMap();
|
|
205
205
|
|
|
206
206
|
public:
|
|
207
207
|
/**
|
package/cpp/core/ArrayBuffer.hpp
CHANGED
|
@@ -28,7 +28,7 @@ using DeleteFn = std::function<void()>;
|
|
|
28
28
|
* - `NativeArrayBuffer`: Created from native (C++), and can either own the memory (`isOwner()`), or borrow it.
|
|
29
29
|
* - `JSArrayBuffer`: Received from JS, and will only be alive for as long as the JS Runtime is actually alive.
|
|
30
30
|
*
|
|
31
|
-
* Also, an `ArrayBuffer` can either own
|
|
31
|
+
* Also, an `ArrayBuffer` can either own its memory, or just borrow its memory.
|
|
32
32
|
* - Owning = the `ArrayBuffer`'s `data()` is alive as long as the `ArrayBuffer` is alive.
|
|
33
33
|
* When this `ArrayBuffer` gets deleted, it will free the memory.
|
|
34
34
|
* - Borrowed = the `ArrayBuffer`'s `data()` might be deleted at any point from an external source (e.g. the JS garbage collector).
|
|
@@ -116,13 +116,13 @@ private:
|
|
|
116
116
|
/**
|
|
117
117
|
* Represents a JS-based `ArrayBuffer`.
|
|
118
118
|
*
|
|
119
|
-
* While
|
|
119
|
+
* While its underlying data might have been allocated on the native side (`NativeArrayBuffer`),
|
|
120
120
|
* we only have a JS reference to the `ArrayBuffer` object so it is considered a "borrowed"-resource.
|
|
121
121
|
*
|
|
122
122
|
* `data()` and `size()` can only be accessed synchronously on the JS Runtime Thread.
|
|
123
123
|
* If you want to access it elsewhere, copy the buffer first.
|
|
124
124
|
*
|
|
125
|
-
* If the JS ArrayBuffer (or
|
|
125
|
+
* If the JS ArrayBuffer (or its JS Runtime) have already been deleted, `data()` returns `nullptr`.
|
|
126
126
|
*/
|
|
127
127
|
class JSArrayBuffer final : public ArrayBuffer {
|
|
128
128
|
public:
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
#include "HybridObject.hpp"
|
|
6
|
+
#include "CommonGlobals.hpp"
|
|
6
7
|
#include "JSIConverter.hpp"
|
|
7
8
|
#include "NitroDefines.hpp"
|
|
8
|
-
#include "ObjectUtils.hpp"
|
|
9
9
|
|
|
10
10
|
namespace margelo::nitro {
|
|
11
11
|
|
|
@@ -75,7 +75,7 @@ jsi::Value HybridObject::toObject(jsi::Runtime& runtime) {
|
|
|
75
75
|
jsi::Value prototype = getPrototype(runtime);
|
|
76
76
|
|
|
77
77
|
// 3. Create the object using Object.create(...)
|
|
78
|
-
jsi::Object object =
|
|
78
|
+
jsi::Object object = CommonGlobals::Object::create(runtime, prototype);
|
|
79
79
|
|
|
80
80
|
// 4. Assign NativeState to the object so the prototype can resolve the native methods
|
|
81
81
|
object.setNativeState(runtime, shared());
|
|
@@ -86,14 +86,14 @@ jsi::Value HybridObject::toObject(jsi::Runtime& runtime) {
|
|
|
86
86
|
#ifdef NITRO_DEBUG
|
|
87
87
|
// 6. Assign a private __type property for debugging - this will be used so users know it's not just an empty object.
|
|
88
88
|
std::string typeName = "HybridObject<" + std::string(_name) + ">";
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
CommonGlobals::Object::defineProperty(runtime, object, "__type",
|
|
90
|
+
PlainPropertyDescriptor{
|
|
91
|
+
// .configurable has to be true because this property is non-frozen
|
|
92
|
+
.configurable = true,
|
|
93
|
+
.enumerable = true,
|
|
94
|
+
.value = jsi::String::createFromUtf8(runtime, typeName),
|
|
95
|
+
.writable = false,
|
|
96
|
+
});
|
|
97
97
|
#endif
|
|
98
98
|
|
|
99
99
|
// 7. Throw a jsi::WeakObject pointing to our object into cache so subsequent calls can use it from cache
|
|
@@ -60,14 +60,14 @@ public:
|
|
|
60
60
|
/**
|
|
61
61
|
* Return the `jsi::Object` that holds this `HybridObject`. (boxed in a `jsi::Value`)
|
|
62
62
|
* This properly assigns (or creates) the base prototype for this type,
|
|
63
|
-
* and assigns
|
|
63
|
+
* and assigns its NativeState.
|
|
64
64
|
* Additionally, this sets the external memory pressure for proper GC memory management.
|
|
65
65
|
*/
|
|
66
66
|
jsi::Value toObject(jsi::Runtime& runtime);
|
|
67
67
|
|
|
68
68
|
public:
|
|
69
69
|
/**
|
|
70
|
-
* Get the `std::shared_ptr` instance of this HybridObject as
|
|
70
|
+
* Get the `std::shared_ptr` instance of this HybridObject as its concrete type.
|
|
71
71
|
* The HybridObject must be managed inside a `shared_ptr` already, otherwise this will fail.
|
|
72
72
|
*/
|
|
73
73
|
template <typename Derived>
|
|
@@ -99,7 +99,7 @@ public:
|
|
|
99
99
|
* Eagerly- (and manually-) dispose all native resources this `HybridObject` holds.
|
|
100
100
|
* This method can only be manually called from JS using `dispose()`.
|
|
101
101
|
*
|
|
102
|
-
* If this method is never manually called, a `HybridObject` is expected to disposes
|
|
102
|
+
* If this method is never manually called, a `HybridObject` is expected to disposes its
|
|
103
103
|
* resources as usual via the object's destructor (`~HybridObject()`, `deinit` or `finalize()`).
|
|
104
104
|
*
|
|
105
105
|
* By default, this method does nothing. It can be overridden to perform actual disposing/cleanup
|
|
@@ -71,7 +71,7 @@ jsi::Value HybridNitroModulesProxy::isHybridObject(jsi::Runtime& runtime, const
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
std::shared_ptr<HybridObject> HybridNitroModulesProxy::updateMemorySize(const std::shared_ptr<HybridObject>& hybridObject) {
|
|
74
|
-
// If a hybridObject goes from Native -> JS, it will update
|
|
74
|
+
// If a hybridObject goes from Native -> JS, it will update its memory size internally (in `HybridObject::toObject(..)`).
|
|
75
75
|
// This is all that function does.
|
|
76
76
|
return hybridObject;
|
|
77
77
|
}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#include "InstallNitro.hpp"
|
|
9
|
+
#include "CommonGlobals.hpp"
|
|
9
10
|
#include "HybridNitroModulesProxy.hpp"
|
|
10
|
-
#include "ObjectUtils.hpp"
|
|
11
11
|
|
|
12
12
|
namespace margelo::nitro {
|
|
13
13
|
|
|
@@ -23,7 +23,7 @@ void install(jsi::Runtime& runtime, std::shared_ptr<Dispatcher> dispatcher) {
|
|
|
23
23
|
void install(jsi::Runtime& runtime) {
|
|
24
24
|
// Installs global.NitroModulesProxy
|
|
25
25
|
auto proxy = std::make_shared<HybridNitroModulesProxy>();
|
|
26
|
-
|
|
26
|
+
CommonGlobals::defineGlobal(runtime, KnownGlobalPropertyName::NITRO_MODULES_PROXY, proxy->toObject(runtime));
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
} // namespace margelo::nitro
|