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
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
//
|
|
2
|
+
// CommonGlobals.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 17.10.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "CommonGlobals.hpp"
|
|
9
|
+
#include "JSICache.hpp"
|
|
10
|
+
#include "JSIHelpers.hpp"
|
|
11
|
+
#include "NitroDefines.hpp"
|
|
12
|
+
#include "PropNameIDCache.hpp"
|
|
13
|
+
|
|
14
|
+
#if __has_include(<cxxreact/ReactNativeVersion.h>)
|
|
15
|
+
#include <cxxreact/ReactNativeVersion.h>
|
|
16
|
+
#if REACT_NATIVE_VERSION_MINOR >= 78
|
|
17
|
+
#define ENABLE_NATIVE_OBJECT_CREATE
|
|
18
|
+
#endif
|
|
19
|
+
#endif
|
|
20
|
+
|
|
21
|
+
namespace margelo::nitro {
|
|
22
|
+
|
|
23
|
+
using namespace facebook;
|
|
24
|
+
|
|
25
|
+
std::unordered_map<jsi::Runtime*, CommonGlobals::FunctionCache> CommonGlobals::_cache;
|
|
26
|
+
|
|
27
|
+
// pragma MARK: Object
|
|
28
|
+
|
|
29
|
+
jsi::Object CommonGlobals::Object::create(jsi::Runtime& runtime, const jsi::Value& prototype) {
|
|
30
|
+
#ifdef ENABLE_NATIVE_OBJECT_CREATE
|
|
31
|
+
return jsi::Object::create(runtime, prototype);
|
|
32
|
+
#else
|
|
33
|
+
const jsi::Function& createFn = getGlobalFunction(runtime, "Object.create", [](jsi::Runtime& runtime) {
|
|
34
|
+
return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "create");
|
|
35
|
+
});
|
|
36
|
+
return createFn.call(runtime, prototype).getObject(runtime);
|
|
37
|
+
#endif
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void CommonGlobals::Object::defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
|
|
41
|
+
PlainPropertyDescriptor&& descriptor) {
|
|
42
|
+
const jsi::Function& definePropertyFn = getGlobalFunction(runtime, "Object.defineProperty", [](jsi::Runtime& runtime) {
|
|
43
|
+
return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "defineProperty");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
jsi::String nameJs = jsi::String::createFromAscii(runtime, propertyName);
|
|
47
|
+
|
|
48
|
+
jsi::Object descriptorJs(runtime);
|
|
49
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "configurable"), jsi::Value(descriptor.configurable));
|
|
50
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "enumerable"), jsi::Value(descriptor.enumerable));
|
|
51
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "value"), std::move(descriptor.value));
|
|
52
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "writable"), jsi::Value(descriptor.writable));
|
|
53
|
+
|
|
54
|
+
definePropertyFn.call(runtime, object, std::move(nameJs), std::move(descriptorJs));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void CommonGlobals::Object::defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
|
|
58
|
+
ComputedReadonlyPropertyDescriptor&& descriptor) {
|
|
59
|
+
const jsi::Function& definePropertyFn = getGlobalFunction(runtime, "Object.defineProperty", [](jsi::Runtime& runtime) {
|
|
60
|
+
return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "defineProperty");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
jsi::String nameJs = jsi::String::createFromAscii(runtime, propertyName);
|
|
64
|
+
|
|
65
|
+
jsi::Object descriptorJs(runtime);
|
|
66
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "configurable"), jsi::Value(descriptor.configurable));
|
|
67
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "enumerable"), jsi::Value(descriptor.enumerable));
|
|
68
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "get"), std::move(descriptor.get));
|
|
69
|
+
|
|
70
|
+
definePropertyFn.call(runtime, object, std::move(nameJs), std::move(descriptorJs));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
void CommonGlobals::Object::defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
|
|
74
|
+
ComputedPropertyDescriptor&& descriptor) {
|
|
75
|
+
const jsi::Function& definePropertyFn = getGlobalFunction(runtime, "Object.defineProperty", [](jsi::Runtime& runtime) {
|
|
76
|
+
return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "defineProperty");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
jsi::String nameJs = jsi::String::createFromAscii(runtime, propertyName);
|
|
80
|
+
|
|
81
|
+
jsi::Object descriptorJs(runtime);
|
|
82
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "configurable"), jsi::Value(descriptor.configurable));
|
|
83
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "enumerable"), jsi::Value(descriptor.enumerable));
|
|
84
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "get"), std::move(descriptor.get));
|
|
85
|
+
descriptorJs.setProperty(runtime, PropNameIDCache::get(runtime, "set"), std::move(descriptor.set));
|
|
86
|
+
|
|
87
|
+
definePropertyFn.call(runtime, object, std::move(nameJs), std::move(descriptorJs));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
void CommonGlobals::Object::freeze(jsi::Runtime& runtime, const jsi::Object& object) {
|
|
91
|
+
const jsi::Function& freezeFn = getGlobalFunction(runtime, "Object.freeze", [](jsi::Runtime& runtime) {
|
|
92
|
+
return runtime.global().getPropertyAsObject(runtime, "Object").getPropertyAsFunction(runtime, "freeze");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
freezeFn.call(runtime, object);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// pragma MARK: Promise
|
|
99
|
+
|
|
100
|
+
jsi::Value CommonGlobals::Promise::resolved(jsi::Runtime& runtime) {
|
|
101
|
+
const jsi::Function& resolvedFunc = getGlobalFunction(runtime, "Promise.resolve", [](jsi::Runtime& runtime) {
|
|
102
|
+
return runtime.global().getPropertyAsObject(runtime, "Promise").getPropertyAsFunction(runtime, "resolve");
|
|
103
|
+
});
|
|
104
|
+
return resolvedFunc.call(runtime);
|
|
105
|
+
}
|
|
106
|
+
jsi::Value CommonGlobals::Promise::resolved(jsi::Runtime& runtime, jsi::Value&& value) {
|
|
107
|
+
const jsi::Function& resolvedFunc = getGlobalFunction(runtime, "Promise.resolve", [](jsi::Runtime& runtime) {
|
|
108
|
+
return runtime.global().getPropertyAsObject(runtime, "Promise").getPropertyAsFunction(runtime, "resolve");
|
|
109
|
+
});
|
|
110
|
+
return resolvedFunc.call(runtime, {std::move(value)});
|
|
111
|
+
}
|
|
112
|
+
jsi::Value CommonGlobals::Promise::rejected(jsi::Runtime& runtime, jsi::Value&& error) {
|
|
113
|
+
const jsi::Function& rejectedFunc = getGlobalFunction(runtime, "Promise.reject", [](jsi::Runtime& runtime) {
|
|
114
|
+
return runtime.global().getPropertyAsObject(runtime, "Promise").getPropertyAsFunction(runtime, "reject");
|
|
115
|
+
});
|
|
116
|
+
return rejectedFunc.call(runtime, {std::move(error)});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
jsi::Value CommonGlobals::Promise::callConstructor(jsi::Runtime& runtime, jsi::HostFunctionType&& executor) {
|
|
120
|
+
const jsi::Function& promiseCtor = getGlobalFunction(
|
|
121
|
+
runtime, "Promise", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Promise"); });
|
|
122
|
+
jsi::Function executorFunc =
|
|
123
|
+
jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forAscii(runtime, "executor"), 2, std::move(executor));
|
|
124
|
+
return promiseCtor.callAsConstructor(runtime, std::move(executorFunc));
|
|
125
|
+
}
|
|
126
|
+
bool CommonGlobals::Promise::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
|
|
127
|
+
const jsi::Function& promiseCtor = getGlobalFunction(
|
|
128
|
+
runtime, "Promise", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Promise"); });
|
|
129
|
+
return object.instanceOf(runtime, promiseCtor);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// pragma MARK: Date
|
|
133
|
+
|
|
134
|
+
jsi::Value CommonGlobals::Date::callConstructor(jsi::Runtime& runtime, double msSinceEpoch) {
|
|
135
|
+
const jsi::Function& dateCtor =
|
|
136
|
+
getGlobalFunction(runtime, "Date", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Date"); });
|
|
137
|
+
return dateCtor.callAsConstructor(runtime, {jsi::Value(msSinceEpoch)});
|
|
138
|
+
}
|
|
139
|
+
bool CommonGlobals::Date::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
|
|
140
|
+
const jsi::Function& dateCtor =
|
|
141
|
+
getGlobalFunction(runtime, "Date", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Date"); });
|
|
142
|
+
return object.instanceOf(runtime, dateCtor);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// pragma MARK: Error
|
|
146
|
+
|
|
147
|
+
bool CommonGlobals::Error::isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object) {
|
|
148
|
+
const jsi::Function& errorCtor =
|
|
149
|
+
getGlobalFunction(runtime, "Error", [](jsi::Runtime& runtime) { return runtime.global().getPropertyAsFunction(runtime, "Error"); });
|
|
150
|
+
return object.instanceOf(runtime, errorCtor);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// pragma MARK: CommonGlobals
|
|
154
|
+
|
|
155
|
+
void CommonGlobals::defineGlobal(jsi::Runtime& runtime, KnownGlobalPropertyName name, jsi::Value&& value) {
|
|
156
|
+
const char* nameString = getKnownGlobalPropertyNameString(name);
|
|
157
|
+
|
|
158
|
+
#ifdef NITRO_DEBUG
|
|
159
|
+
// In debug, let's perform additional safety checks.
|
|
160
|
+
if (runtime.global().hasProperty(runtime, nameString)) [[unlikely]] {
|
|
161
|
+
throw std::runtime_error("Failed to set `global." + std::string(nameString) + "` - it already exists for Runtime \"" +
|
|
162
|
+
getRuntimeId(runtime) + "\"! Did you call `defineGlobal(\"" + std::string(nameString) +
|
|
163
|
+
"\")` twice? Did you link Nitro Modules twice?");
|
|
164
|
+
}
|
|
165
|
+
Object::defineProperty(runtime, runtime.global(), nameString,
|
|
166
|
+
PlainPropertyDescriptor{.configurable = false, .enumerable = true, .value = std::move(value), .writable = false});
|
|
167
|
+
#else
|
|
168
|
+
// In release, just set the property.
|
|
169
|
+
runtime.global().setProperty(runtime, nameString, std::move(value));
|
|
170
|
+
#endif
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const char* CommonGlobals::getKnownGlobalPropertyNameString(KnownGlobalPropertyName name) {
|
|
174
|
+
switch (name) {
|
|
175
|
+
case KnownGlobalPropertyName::DISPATCHER:
|
|
176
|
+
return "__nitroDispatcher";
|
|
177
|
+
case KnownGlobalPropertyName::JSI_CACHE:
|
|
178
|
+
return "__nitroJsiCache";
|
|
179
|
+
case KnownGlobalPropertyName::NITRO_MODULES_PROXY:
|
|
180
|
+
return "NitroModulesProxy";
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const jsi::PropNameID& CommonGlobals::getKnownGlobalPropertyName(jsi::Runtime& runtime, KnownGlobalPropertyName name) {
|
|
185
|
+
return PropNameIDCache::get(runtime, getKnownGlobalPropertyNameString(name));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const jsi::Function& CommonGlobals::getGlobalFunction(jsi::Runtime& runtime, const char* key,
|
|
189
|
+
std::function<jsi::Function(jsi::Runtime&)> getFunction) {
|
|
190
|
+
// Let's try to find the function in cache
|
|
191
|
+
FunctionCache& functionCache = _cache[&runtime];
|
|
192
|
+
std::string stringKey = key;
|
|
193
|
+
auto iterator = functionCache.find(stringKey);
|
|
194
|
+
if (iterator != functionCache.end()) {
|
|
195
|
+
// We found it! Let's check if the reference is still valid...
|
|
196
|
+
BorrowingReference<jsi::Function> function = iterator->second;
|
|
197
|
+
if (function != nullptr) [[likely]] {
|
|
198
|
+
// It's still alive - let's use it from cache!
|
|
199
|
+
return *function;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// We haven't found the function with the given key in cache - so let's get it:
|
|
204
|
+
jsi::Function function = getFunction(runtime);
|
|
205
|
+
|
|
206
|
+
// Let's throw it in cache!
|
|
207
|
+
JSICacheReference jsiCache = JSICache::getOrCreateCache(runtime);
|
|
208
|
+
BorrowingReference<jsi::Function> sharedFunction = jsiCache.makeShared(std::move(function));
|
|
209
|
+
functionCache[stringKey] = sharedFunction;
|
|
210
|
+
|
|
211
|
+
// And now return:
|
|
212
|
+
return *sharedFunction;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
} // namespace margelo::nitro
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
//
|
|
2
|
+
// CommonGlobals.hpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 17.10.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "BorrowingReference.hpp"
|
|
11
|
+
#include <jsi/jsi.h>
|
|
12
|
+
#include <unordered_map>
|
|
13
|
+
|
|
14
|
+
namespace margelo::nitro {
|
|
15
|
+
|
|
16
|
+
using namespace facebook;
|
|
17
|
+
|
|
18
|
+
struct PlainPropertyDescriptor {
|
|
19
|
+
bool configurable;
|
|
20
|
+
bool enumerable;
|
|
21
|
+
jsi::Value value;
|
|
22
|
+
bool writable;
|
|
23
|
+
};
|
|
24
|
+
struct ComputedReadonlyPropertyDescriptor {
|
|
25
|
+
bool configurable;
|
|
26
|
+
bool enumerable;
|
|
27
|
+
jsi::Function get;
|
|
28
|
+
};
|
|
29
|
+
struct ComputedPropertyDescriptor {
|
|
30
|
+
bool configurable;
|
|
31
|
+
bool enumerable;
|
|
32
|
+
jsi::Function get;
|
|
33
|
+
jsi::Function set;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
enum class KnownGlobalPropertyName { DISPATCHER, JSI_CACHE, NITRO_MODULES_PROXY };
|
|
37
|
+
|
|
38
|
+
class CommonGlobals final {
|
|
39
|
+
public:
|
|
40
|
+
CommonGlobals() = delete;
|
|
41
|
+
~CommonGlobals() = delete;
|
|
42
|
+
|
|
43
|
+
public:
|
|
44
|
+
/**
|
|
45
|
+
* Define a global value for the given Runtime.
|
|
46
|
+
* In debug, this performs additional safety checks such as freezing the property.
|
|
47
|
+
*/
|
|
48
|
+
static void defineGlobal(jsi::Runtime& runtime, KnownGlobalPropertyName name, jsi::Value&& value);
|
|
49
|
+
/**
|
|
50
|
+
* Get a string name for a known global property name.
|
|
51
|
+
*/
|
|
52
|
+
static const char* getKnownGlobalPropertyNameString(KnownGlobalPropertyName name);
|
|
53
|
+
/**
|
|
54
|
+
* Get a `jsi::PropNameID` for a known global property name.
|
|
55
|
+
*/
|
|
56
|
+
static const jsi::PropNameID& getKnownGlobalPropertyName(jsi::Runtime& runtime, KnownGlobalPropertyName name);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
|
|
60
|
+
*/
|
|
61
|
+
class Object final {
|
|
62
|
+
public:
|
|
63
|
+
Object() = delete;
|
|
64
|
+
~Object() = delete;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Create a new `jsi::Object` with the given `prototype`.
|
|
68
|
+
* Uses a native implementation if possible.
|
|
69
|
+
*/
|
|
70
|
+
static jsi::Object create(jsi::Runtime& runtime, const jsi::Value& prototype);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Define a plain property on the given `object` with the given `propertyName`.
|
|
74
|
+
* The `descriptor` defines the attributes of this property.
|
|
75
|
+
*/
|
|
76
|
+
static void defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
|
|
77
|
+
PlainPropertyDescriptor&& descriptor);
|
|
78
|
+
/**
|
|
79
|
+
* Define a plain property on the given `object` with the given `propertyName`.
|
|
80
|
+
* The `descriptor` defines the attributes of this property.
|
|
81
|
+
*/
|
|
82
|
+
static void defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
|
|
83
|
+
ComputedReadonlyPropertyDescriptor&& descriptor);
|
|
84
|
+
/**
|
|
85
|
+
* Define a plain property on the given `object` with the given `propertyName`.
|
|
86
|
+
* The `descriptor` defines the attributes of this property.
|
|
87
|
+
*/
|
|
88
|
+
static void defineProperty(jsi::Runtime& runtime, const jsi::Object& object, const char* propertyName,
|
|
89
|
+
ComputedPropertyDescriptor&& descriptor);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Freezes all values of the given `object`.
|
|
93
|
+
*/
|
|
94
|
+
static void freeze(jsi::Runtime& runtime, const jsi::Object& object);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
|
|
99
|
+
*/
|
|
100
|
+
class Promise final {
|
|
101
|
+
public:
|
|
102
|
+
Promise() = delete;
|
|
103
|
+
~Promise() = delete;
|
|
104
|
+
|
|
105
|
+
static jsi::Value resolved(jsi::Runtime& runtime);
|
|
106
|
+
static jsi::Value resolved(jsi::Runtime& runtime, jsi::Value&& value);
|
|
107
|
+
static jsi::Value rejected(jsi::Runtime& runtime, jsi::Value&& error);
|
|
108
|
+
|
|
109
|
+
static jsi::Value callConstructor(jsi::Runtime& runtime, jsi::HostFunctionType&& executor);
|
|
110
|
+
static bool isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
|
|
115
|
+
*/
|
|
116
|
+
class Date final {
|
|
117
|
+
public:
|
|
118
|
+
Date() = delete;
|
|
119
|
+
~Date() = delete;
|
|
120
|
+
|
|
121
|
+
static jsi::Value callConstructor(jsi::Runtime& runtime, double msSinceEpoch);
|
|
122
|
+
static bool isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
|
|
127
|
+
*/
|
|
128
|
+
class Error final {
|
|
129
|
+
public:
|
|
130
|
+
Error() = delete;
|
|
131
|
+
~Error() = delete;
|
|
132
|
+
|
|
133
|
+
static bool isInstanceOf(jsi::Runtime& runtime, const jsi::Object& object);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
private:
|
|
137
|
+
friend Object;
|
|
138
|
+
friend Promise;
|
|
139
|
+
friend Date;
|
|
140
|
+
friend Error;
|
|
141
|
+
|
|
142
|
+
private:
|
|
143
|
+
/**
|
|
144
|
+
* Get a global Function, and optionally cache it in the Runtime via the `key`.
|
|
145
|
+
*
|
|
146
|
+
* The returned const-ref to a `jsi::Function` should only be used within the callee's
|
|
147
|
+
* synchronous scope.
|
|
148
|
+
* It may no longer be active after the scope ends (function return).
|
|
149
|
+
*/
|
|
150
|
+
static const jsi::Function& getGlobalFunction(jsi::Runtime& runtime, const char* key,
|
|
151
|
+
std::function<jsi::Function(jsi::Runtime&)> getFunction);
|
|
152
|
+
|
|
153
|
+
private:
|
|
154
|
+
using FunctionCache = std::unordered_map<std::string, BorrowingReference<jsi::Function>>;
|
|
155
|
+
static std::unordered_map<jsi::Runtime*, FunctionCache> _cache;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
} // namespace margelo::nitro
|
package/cpp/utils/JSCallback.hpp
CHANGED
|
@@ -35,7 +35,7 @@ public:
|
|
|
35
35
|
public:
|
|
36
36
|
/**
|
|
37
37
|
* Calls this `SyncJSCallback` synchronously, and
|
|
38
|
-
* returns
|
|
38
|
+
* returns its result (`R`).
|
|
39
39
|
* The callee is responsible for ensuring that the
|
|
40
40
|
* underlying `jsi::Function` can actually be called from this Thread.
|
|
41
41
|
* In Debug, sanity checks are made to ensure the `jsi::Function` is still alive.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PropNameIDCache.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 17.10.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "PropNameIDCache.hpp"
|
|
9
|
+
#include "JSICache.hpp"
|
|
10
|
+
|
|
11
|
+
namespace margelo::nitro {
|
|
12
|
+
|
|
13
|
+
using namespace facebook;
|
|
14
|
+
|
|
15
|
+
std::unordered_map<jsi::Runtime*, PropNameIDCache::CacheMap> PropNameIDCache::_cache;
|
|
16
|
+
|
|
17
|
+
const jsi::PropNameID& PropNameIDCache::get(jsi::Runtime& runtime, std::string value) {
|
|
18
|
+
CacheMap& cache = _cache[&runtime];
|
|
19
|
+
const auto& cachedName = cache.find(value);
|
|
20
|
+
if (cachedName != cache.end()) {
|
|
21
|
+
// cache warm!
|
|
22
|
+
const BorrowingReference<jsi::PropNameID>& value = cachedName->second;
|
|
23
|
+
return *value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// not cached - create the jsi::PropNameID...
|
|
27
|
+
auto propName = jsi::PropNameID::forAscii(runtime, value);
|
|
28
|
+
auto jsiCache = JSICache::getOrCreateCache(runtime);
|
|
29
|
+
auto sharedPropName = jsiCache.makeShared(std::move(propName));
|
|
30
|
+
|
|
31
|
+
// store it in cache...
|
|
32
|
+
cache.emplace(value, sharedPropName);
|
|
33
|
+
|
|
34
|
+
// return it!
|
|
35
|
+
return *sharedPropName;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
} // namespace margelo::nitro
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PropNameIDCache.hpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 17.10.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#include "BorrowingReference.hpp"
|
|
11
|
+
#include <jsi/jsi.h>
|
|
12
|
+
#include <unordered_map>
|
|
13
|
+
|
|
14
|
+
namespace margelo::nitro {
|
|
15
|
+
|
|
16
|
+
using namespace facebook;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Allows caching `jsi::PropNameID`s via `std::string`s.
|
|
20
|
+
* The returned `jsi::PropNameID` can be used for JSI operations like
|
|
21
|
+
* - `jsi::Object::getProperty(...)`
|
|
22
|
+
* - `jsi::Object::setProperty(...)`
|
|
23
|
+
* - `jsi::Object::hasProperty(...)`
|
|
24
|
+
* And is more efficient than the string equivalent overloads of those
|
|
25
|
+
* functions due to caching.
|
|
26
|
+
*/
|
|
27
|
+
class PropNameIDCache final {
|
|
28
|
+
public:
|
|
29
|
+
PropNameIDCache() = delete;
|
|
30
|
+
~PropNameIDCache() = delete;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get a `jsi::PropNameID` for the given `std::string` value.
|
|
34
|
+
* The `jsi::PropNameID` is only valid within the callee's current
|
|
35
|
+
* synchronous scope, and must be non-escaping.
|
|
36
|
+
*/
|
|
37
|
+
static const jsi::PropNameID& get(jsi::Runtime& runtime, std::string value);
|
|
38
|
+
|
|
39
|
+
private:
|
|
40
|
+
using CacheMap = std::unordered_map<std::string, BorrowingReference<jsi::PropNameID>>;
|
|
41
|
+
static std::unordered_map<jsi::Runtime*, CacheMap> _cache;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
} // namespace margelo::nitro
|
|
@@ -72,7 +72,7 @@ public:
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
/**
|
|
75
|
-
Try to lock the
|
|
75
|
+
* Try to lock the weak reference to a borrowing reference, or `nullptr` if it has already been deleted.
|
|
76
76
|
*/
|
|
77
77
|
[[nodiscard]]
|
|
78
78
|
BorrowingReference<T> lock() const;
|
|
@@ -30,7 +30,7 @@ public protocol HybridObject: AnyObject {
|
|
|
30
30
|
* Eagerly- (and manually-) dispose all native resources this `HybridObject` holds.
|
|
31
31
|
* This method can only be manually called from JS using `dispose()`.
|
|
32
32
|
*
|
|
33
|
-
* If this method is never manually called, a `HybridObject` is expected to disposes
|
|
33
|
+
* If this method is never manually called, a `HybridObject` is expected to disposes its
|
|
34
34
|
* resources as usual via the object's destructor (`~HybridObject()`, `deinit` or `finalize()`).
|
|
35
35
|
*
|
|
36
36
|
* By default, this method does nothing. It can be overridden to perform actual disposing/cleanup
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NitroLogger.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.07.24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "NitroLogger.hpp"
|
|
9
|
+
#include "NitroDefines.hpp"
|
|
10
|
+
#include <os/log.h>
|
|
11
|
+
|
|
12
|
+
namespace margelo::nitro {
|
|
13
|
+
|
|
14
|
+
void Logger::nativeLog([[maybe_unused]] LogLevel level, //
|
|
15
|
+
[[maybe_unused]] const char* NON_NULL tag, //
|
|
16
|
+
[[maybe_unused]] const std::string& message) {
|
|
17
|
+
#ifdef NITRO_DEBUG
|
|
18
|
+
static os_log_t logger = os_log_create("com.margelo.nitro", "nitro");
|
|
19
|
+
|
|
20
|
+
switch (level) {
|
|
21
|
+
case LogLevel::Debug:
|
|
22
|
+
os_log_debug(logger, "[%s] %s", tag, message.c_str());
|
|
23
|
+
break;
|
|
24
|
+
case LogLevel::Info:
|
|
25
|
+
os_log_info(logger, "[%s] %s", tag, message.c_str());
|
|
26
|
+
break;
|
|
27
|
+
case LogLevel::Warning:
|
|
28
|
+
os_log_error(logger, "[%s] %s", tag, message.c_str());
|
|
29
|
+
break;
|
|
30
|
+
case LogLevel::Error:
|
|
31
|
+
os_log_error(logger, "[%s] %s", tag, message.c_str());
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
#endif
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
} // namespace margelo::nitro
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ThreadUtils.cpp
|
|
3
|
+
// react-native-nitro
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 14.07.24.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#include "ThreadUtils.hpp"
|
|
9
|
+
#include <dispatch/dispatch.h>
|
|
10
|
+
#include <pthread.h>
|
|
11
|
+
#include <sstream>
|
|
12
|
+
#include <thread>
|
|
13
|
+
|
|
14
|
+
namespace margelo::nitro {
|
|
15
|
+
|
|
16
|
+
std::string ThreadUtils::getThreadName() {
|
|
17
|
+
// Try using pthread APIs
|
|
18
|
+
char threadName[64] = {};
|
|
19
|
+
int pthreadResult = pthread_getname_np(pthread_self(), threadName, sizeof(threadName));
|
|
20
|
+
if (pthreadResult == 0 && threadName[0] != '\0') {
|
|
21
|
+
// We have a pthread name
|
|
22
|
+
return std::string(threadName);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Try getting DispatchQueue name
|
|
26
|
+
const char* queueName = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
|
|
27
|
+
if (queueName != nullptr && queueName[0] != '\0') {
|
|
28
|
+
// We are on a DispatchQueue with a name
|
|
29
|
+
return std::string(queueName);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Fall back to std::this_thread
|
|
33
|
+
std::stringstream stream;
|
|
34
|
+
stream << std::this_thread::get_id();
|
|
35
|
+
std::string threadId = stream.str();
|
|
36
|
+
return std::string("Thread #") + threadId;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void ThreadUtils::setThreadName(const std::string& name) {
|
|
40
|
+
pthread_setname_np(name.c_str());
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
} // namespace margelo::nitro
|
|
@@ -31,7 +31,7 @@ extension SwiftClosure {
|
|
|
31
31
|
* This can then be called from both C++ and Swift.
|
|
32
32
|
*/
|
|
33
33
|
public init(wrappingClosure closure: @escaping () -> Void) {
|
|
34
|
-
// Wrap closure in void*, and increment
|
|
34
|
+
// Wrap closure in void*, and increment its ref count so it stays alive.
|
|
35
35
|
let context = Unmanaged.passRetained(ClosureWrapper(closure: closure)).toOpaque()
|
|
36
36
|
|
|
37
37
|
// Create a C-style Function Pointer, which calls the actual Swift closure.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-modules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"description": "Insanely fast native C++, Swift or Kotlin modules with a statically compiled binding layer to JSI.",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
"registry": "https://registry.npmjs.org/"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
|
-
"postinstall": "bun build || exit 0;",
|
|
63
62
|
"write-native-version": "version=$(node -p \"require('./package.json').version\") && sed -i '' \"s/#define NITRO_VERSION \\\".*\\\"/#define NITRO_VERSION \\\"$version\\\"/\" ./cpp/utils/NitroDefines.hpp",
|
|
64
63
|
"postversion": "bun run write-native-version",
|
|
65
64
|
"build": "rm -rf lib && bun typecheck && bob build",
|