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/cpp/jsi/JSICache.cpp
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#include "JSICache.hpp"
|
|
9
|
+
#include "CommonGlobals.hpp"
|
|
9
10
|
#include "JSIHelpers.hpp"
|
|
10
11
|
#include "NitroDefines.hpp"
|
|
11
|
-
#include "ObjectUtils.hpp"
|
|
12
12
|
|
|
13
13
|
namespace margelo::nitro {
|
|
14
14
|
|
|
@@ -54,11 +54,16 @@ JSICacheReference JSICache::getOrCreateCache(jsi::Runtime& runtime) {
|
|
|
54
54
|
// Wrap it in a jsi::Value using NativeState
|
|
55
55
|
jsi::Object cache(runtime);
|
|
56
56
|
cache.setNativeState(runtime, nativeState);
|
|
57
|
-
//
|
|
58
|
-
// We pass `allowCache = false` because we are the JSICache, and this would cause recursion.
|
|
59
|
-
ObjectUtils::defineGlobal(runtime, KnownGlobalPropertyName::JSI_CACHE, std::move(cache), /* allowCache */ false);
|
|
60
|
-
// Add it to our map of caches
|
|
57
|
+
// Add it to our map of caches first, because the next `::defineGlobal(...)` call will already be using it (recursively)
|
|
61
58
|
_globalCache[&runtime] = nativeState;
|
|
59
|
+
try {
|
|
60
|
+
// Call Object.defineProperty(global, ...) now with our cache (it internally already uses cache)
|
|
61
|
+
CommonGlobals::defineGlobal(runtime, KnownGlobalPropertyName::JSI_CACHE, std::move(cache));
|
|
62
|
+
} catch (...) {
|
|
63
|
+
// If `defineGlobal(...)` failed, we should remove it from `_globalCache` so we don't have invalid caches.
|
|
64
|
+
_globalCache.erase(&runtime);
|
|
65
|
+
throw;
|
|
66
|
+
}
|
|
62
67
|
// Return it
|
|
63
68
|
return JSICacheReference(nativeState);
|
|
64
69
|
}
|
package/cpp/jsi/JSICache.hpp
CHANGED
|
@@ -63,6 +63,7 @@ private:
|
|
|
63
63
|
std::vector<WeakReference<jsi::Object>> _objectCache;
|
|
64
64
|
std::vector<WeakReference<jsi::Function>> _functionCache;
|
|
65
65
|
std::vector<WeakReference<jsi::WeakObject>> _weakObjectCache;
|
|
66
|
+
std::vector<WeakReference<jsi::PropNameID>> _propNameIDCache;
|
|
66
67
|
std::vector<WeakReference<jsi::ArrayBuffer>> _arrayBufferCache;
|
|
67
68
|
|
|
68
69
|
private:
|
|
@@ -103,6 +104,11 @@ public:
|
|
|
103
104
|
_strongCache->_weakObjectCache.push_back(owning.weak());
|
|
104
105
|
return owning;
|
|
105
106
|
}
|
|
107
|
+
BorrowingReference<jsi::PropNameID> makeShared(jsi::PropNameID&& value) {
|
|
108
|
+
BorrowingReference<jsi::PropNameID> owning(new jsi::PropNameID(std::move(value)));
|
|
109
|
+
_strongCache->_propNameIDCache.push_back(owning.weak());
|
|
110
|
+
return owning;
|
|
111
|
+
}
|
|
106
112
|
BorrowingReference<jsi::ArrayBuffer> makeShared(jsi::ArrayBuffer&& value) {
|
|
107
113
|
BorrowingReference<jsi::ArrayBuffer> owning(new jsi::ArrayBuffer(std::move(value)));
|
|
108
114
|
_strongCache->_arrayBufferCache.push_back(owning.weak());
|
|
@@ -18,6 +18,7 @@ struct JSIConverter;
|
|
|
18
18
|
|
|
19
19
|
#include "AnyMap.hpp"
|
|
20
20
|
#include "JSIHelpers.hpp"
|
|
21
|
+
#include "PropNameIDCache.hpp"
|
|
21
22
|
#include <jsi/jsi.h>
|
|
22
23
|
#include <memory>
|
|
23
24
|
|
|
@@ -48,9 +49,9 @@ struct JSIConverter<std::shared_ptr<AnyMap>> final {
|
|
|
48
49
|
size_t size = propNames.size(runtime);
|
|
49
50
|
std::shared_ptr<AnyMap> map = AnyMap::make();
|
|
50
51
|
for (size_t i = 0; i < size; i++) {
|
|
51
|
-
|
|
52
|
-
jsi::Value jsValue = object.getProperty(runtime, jsKey);
|
|
53
|
-
map->setAny(jsKey
|
|
52
|
+
std::string jsKey = propNames.getValueAtIndex(runtime, i).getString(runtime).utf8(runtime);
|
|
53
|
+
jsi::Value jsValue = object.getProperty(runtime, PropNameIDCache::get(runtime, jsKey));
|
|
54
|
+
map->setAny(jsKey, JSIConverter<AnyValue>::fromJSI(runtime, jsValue));
|
|
54
55
|
}
|
|
55
56
|
return map;
|
|
56
57
|
}
|
|
@@ -50,7 +50,7 @@ struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_v<T, jsi::MutableBuffer
|
|
|
50
50
|
if (!object.isArrayBuffer(runtime)) [[unlikely]] {
|
|
51
51
|
throw std::invalid_argument("Object \"" + arg.toString(runtime).utf8(runtime) +
|
|
52
52
|
"\" is not an ArrayBuffer! "
|
|
53
|
-
"Are you maybe passing a TypedArray (e.g. Uint8Array)? Try to pass
|
|
53
|
+
"Are you maybe passing a TypedArray (e.g. Uint8Array)? Try to pass its `.buffer` value.");
|
|
54
54
|
}
|
|
55
55
|
#endif
|
|
56
56
|
if (object.hasNativeState<MutableBufferNativeState>(runtime)) {
|
|
@@ -69,7 +69,7 @@ struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_v<T, jsi::MutableBuffer
|
|
|
69
69
|
}
|
|
70
70
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const std::shared_ptr<jsi::MutableBuffer>& buffer) {
|
|
71
71
|
if (auto jsBuffer = std::dynamic_pointer_cast<JSArrayBuffer>(buffer)) {
|
|
72
|
-
// It already is a JSBuffer! Let's try to just get
|
|
72
|
+
// It already is a JSBuffer! Let's try to just get its existing jsi::Value...
|
|
73
73
|
auto jsValue = jsBuffer->getJSReference();
|
|
74
74
|
if (jsValue != nullptr) [[likely]] {
|
|
75
75
|
return jsi::Value(runtime, *jsValue);
|
|
@@ -14,6 +14,8 @@ struct JSIConverter;
|
|
|
14
14
|
|
|
15
15
|
#include "JSIConverter.hpp"
|
|
16
16
|
|
|
17
|
+
#include "CommonGlobals.hpp"
|
|
18
|
+
#include "PropNameIDCache.hpp"
|
|
17
19
|
#include <chrono>
|
|
18
20
|
#include <jsi/jsi.h>
|
|
19
21
|
#include <memory>
|
|
@@ -38,15 +40,15 @@ struct JSIConverter<std::chrono::system_clock::time_point> final {
|
|
|
38
40
|
|
|
39
41
|
jsi::Object object = arg.asObject(runtime);
|
|
40
42
|
#ifdef NITRO_DEBUG
|
|
41
|
-
if (!object.hasProperty(runtime, "getTime")) {
|
|
43
|
+
if (!object.hasProperty(runtime, PropNameIDCache::get(runtime, "getTime"))) {
|
|
42
44
|
throw std::invalid_argument("Object \"" + arg.toString(runtime).utf8(runtime) +
|
|
43
45
|
"\" does not have a .getTime() function! "
|
|
44
46
|
"It's not a valid Date object.");
|
|
45
47
|
}
|
|
46
48
|
#endif
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
jsi::Function getTimeFunc =
|
|
51
|
+
object.getProperty(runtime, PropNameIDCache::get(runtime, "getTime")).getObject(runtime).getFunction(runtime);
|
|
50
52
|
double msSinceEpoch = getTimeFunc.callWithThis(runtime, object).getNumber();
|
|
51
53
|
|
|
52
54
|
// ms -> std::chrono::system_clock::time_point
|
|
@@ -62,19 +64,15 @@ struct JSIConverter<std::chrono::system_clock::time_point> final {
|
|
|
62
64
|
auto ms = chrono::duration_cast<chrono::milliseconds>(date.time_since_epoch()).count();
|
|
63
65
|
auto msSinceEpoch = static_cast<double>(ms);
|
|
64
66
|
|
|
65
|
-
//
|
|
66
|
-
jsi::
|
|
67
|
-
|
|
68
|
-
jsi::Value jsDate = dateCtor.callAsConstructor(runtime, {jsi::Value(msSinceEpoch)});
|
|
67
|
+
// 2. Call `new Date(...)` with the milliseconds since epoch
|
|
68
|
+
jsi::Value jsDate = CommonGlobals::Date::callConstructor(runtime, msSinceEpoch);
|
|
69
69
|
return jsDate;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
73
73
|
if (value.isObject()) {
|
|
74
74
|
jsi::Object object = value.getObject(runtime);
|
|
75
|
-
|
|
76
|
-
jsi::Function dateCtor = runtime.global().getPropertyAsFunction(runtime, "Date");
|
|
77
|
-
return object.instanceOf(runtime, dateCtor);
|
|
75
|
+
return CommonGlobals::Date::isInstanceOf(runtime, object);
|
|
78
76
|
}
|
|
79
77
|
return false;
|
|
80
78
|
}
|
|
@@ -10,9 +10,10 @@ template <typename T, typename Enable>
|
|
|
10
10
|
struct JSIConverter;
|
|
11
11
|
} // namespace margelo::nitro
|
|
12
12
|
|
|
13
|
+
#include "CommonGlobals.hpp"
|
|
13
14
|
#include "JSIConverter.hpp"
|
|
14
|
-
|
|
15
15
|
#include "NitroTypeInfo.hpp"
|
|
16
|
+
#include "PropNameIDCache.hpp"
|
|
16
17
|
#include <exception>
|
|
17
18
|
#include <jsi/jsi.h>
|
|
18
19
|
|
|
@@ -25,8 +26,8 @@ template <>
|
|
|
25
26
|
struct JSIConverter<std::exception_ptr> final {
|
|
26
27
|
static inline std::exception_ptr fromJSI(jsi::Runtime& runtime, const jsi::Value& error) {
|
|
27
28
|
jsi::Object object = error.asObject(runtime);
|
|
28
|
-
std::string name = object.getProperty(runtime, "name").asString(runtime).utf8(runtime);
|
|
29
|
-
std::string message = object.getProperty(runtime, "message").asString(runtime).utf8(runtime);
|
|
29
|
+
std::string name = object.getProperty(runtime, PropNameIDCache::get(runtime, "name")).asString(runtime).utf8(runtime);
|
|
30
|
+
std::string message = object.getProperty(runtime, PropNameIDCache::get(runtime, "message")).asString(runtime).utf8(runtime);
|
|
30
31
|
return std::make_exception_ptr(std::runtime_error(name + ": " + message));
|
|
31
32
|
}
|
|
32
33
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const std::exception_ptr& exception) {
|
|
@@ -51,8 +52,7 @@ struct JSIConverter<std::exception_ptr> final {
|
|
|
51
52
|
return false;
|
|
52
53
|
}
|
|
53
54
|
jsi::Object object = value.getObject(runtime);
|
|
54
|
-
|
|
55
|
-
return object.instanceOf(runtime, errorCtor);
|
|
55
|
+
return CommonGlobals::Error::isInstanceOf(runtime, object);
|
|
56
56
|
}
|
|
57
57
|
};
|
|
58
58
|
|
|
@@ -16,6 +16,7 @@ struct JSIConverter;
|
|
|
16
16
|
#include "JSCallback.hpp"
|
|
17
17
|
#include "JSICache.hpp"
|
|
18
18
|
#include "PromiseType.hpp"
|
|
19
|
+
#include "PropNameIDCache.hpp"
|
|
19
20
|
#include <jsi/jsi.h>
|
|
20
21
|
|
|
21
22
|
namespace margelo::nitro {
|
|
@@ -56,7 +57,9 @@ struct JSIConverter<std::function<R(Args...)>> final {
|
|
|
56
57
|
}
|
|
57
58
|
return callHybridFunction(function, runtime, args, std::index_sequence_for<Args...>{});
|
|
58
59
|
};
|
|
59
|
-
return jsi::Function::createFromHostFunction(runtime,
|
|
60
|
+
return jsi::Function::createFromHostFunction(runtime, //
|
|
61
|
+
PropNameIDCache::get(runtime, "hostFunction"), //
|
|
62
|
+
sizeof...(Args), //
|
|
60
63
|
std::move(jsFunction));
|
|
61
64
|
}
|
|
62
65
|
|
|
@@ -65,7 +65,7 @@ struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_v<T, jsi::NativeState>>
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
if constexpr (std::is_base_of_v<HybridObject, TPointee>) {
|
|
68
|
-
// It's a HybridObject - use
|
|
68
|
+
// It's a HybridObject - use its internal constructor which caches jsi::Objects for proper memory management!
|
|
69
69
|
return arg->toObject(runtime);
|
|
70
70
|
} else {
|
|
71
71
|
// It's any other kind of jsi::NativeState - just create it as normal. This will not have a prototype then!
|
|
@@ -11,10 +11,12 @@ template <typename T, typename Enable>
|
|
|
11
11
|
struct JSIConverter;
|
|
12
12
|
} // namespace margelo::nitro
|
|
13
13
|
|
|
14
|
+
#include "CommonGlobals.hpp"
|
|
14
15
|
#include "JSIConverter.hpp"
|
|
15
16
|
#include "NitroTypeInfo.hpp"
|
|
16
17
|
#include "Null.hpp"
|
|
17
18
|
#include "Promise.hpp"
|
|
19
|
+
#include "PropNameIDCache.hpp"
|
|
18
20
|
#include <exception>
|
|
19
21
|
#include <jsi/jsi.h>
|
|
20
22
|
#include <memory>
|
|
@@ -44,7 +46,7 @@ struct JSIConverter<std::shared_ptr<Promise<TResult>>> final {
|
|
|
44
46
|
|
|
45
47
|
// Chain .then listeners on JS Promise (onResolved and onRejected)
|
|
46
48
|
jsi::Object jsPromise = value.asObject(runtime);
|
|
47
|
-
jsi::Function thenFn = jsPromise.
|
|
49
|
+
jsi::Function thenFn = jsPromise.getProperty(runtime, PropNameIDCache::get(runtime, "then")).asObject(runtime).getFunction(runtime);
|
|
48
50
|
thenFn.callWithThis(runtime, jsPromise, thenCallback, catchCallback);
|
|
49
51
|
|
|
50
52
|
return promise;
|
|
@@ -53,7 +55,6 @@ struct JSIConverter<std::shared_ptr<Promise<TResult>>> final {
|
|
|
53
55
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const std::shared_ptr<Promise<TResult>>& promise) {
|
|
54
56
|
if (promise->isPending()) {
|
|
55
57
|
// Get Promise ctor from global
|
|
56
|
-
jsi::Function promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
|
|
57
58
|
jsi::HostFunctionType executor = [promise](jsi::Runtime& runtime, const jsi::Value&, const jsi::Value* arguments,
|
|
58
59
|
size_t) -> jsi::Value {
|
|
59
60
|
// Add resolver listener
|
|
@@ -72,27 +73,21 @@ struct JSIConverter<std::shared_ptr<Promise<TResult>>> final {
|
|
|
72
73
|
|
|
73
74
|
return jsi::Value::undefined();
|
|
74
75
|
};
|
|
75
|
-
|
|
76
|
-
return promiseCtor.callAsConstructor(
|
|
77
|
-
runtime, jsi::Function::createFromHostFunction(runtime, jsi::PropNameID::forUtf8(runtime, "executor"), 2, executor));
|
|
76
|
+
return CommonGlobals::Promise::callConstructor(runtime, std::move(executor));
|
|
78
77
|
} else if (promise->isResolved()) {
|
|
79
78
|
// Promise is already resolved - just return immediately
|
|
80
|
-
jsi::Object promiseObject = runtime.global().getPropertyAsObject(runtime, "Promise");
|
|
81
|
-
jsi::Function createResolvedPromise = promiseObject.getPropertyAsFunction(runtime, "resolve");
|
|
82
79
|
if constexpr (std::is_void_v<TResult>) {
|
|
83
80
|
// It's resolving to void.
|
|
84
|
-
return
|
|
81
|
+
return CommonGlobals::Promise::resolved(runtime);
|
|
85
82
|
} else {
|
|
86
83
|
// It's resolving to a type.
|
|
87
84
|
jsi::Value result = JSIConverter<TResult>::toJSI(runtime, promise->getResult());
|
|
88
|
-
return
|
|
85
|
+
return CommonGlobals::Promise::resolved(runtime, std::move(result));
|
|
89
86
|
}
|
|
90
87
|
} else if (promise->isRejected()) {
|
|
91
88
|
// Promise is already rejected - just return immediately
|
|
92
|
-
jsi::Object promiseObject = runtime.global().getPropertyAsObject(runtime, "Promise");
|
|
93
|
-
jsi::Function createRejectedPromise = promiseObject.getPropertyAsFunction(runtime, "reject");
|
|
94
89
|
jsi::Value error = JSIConverter<std::exception_ptr>::toJSI(runtime, promise->getError());
|
|
95
|
-
return
|
|
90
|
+
return CommonGlobals::Promise::rejected(runtime, std::move(error));
|
|
96
91
|
} else {
|
|
97
92
|
std::string typeName = TypeInfo::getFriendlyTypename<TResult>(true);
|
|
98
93
|
throw std::runtime_error("Promise<" + typeName + "> has invalid state!");
|
|
@@ -104,8 +99,7 @@ struct JSIConverter<std::shared_ptr<Promise<TResult>>> final {
|
|
|
104
99
|
return false;
|
|
105
100
|
}
|
|
106
101
|
jsi::Object object = value.getObject(runtime);
|
|
107
|
-
|
|
108
|
-
return object.instanceOf(runtime, promiseCtor);
|
|
102
|
+
return CommonGlobals::Promise::isInstanceOf(runtime, object);
|
|
109
103
|
}
|
|
110
104
|
};
|
|
111
105
|
|
|
@@ -14,6 +14,7 @@ struct JSIConverter;
|
|
|
14
14
|
|
|
15
15
|
#include "AnyMap.hpp"
|
|
16
16
|
#include "JSIHelpers.hpp"
|
|
17
|
+
#include "PropNameIDCache.hpp"
|
|
17
18
|
#include <jsi/jsi.h>
|
|
18
19
|
#include <unordered_map>
|
|
19
20
|
|
|
@@ -33,7 +34,7 @@ struct JSIConverter<std::unordered_map<std::string, ValueType>> final {
|
|
|
33
34
|
map.reserve(length);
|
|
34
35
|
for (size_t i = 0; i < length; ++i) {
|
|
35
36
|
std::string key = propertyNames.getValueAtIndex(runtime, i).asString(runtime).utf8(runtime);
|
|
36
|
-
jsi::Value value = object.getProperty(runtime, key
|
|
37
|
+
jsi::Value value = object.getProperty(runtime, PropNameIDCache::get(runtime, key));
|
|
37
38
|
map.emplace(key, JSIConverter<ValueType>::fromJSI(runtime, value));
|
|
38
39
|
}
|
|
39
40
|
return map;
|
package/cpp/jsi/JSIHelpers.hpp
CHANGED
|
@@ -42,7 +42,7 @@ static inline bool isPlainObject(jsi::Runtime& runtime, const jsi::Object& objec
|
|
|
42
42
|
* Get an ID for the given Runtime.
|
|
43
43
|
*
|
|
44
44
|
* The ID usually consists of a Runtime description (e.g. "HermesRuntime"),
|
|
45
|
-
* and
|
|
45
|
+
* and its Thread's name (e.g. "com.facebook.react.runtime.JavaScript")
|
|
46
46
|
*/
|
|
47
47
|
static inline std::string getRuntimeId(jsi::Runtime& runtime) {
|
|
48
48
|
std::string threadName = ThreadUtils::getThreadName();
|
|
@@ -22,7 +22,9 @@ private:
|
|
|
22
22
|
|
|
23
23
|
public:
|
|
24
24
|
template <typename... Args>
|
|
25
|
-
static void log([[maybe_unused]] LogLevel level,
|
|
25
|
+
static void log([[maybe_unused]] LogLevel level, //
|
|
26
|
+
[[maybe_unused]] const char* NON_NULL tag, //
|
|
27
|
+
[[maybe_unused]] const char* NON_NULL format, //
|
|
26
28
|
[[maybe_unused]] Args... args) {
|
|
27
29
|
#ifdef NITRO_DEBUG
|
|
28
30
|
// 1. Make sure args can be passed to sprintf(..)
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#include "HybridObjectPrototype.hpp"
|
|
9
|
+
#include "CommonGlobals.hpp"
|
|
9
10
|
#include "NitroDefines.hpp"
|
|
10
11
|
#include "NitroLogger.hpp"
|
|
11
12
|
#include "NitroTypeInfo.hpp"
|
|
12
|
-
#include "ObjectUtils.hpp"
|
|
13
13
|
|
|
14
14
|
namespace margelo::nitro {
|
|
15
15
|
|
|
@@ -39,19 +39,19 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
|
|
|
39
39
|
std::string typeName = TypeInfo::getFriendlyTypename(prototype->getNativeInstanceId(), true);
|
|
40
40
|
Logger::log(LogLevel::Info, TAG, "Creating new JS prototype for C++ instance type \"%s\"...", typeName.c_str());
|
|
41
41
|
jsi::Value basePrototype = createPrototype(runtime, prototype->getBase());
|
|
42
|
-
jsi::Object object =
|
|
42
|
+
jsi::Object object = CommonGlobals::Object::create(runtime, basePrototype);
|
|
43
43
|
|
|
44
44
|
// 4. Add all Hybrid Methods to it
|
|
45
45
|
for (const auto& method : prototype->getMethods()) {
|
|
46
46
|
// method()
|
|
47
47
|
const std::string& name = method.first;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
|
|
49
|
+
PlainPropertyDescriptor{
|
|
50
|
+
.configurable = false,
|
|
51
|
+
.enumerable = true,
|
|
52
|
+
.value = method.second.toJSFunction(runtime),
|
|
53
|
+
.writable = false,
|
|
54
|
+
});
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// 5. Add all properties (getter + setter) to it using defineProperty
|
|
@@ -61,37 +61,37 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
|
|
|
61
61
|
const std::string& name = getter.first;
|
|
62
62
|
if (isReadonly) {
|
|
63
63
|
// get
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
|
|
65
|
+
ComputedReadonlyPropertyDescriptor{// readonly
|
|
66
|
+
.configurable = false,
|
|
67
|
+
.enumerable = true,
|
|
68
|
+
.get = getter.second.toJSFunction(runtime)});
|
|
69
69
|
} else {
|
|
70
70
|
// get + set
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
71
|
+
CommonGlobals::Object::defineProperty(runtime, object, name.c_str(),
|
|
72
|
+
ComputedPropertyDescriptor{// readonly with setter
|
|
73
|
+
.configurable = false,
|
|
74
|
+
.enumerable = false,
|
|
75
|
+
.get = getter.second.toJSFunction(runtime),
|
|
76
|
+
.set = setter->second.toJSFunction(runtime)});
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// 6. In DEBUG, add a __type info to the prototype object.
|
|
81
81
|
#ifdef NITRO_DEBUG
|
|
82
82
|
std::string prototypeName = "Prototype<" + typeName + ">";
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
CommonGlobals::Object::defineProperty(runtime, object, "__type",
|
|
84
|
+
PlainPropertyDescriptor{
|
|
85
|
+
.configurable = false,
|
|
86
|
+
.enumerable = true,
|
|
87
|
+
.value = jsi::String::createFromUtf8(runtime, prototypeName),
|
|
88
|
+
.writable = false,
|
|
89
|
+
});
|
|
90
90
|
#endif
|
|
91
91
|
|
|
92
92
|
// 7. In DEBUG, freeze the prototype.
|
|
93
93
|
#ifdef NITRO_DEBUG
|
|
94
|
-
|
|
94
|
+
CommonGlobals::Object::freeze(runtime, object);
|
|
95
95
|
#endif
|
|
96
96
|
|
|
97
97
|
// 8. Throw it into our cache so the next lookup can be cached and therefore faster
|
|
@@ -63,7 +63,7 @@ private:
|
|
|
63
63
|
return node;
|
|
64
64
|
} else {
|
|
65
65
|
if (node->hasBase()) {
|
|
66
|
-
// We didn't find a match in this prototype, let's recursively try
|
|
66
|
+
// We didn't find a match in this prototype, let's recursively try its parent!
|
|
67
67
|
return getOrExtendPrototype<Derived>(node->getBase());
|
|
68
68
|
} else {
|
|
69
69
|
// We didn't find `Derived` and we don't have a base- add a child and shift the tree by one.
|
|
@@ -27,7 +27,7 @@ public:
|
|
|
27
27
|
public:
|
|
28
28
|
/**
|
|
29
29
|
* Registers the given HybridObject in the `HybridObjectRegistry`.
|
|
30
|
-
* It will be uniquely identified via
|
|
30
|
+
* It will be uniquely identified via its `hybridObjectName`, and can be initialized from
|
|
31
31
|
* JS using `NitroModules.createHybridObject<T>(name)` - which will call the `constructorFn` here.
|
|
32
32
|
*/
|
|
33
33
|
static void registerHybridObjectConstructor(const std::string& hybridObjectName, HybridObjectConstructorFn&& constructorFn);
|
|
@@ -15,7 +15,7 @@ namespace margelo::nitro {
|
|
|
15
15
|
using namespace facebook;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* A Dispatcher that uses react::CallInvoker for
|
|
18
|
+
* A Dispatcher that uses react::CallInvoker for its implementation
|
|
19
19
|
*/
|
|
20
20
|
class CallInvokerDispatcher final : public Dispatcher {
|
|
21
21
|
public:
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#include "Dispatcher.hpp"
|
|
9
|
+
#include "CommonGlobals.hpp"
|
|
9
10
|
#include "JSIConverter.hpp"
|
|
10
11
|
#include "JSIHelpers.hpp"
|
|
11
12
|
#include "NitroDefines.hpp"
|
|
12
13
|
#include "NitroLogger.hpp"
|
|
13
|
-
#include "ObjectUtils.hpp"
|
|
14
14
|
|
|
15
15
|
namespace margelo::nitro {
|
|
16
16
|
|
|
@@ -30,7 +30,7 @@ void Dispatcher::installRuntimeGlobalDispatcher(jsi::Runtime& runtime, std::shar
|
|
|
30
30
|
|
|
31
31
|
// Inject the dispatcher into Runtime global (runtime will hold a strong reference)
|
|
32
32
|
jsi::Value dispatcherHolder = JSIConverter<std::shared_ptr<Dispatcher>>::toJSI(runtime, dispatcher);
|
|
33
|
-
|
|
33
|
+
CommonGlobals::defineGlobal(runtime, KnownGlobalPropertyName::DISPATCHER, std::move(dispatcherHolder));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
std::shared_ptr<Dispatcher> Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime& runtime) {
|
|
@@ -57,15 +57,15 @@ std::shared_ptr<Dispatcher> Dispatcher::getRuntimeGlobalDispatcher(jsi::Runtime&
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
jsi::Value Dispatcher::getRuntimeGlobalDispatcherHolder(jsi::Runtime& runtime) {
|
|
60
|
-
const
|
|
61
|
-
if (!runtime.global().hasProperty(runtime,
|
|
60
|
+
const jsi::PropNameID& dispatcherHolderPropName = CommonGlobals::getKnownGlobalPropertyName(runtime, KnownGlobalPropertyName::DISPATCHER);
|
|
61
|
+
if (!runtime.global().hasProperty(runtime, dispatcherHolderPropName)) [[unlikely]] {
|
|
62
62
|
throw std::runtime_error("The `jsi::Runtime` \"" + getRuntimeId(runtime) +
|
|
63
63
|
"\" does not support Callbacks or Promises because it does not have a `Dispatcher` installed!\n"
|
|
64
64
|
"To use Callbacks and Promises follow these steps;\n"
|
|
65
65
|
"1. Subclass `Dispatcher` with your implementation of `runAsync`/`runSync` for your Thread.\n"
|
|
66
66
|
"2. Call `Dispatcher::installRuntimeGlobalDispatcher(...)` with your `Runtime` and your `Dispatcher`.");
|
|
67
67
|
}
|
|
68
|
-
return runtime.global().getProperty(runtime,
|
|
68
|
+
return runtime.global().getProperty(runtime, dispatcherHolderPropName);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
} // namespace margelo::nitro
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
namespace margelo::nitro {
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
21
|
+
* A `BorrowingReference<T>` is a smart-pointer that holds a strong reference to a pointer.
|
|
22
22
|
* You can have multiple `BorrowingReference<T>` instances point to the same pointer, as they internally keep a ref-count.
|
|
23
|
-
* As opposed to a `shared_ptr<T>`,
|
|
23
|
+
* As opposed to a `shared_ptr<T>`, a `BorrowingReference<T>` can also be imperatively manually deleted, even if there
|
|
24
24
|
* are multiple strong references still holding onto the pointer.
|
|
25
25
|
* This is useful in cases where the `BorrowingReference` might keep a reference alive, but an external value holder
|
|
26
26
|
* is actually responsible for truly deleting the underlying value - like a `jsi::Runtime` for a `jsi::Value`.
|
|
27
27
|
*
|
|
28
|
-
*
|
|
29
|
-
* A `WeakReference<T>` can be locked to get
|
|
28
|
+
* A `BorrowingReference<T>` can be weakified, which gives the user a `WeakReference<T>`.
|
|
29
|
+
* A `WeakReference<T>` can be locked to get a `BorrowingReference<T>` again, assuming it has not been deleted yet.
|
|
30
30
|
*/
|
|
31
31
|
template <typename T>
|
|
32
32
|
class BorrowingReference final {
|
|
@@ -120,7 +120,7 @@ public:
|
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
|
-
* Get a
|
|
123
|
+
* Get a weak reference to this borrowing reference.
|
|
124
124
|
*/
|
|
125
125
|
[[nodiscard]]
|
|
126
126
|
WeakReference<T> weak() const {
|
|
@@ -220,4 +220,4 @@ private:
|
|
|
220
220
|
|
|
221
221
|
} // namespace margelo::nitro
|
|
222
222
|
|
|
223
|
-
#include "WeakReference+
|
|
223
|
+
#include "WeakReference+Borrowing.hpp"
|