react-native-nitro-modules 0.21.0 → 0.22.1
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 +4 -1
- package/README.md +1 -1
- package/android/CMakeLists.txt +1 -0
- package/android/build.gradle +4 -2
- package/android/gradle.properties +2 -2
- package/android/src/main/cpp/platform/ThreadUtils.cpp +4 -4
- package/android/src/main/cpp/registry/JHybridObjectRegistry.hpp +2 -0
- package/android/src/main/java/com/margelo/nitro/core/HybridObject.kt +10 -9
- package/android/src/main/java/com/margelo/nitro/core/HybridObjectInitializer.java +4 -0
- package/android/src/main/java/com/margelo/nitro/core/HybridObjectRegistry.java +2 -0
- package/android/src/main/java/com/margelo/nitro/views/HybridView.kt +23 -0
- package/cpp/core/ArrayBuffer.cpp +2 -2
- package/cpp/core/ArrayBuffer.hpp +3 -3
- package/cpp/core/HybridFunction.hpp +1 -1
- package/cpp/core/HybridObject.cpp +7 -6
- package/cpp/core/HybridObject.hpp +3 -3
- package/cpp/core/Promise.hpp +1 -1
- package/cpp/entrypoint/HybridNitroModulesProxy.cpp +8 -0
- package/cpp/entrypoint/HybridNitroModulesProxy.hpp +1 -0
- package/cpp/jsi/JSICache.cpp +5 -4
- package/cpp/jsi/JSICache.hpp +21 -15
- package/cpp/jsi/JSIConverter+Exception.hpp +1 -1
- package/cpp/jsi/JSIConverter+Function.hpp +3 -2
- package/cpp/jsi/JSIConverter+HostObject.hpp +1 -1
- package/cpp/jsi/JSIConverter+HybridObject.hpp +1 -1
- package/cpp/jsi/JSIConverter+Tuple.hpp +1 -1
- package/cpp/jsi/JSIConverter+Variant.hpp +1 -1
- package/cpp/jsi/JSIHelpers.hpp +1 -1
- package/cpp/prototype/HybridObjectPrototype.cpp +3 -3
- package/cpp/prototype/HybridObjectPrototype.hpp +2 -2
- package/cpp/registry/HybridObjectRegistry.cpp +25 -12
- package/cpp/registry/HybridObjectRegistry.hpp +1 -0
- package/cpp/utils/AssertPromiseState.hpp +1 -1
- package/cpp/utils/BorrowingReference.hpp +163 -54
- package/cpp/utils/NitroDefines.hpp +10 -1
- package/cpp/utils/NitroHash.hpp +17 -0
- package/cpp/utils/{TypeInfo.hpp → NitroTypeInfo.hpp} +1 -1
- package/cpp/utils/OwningLock.hpp +14 -14
- package/cpp/utils/ReferenceState.hpp +40 -0
- package/cpp/utils/WeakReference+Owning.hpp +33 -0
- package/cpp/utils/WeakReference.hpp +102 -0
- package/cpp/views/CachedProp.hpp +43 -0
- package/ios/core/AnyMapHolder.swift +8 -8
- package/ios/core/HybridContext.hpp +1 -1
- package/ios/core/{HybridObjectSpec.swift → HybridObject.swift} +10 -2
- package/ios/turbomodule/NativeNitroModules+NewArch.mm +1 -1
- package/ios/utils/RuntimeError.hpp +1 -1
- package/ios/views/HybridView.swift +41 -0
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/views/HybridView.js +17 -0
- package/lib/commonjs/views/HybridView.js.map +1 -0
- package/lib/commonjs/views/getHostComponent.js +22 -0
- package/lib/commonjs/views/getHostComponent.js.map +1 -0
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/views/HybridView.js +30 -0
- package/lib/module/views/HybridView.js.map +1 -0
- package/lib/module/views/getHostComponent.js +15 -0
- package/lib/module/views/getHostComponent.js.map +1 -0
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/typescript/NitroModulesProxy.d.ts +7 -0
- package/lib/typescript/NitroModulesProxy.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/views/HybridView.d.ts +35 -0
- package/lib/typescript/views/HybridView.d.ts.map +1 -0
- package/lib/typescript/views/getHostComponent.d.ts +13 -0
- package/lib/typescript/views/getHostComponent.d.ts.map +1 -0
- package/package.json +3 -2
- package/src/NitroModulesProxy.ts +8 -0
- package/src/index.ts +1 -0
- package/src/views/HybridView.ts +37 -0
- package/src/views/getHostComponent.ts +26 -0
- package/cpp/utils/BorrowingReference+Owning.hpp +0 -36
- package/cpp/utils/OwningReference.hpp +0 -237
package/NitroModules.podspec
CHANGED
|
@@ -43,6 +43,7 @@ Pod::Spec.new do |s|
|
|
|
43
43
|
"cpp/threading/Dispatcher.hpp",
|
|
44
44
|
"cpp/utils/NitroHash.hpp",
|
|
45
45
|
"cpp/utils/NitroDefines.hpp",
|
|
46
|
+
"cpp/views/CachedProp.hpp",
|
|
46
47
|
# Public iOS-specific headers that will be exposed in modulemap (for Swift)
|
|
47
48
|
"ios/core/ArrayBufferHolder.hpp",
|
|
48
49
|
"ios/core/AnyMapHolder.hpp",
|
|
@@ -60,11 +61,13 @@ Pod::Spec.new do |s|
|
|
|
60
61
|
"SWIFT_OBJC_INTEROP_MODE" => "objcxx",
|
|
61
62
|
# Enables stricter modular headers
|
|
62
63
|
"DEFINES_MODULE" => "YES",
|
|
63
|
-
# C++ compiler flags, mainly for folly.
|
|
64
|
+
# C++ compiler flags, mainly for RN version and folly.
|
|
64
65
|
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
# Nitro depends on JSI.
|
|
67
69
|
s.dependency 'React-jsi'
|
|
70
|
+
# For React Native, we implement nitro::Dispatcher using react::CallInvoker
|
|
68
71
|
s.dependency 'React-callinvoker'
|
|
69
72
|
install_modules_dependencies(s)
|
|
70
73
|
end
|
package/README.md
CHANGED
|
@@ -208,7 +208,7 @@ The following C++ / JS types are supported out of the box:
|
|
|
208
208
|
<tr>
|
|
209
209
|
<td>..any <code><a href="./src/HybridObject.ts">HybridObject</a></code></td>
|
|
210
210
|
<td><code>std::shared_ptr<<a href="./cpp/core/HybridObject.hpp">HybridObject</a>></code></td>
|
|
211
|
-
<td><code><a href="./ios/core/
|
|
211
|
+
<td><code><a href="./ios/core/HybridObject.swift">HybridObject</a></code></td>
|
|
212
212
|
<td><code><a href="./android/src/main/java/com/margelo/nitro/core/HybridObject.kt">HybridObject</a></code></td>
|
|
213
213
|
</tr>
|
|
214
214
|
<tr>
|
package/android/CMakeLists.txt
CHANGED
package/android/build.gradle
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import groovy.json.JsonSlurper
|
|
2
|
+
|
|
1
3
|
buildscript {
|
|
2
4
|
repositories {
|
|
3
5
|
google()
|
|
@@ -5,7 +7,7 @@ buildscript {
|
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
dependencies {
|
|
8
|
-
classpath "com.android.tools.build:gradle:8.
|
|
10
|
+
classpath "com.android.tools.build:gradle:8.8.0"
|
|
9
11
|
}
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -154,7 +156,7 @@ if (isNewArchitectureEnabled()) {
|
|
|
154
156
|
}
|
|
155
157
|
}
|
|
156
158
|
|
|
157
|
-
|
|
159
|
+
tasks.register('prepareHeaders', Copy) {
|
|
158
160
|
from fileTree('./src/main/cpp').filter { it.isFile() }
|
|
159
161
|
from fileTree('../cpp/').filter { it.isFile() }
|
|
160
162
|
include "*.hpp"
|
|
@@ -17,12 +17,12 @@ namespace margelo::nitro {
|
|
|
17
17
|
std::string ThreadUtils::getThreadName() {
|
|
18
18
|
#ifdef HAVE_ANDROID_PTHREAD_SETNAME_NP
|
|
19
19
|
// Try using pthread APIs
|
|
20
|
-
pthread_t
|
|
21
|
-
char
|
|
20
|
+
pthread_t thisThread = pthread_self();
|
|
21
|
+
char threadName[16]; // Thread name length limit in Android is 16 characters
|
|
22
22
|
|
|
23
|
-
int result = pthread_getname_np(
|
|
23
|
+
int result = pthread_getname_np(thisThread, threadName, sizeof(threadName));
|
|
24
24
|
if (result == 0) {
|
|
25
|
-
return std::string(
|
|
25
|
+
return std::string(threadName);
|
|
26
26
|
}
|
|
27
27
|
#endif
|
|
28
28
|
|
|
@@ -20,6 +20,8 @@ public:
|
|
|
20
20
|
static auto constexpr kJavaDescriptor = "Lcom/margelo/nitro/core/HybridObjectRegistry;";
|
|
21
21
|
|
|
22
22
|
public:
|
|
23
|
+
[[deprecated("HybridObjects should be registered from C++ instead. Either autolink them using `nitro.json`, "
|
|
24
|
+
"or add them manually in the C++ HybridObjectRegistry.")]]
|
|
23
25
|
static void registerHybridObjectConstructor(jni::alias_ref<jni::JClass> clazz, std::string hybridObjectName,
|
|
24
26
|
jni::alias_ref<JHybridObjectInitializer> constructorFn);
|
|
25
27
|
|
|
@@ -4,16 +4,12 @@ import androidx.annotation.Keep
|
|
|
4
4
|
import com.facebook.jni.HybridData
|
|
5
5
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
6
6
|
|
|
7
|
-
interface ExtendableHybridClass {
|
|
8
|
-
fun updateNative(hybridData: HybridData)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
7
|
/**
|
|
12
8
|
* A base class for all Kotlin-based HybridObjects.
|
|
13
9
|
*/
|
|
14
10
|
@Keep
|
|
15
11
|
@DoNotStrip
|
|
16
|
-
abstract class HybridObject
|
|
12
|
+
abstract class HybridObject {
|
|
17
13
|
/**
|
|
18
14
|
* Get the memory size of the Kotlin instance (plus any external heap allocations),
|
|
19
15
|
* in bytes.
|
|
@@ -32,7 +28,8 @@ abstract class HybridObject: ExtendableHybridClass {
|
|
|
32
28
|
*/
|
|
33
29
|
@get:DoNotStrip
|
|
34
30
|
@get:Keep
|
|
35
|
-
|
|
31
|
+
open val memorySize: Long
|
|
32
|
+
get() = 0L
|
|
36
33
|
|
|
37
34
|
/**
|
|
38
35
|
* Holds the native C++ instance.
|
|
@@ -42,10 +39,14 @@ abstract class HybridObject: ExtendableHybridClass {
|
|
|
42
39
|
private var mHybridData: HybridData? = null
|
|
43
40
|
|
|
44
41
|
/**
|
|
45
|
-
*
|
|
46
|
-
* `
|
|
42
|
+
* If `HybridObject` is subclassed, the sub-class needs to create it's own `HybridData`
|
|
43
|
+
* with a C++ `jni::HybridClass` representing the subclass directly.
|
|
44
|
+
* Then, that `HybridData` must be passed upwards to `HybridObject` using `updateNative(..)`.
|
|
45
|
+
*
|
|
46
|
+
* This must happen for each sub/base class in the whole inheritance chain to ensure
|
|
47
|
+
* overrides and type-erasure works as expected.
|
|
47
48
|
*/
|
|
48
|
-
|
|
49
|
+
protected open fun updateNative(hybridData: HybridData) {
|
|
49
50
|
mHybridData = hybridData
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -4,8 +4,12 @@ import androidx.annotation.Keep;
|
|
|
4
4
|
|
|
5
5
|
import com.facebook.proguard.annotations.DoNotStrip;
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated HybridObjects should be registered from C++ instead. Either autolink them using `nitro.json`, or add them manually in the C++ `HybridObjectRegistry`.
|
|
9
|
+
*/
|
|
7
10
|
@Keep
|
|
8
11
|
@DoNotStrip
|
|
12
|
+
@Deprecated(forRemoval = true)
|
|
9
13
|
public interface HybridObjectInitializer {
|
|
10
14
|
@Keep
|
|
11
15
|
@DoNotStrip
|
|
@@ -20,6 +20,8 @@ public class HybridObjectRegistry {
|
|
|
20
20
|
* Registers the given HybridObject in the `HybridObjectRegistry`.
|
|
21
21
|
* It will be uniquely identified via it's `hybridObjectName`, and can be initialized from
|
|
22
22
|
* JS using `NitroModules.createHybridObject<T>(name)` - which will call the `constructorFn` here.
|
|
23
|
+
* @deprecated HybridObjects should be registered from C++ instead. Either autolink them using `nitro.json`, or add them manually in the C++ `HybridObjectRegistry`.
|
|
23
24
|
*/
|
|
25
|
+
@Deprecated(forRemoval = true)
|
|
24
26
|
public static native void registerHybridObjectConstructor(String hybridObjectName, HybridObjectInitializer initializer);
|
|
25
27
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package com.margelo.nitro.views
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import androidx.annotation.Keep
|
|
5
|
+
import com.facebook.jni.HybridData
|
|
6
|
+
import com.facebook.proguard.annotations.DoNotStrip
|
|
7
|
+
import com.margelo.nitro.core.HybridObject
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A base class for all Kotlin-based Hybrid Views.
|
|
11
|
+
*/
|
|
12
|
+
@Keep
|
|
13
|
+
@DoNotStrip
|
|
14
|
+
abstract class HybridView: HybridObject() {
|
|
15
|
+
/**
|
|
16
|
+
* Get the `UIView` this HybridView is holding.
|
|
17
|
+
*
|
|
18
|
+
* This value should not change during the lifetime of this `HybridView`.
|
|
19
|
+
*/
|
|
20
|
+
@get:DoNotStrip
|
|
21
|
+
@get:Keep
|
|
22
|
+
abstract val view: View
|
|
23
|
+
}
|
package/cpp/core/ArrayBuffer.cpp
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
//
|
|
7
7
|
|
|
8
8
|
#include "ArrayBuffer.hpp"
|
|
9
|
-
#include "
|
|
9
|
+
#include "BorrowingReference.hpp"
|
|
10
10
|
#include <functional>
|
|
11
11
|
#include <jsi/jsi.h>
|
|
12
12
|
#include <thread>
|
|
@@ -61,7 +61,7 @@ bool NativeArrayBuffer::isOwner() const noexcept {
|
|
|
61
61
|
|
|
62
62
|
// 3. JSArrayBuffer
|
|
63
63
|
|
|
64
|
-
JSArrayBuffer::JSArrayBuffer(jsi::Runtime* runtime,
|
|
64
|
+
JSArrayBuffer::JSArrayBuffer(jsi::Runtime* runtime, BorrowingReference<jsi::ArrayBuffer> jsReference)
|
|
65
65
|
: ArrayBuffer(), _runtime(runtime), _jsReference(jsReference), _initialThreadId(std::this_thread::get_id()) {}
|
|
66
66
|
|
|
67
67
|
JSArrayBuffer::~JSArrayBuffer() {}
|
package/cpp/core/ArrayBuffer.hpp
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
-
#include "
|
|
10
|
+
#include "BorrowingReference.hpp"
|
|
11
11
|
#include <jsi/jsi.h>
|
|
12
12
|
#include <thread>
|
|
13
13
|
#include <vector>
|
|
@@ -122,7 +122,7 @@ private:
|
|
|
122
122
|
*/
|
|
123
123
|
class JSArrayBuffer final : public ArrayBuffer {
|
|
124
124
|
public:
|
|
125
|
-
explicit JSArrayBuffer(jsi::Runtime* runtime,
|
|
125
|
+
explicit JSArrayBuffer(jsi::Runtime* runtime, BorrowingReference<jsi::ArrayBuffer> jsReference);
|
|
126
126
|
~JSArrayBuffer();
|
|
127
127
|
|
|
128
128
|
public:
|
|
@@ -141,7 +141,7 @@ public:
|
|
|
141
141
|
|
|
142
142
|
private:
|
|
143
143
|
jsi::Runtime* _runtime;
|
|
144
|
-
|
|
144
|
+
BorrowingReference<jsi::ArrayBuffer> _jsReference;
|
|
145
145
|
std::thread::id _initialThreadId;
|
|
146
146
|
};
|
|
147
147
|
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
namespace margelo::nitro {
|
|
10
10
|
|
|
11
11
|
HybridObject::HybridObject(const char* name) : HybridObjectPrototype(), _name(name) {}
|
|
12
|
-
HybridObject::~HybridObject() {}
|
|
13
12
|
|
|
14
13
|
std::string HybridObject::toString() {
|
|
15
14
|
return "[HybridObject " + std::string(_name) + "]";
|
|
@@ -19,7 +18,7 @@ std::string HybridObject::getName() {
|
|
|
19
18
|
return _name;
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
bool HybridObject::equals(std::shared_ptr<HybridObject
|
|
21
|
+
bool HybridObject::equals(const std::shared_ptr<HybridObject>& other) {
|
|
23
22
|
return this == other.get();
|
|
24
23
|
}
|
|
25
24
|
|
|
@@ -48,10 +47,12 @@ jsi::Value HybridObject::toObject(jsi::Runtime& runtime) {
|
|
|
48
47
|
if (cachedObject != _objectCache.end()) {
|
|
49
48
|
// 1.1. We have a WeakObject, try to see if it is still alive
|
|
50
49
|
OwningLock<jsi::WeakObject> lock = cachedObject->second.lock();
|
|
51
|
-
jsi::Value
|
|
52
|
-
if (!
|
|
53
|
-
// 1.2. It is still alive - we can use it instead of creating a new one!
|
|
54
|
-
|
|
50
|
+
jsi::Value value = cachedObject->second->lock(runtime);
|
|
51
|
+
if (!value.isUndefined()) {
|
|
52
|
+
// 1.2. It is still alive - we can use it instead of creating a new one! But first, let's update memory-size
|
|
53
|
+
value.getObject(runtime).setExternalMemoryPressure(runtime, getExternalMemorySize());
|
|
54
|
+
// 1.3. Return it now
|
|
55
|
+
return value;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -34,7 +34,7 @@ public:
|
|
|
34
34
|
* Called when no more references to the given `HybridObject` exist in both C++ and JS.
|
|
35
35
|
* JS might keep references for longer, as it is a garbage collected language.
|
|
36
36
|
*/
|
|
37
|
-
|
|
37
|
+
~HybridObject() override = default;
|
|
38
38
|
/**
|
|
39
39
|
* HybridObjects cannot be copied.
|
|
40
40
|
*/
|
|
@@ -80,7 +80,7 @@ public:
|
|
|
80
80
|
* While two `jsi::Object`s of the same `HybridObject` might not be equal when compared with `==`,
|
|
81
81
|
* they might still be the same `HybridObject` - in this case `equals(other)` will return true.
|
|
82
82
|
*/
|
|
83
|
-
bool equals(std::shared_ptr<HybridObject
|
|
83
|
+
bool equals(const std::shared_ptr<HybridObject>& other);
|
|
84
84
|
/**
|
|
85
85
|
* Get a string representation of this `HybridObject` - useful for logging or debugging.
|
|
86
86
|
*/
|
|
@@ -136,7 +136,7 @@ protected:
|
|
|
136
136
|
private:
|
|
137
137
|
static constexpr auto TAG = "HybridObject";
|
|
138
138
|
const char* _name = TAG;
|
|
139
|
-
std::unordered_map<jsi::Runtime*,
|
|
139
|
+
std::unordered_map<jsi::Runtime*, BorrowingReference<jsi::WeakObject>> _objectCache;
|
|
140
140
|
};
|
|
141
141
|
|
|
142
142
|
} // namespace margelo::nitro
|
package/cpp/core/Promise.hpp
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
#include "HybridNitroModulesProxy.hpp"
|
|
9
9
|
#include "HybridObjectRegistry.hpp"
|
|
10
|
+
#include "JSIConverter.hpp"
|
|
10
11
|
#include "NitroDefines.hpp"
|
|
11
12
|
|
|
12
13
|
namespace margelo::nitro {
|
|
@@ -20,6 +21,7 @@ void HybridNitroModulesProxy::loadHybridMethods() {
|
|
|
20
21
|
prototype.registerHybridMethod("getAllHybridObjectNames", &HybridNitroModulesProxy::getAllHybridObjectNames);
|
|
21
22
|
|
|
22
23
|
prototype.registerHybridMethod("box", &HybridNitroModulesProxy::box);
|
|
24
|
+
prototype.registerHybridMethod("updateMemorySize", &HybridNitroModulesProxy::updateMemorySize);
|
|
23
25
|
|
|
24
26
|
prototype.registerRawHybridMethod("hasNativeState", 1, &HybridNitroModulesProxy::hasNativeState);
|
|
25
27
|
|
|
@@ -53,6 +55,12 @@ jsi::Value HybridNitroModulesProxy::hasNativeState(jsi::Runtime& runtime, const
|
|
|
53
55
|
return args[0].getObject(runtime).hasNativeState(runtime);
|
|
54
56
|
}
|
|
55
57
|
|
|
58
|
+
std::shared_ptr<HybridObject> HybridNitroModulesProxy::updateMemorySize(const std::shared_ptr<HybridObject>& hybridObject) {
|
|
59
|
+
// If a hybridObject goes from Native -> JS, it will update it's memory size internally (in `HybridObject::toObject(..)`).
|
|
60
|
+
// This is all that function does.
|
|
61
|
+
return hybridObject;
|
|
62
|
+
}
|
|
63
|
+
|
|
56
64
|
// Build Info
|
|
57
65
|
std::string HybridNitroModulesProxy::getBuildType() {
|
|
58
66
|
#ifdef NITRO_DEBUG
|
|
@@ -37,6 +37,7 @@ public:
|
|
|
37
37
|
|
|
38
38
|
// Helpers
|
|
39
39
|
std::shared_ptr<BoxedHybridObject> box(const std::shared_ptr<HybridObject>& hybridObject);
|
|
40
|
+
std::shared_ptr<HybridObject> updateMemorySize(const std::shared_ptr<HybridObject>& hybridObject);
|
|
40
41
|
jsi::Value hasNativeState(jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* args, size_t size);
|
|
41
42
|
|
|
42
43
|
// Build Info
|
package/cpp/jsi/JSICache.cpp
CHANGED
|
@@ -14,12 +14,12 @@ namespace margelo::nitro {
|
|
|
14
14
|
static constexpr auto CACHE_PROP_NAME = "__nitroModulesJSICache";
|
|
15
15
|
|
|
16
16
|
template <typename T>
|
|
17
|
-
inline void destroyReferences(const std::vector<
|
|
17
|
+
inline void destroyReferences(const std::vector<WeakReference<T>>& references) {
|
|
18
18
|
for (auto& func : references) {
|
|
19
|
-
|
|
20
|
-
if (
|
|
19
|
+
BorrowingReference<T> reference = func.lock();
|
|
20
|
+
if (reference) {
|
|
21
21
|
// Destroy all functions that we might still have in cache, some callbacks and Promises may now become invalid.
|
|
22
|
-
|
|
22
|
+
reference.destroy();
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -28,6 +28,7 @@ JSICache::~JSICache() {
|
|
|
28
28
|
Logger::log(LogLevel::Info, TAG, "Destroying JSICache...");
|
|
29
29
|
std::unique_lock lock(_mutex);
|
|
30
30
|
|
|
31
|
+
destroyReferences(_valueCache);
|
|
31
32
|
destroyReferences(_objectCache);
|
|
32
33
|
destroyReferences(_functionCache);
|
|
33
34
|
destroyReferences(_weakObjectCache);
|
package/cpp/jsi/JSICache.hpp
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
#include "BorrowingReference.hpp"
|
|
11
11
|
#include "NitroLogger.hpp"
|
|
12
|
-
#include "
|
|
12
|
+
#include "WeakReference.hpp"
|
|
13
13
|
#include <jsi/jsi.h>
|
|
14
14
|
#include <memory>
|
|
15
15
|
#include <mutex>
|
|
@@ -24,12 +24,12 @@ class JSICacheReference;
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* A `JSICache` can safely store `jsi::Value` instances (e.g. `jsi::Object` or
|
|
27
|
-
* `jsi::Function`) inside `
|
|
27
|
+
* `jsi::Function`) inside `BorrowingReference<T>`.
|
|
28
28
|
*
|
|
29
29
|
* `jsi::Value`s are managed by a `jsi::Runtime`, and will be deleted if the `jsi::Runtime`
|
|
30
30
|
* is deleted - even if there are still strong references to the `jsi::Value`.
|
|
31
31
|
*
|
|
32
|
-
* To access a `
|
|
32
|
+
* To access a `BorrowingReference<jsi::Value>` safely, use `lock()` to get an `OwningLock<jsi::Value>`.
|
|
33
33
|
* This will allow you to access the `jsi::Value` as long as the `OwningLock` is alive,
|
|
34
34
|
* and `JSICache` will hold any garbage collection calls until the `OwningLock` is destroyed.
|
|
35
35
|
*/
|
|
@@ -59,10 +59,11 @@ private:
|
|
|
59
59
|
|
|
60
60
|
private:
|
|
61
61
|
std::mutex _mutex;
|
|
62
|
-
std::vector<
|
|
63
|
-
std::vector<
|
|
64
|
-
std::vector<
|
|
65
|
-
std::vector<
|
|
62
|
+
std::vector<WeakReference<jsi::Value>> _valueCache;
|
|
63
|
+
std::vector<WeakReference<jsi::Object>> _objectCache;
|
|
64
|
+
std::vector<WeakReference<jsi::Function>> _functionCache;
|
|
65
|
+
std::vector<WeakReference<jsi::WeakObject>> _weakObjectCache;
|
|
66
|
+
std::vector<WeakReference<jsi::ArrayBuffer>> _arrayBufferCache;
|
|
66
67
|
|
|
67
68
|
private:
|
|
68
69
|
static inline std::unordered_map<jsi::Runtime*, std::weak_ptr<JSICache>> _globalCache;
|
|
@@ -82,23 +83,28 @@ public:
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
public:
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
BorrowingReference<jsi::Value> makeShared(jsi::Value&& value) {
|
|
87
|
+
BorrowingReference<jsi::Value> owning(new jsi::Value(std::move(value)));
|
|
88
|
+
_strongCache->_valueCache.push_back(owning.weak());
|
|
89
|
+
return owning;
|
|
90
|
+
}
|
|
91
|
+
BorrowingReference<jsi::Object> makeShared(jsi::Object&& value) {
|
|
92
|
+
BorrowingReference<jsi::Object> owning(new jsi::Object(std::move(value)));
|
|
87
93
|
_strongCache->_objectCache.push_back(owning.weak());
|
|
88
94
|
return owning;
|
|
89
95
|
}
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
BorrowingReference<jsi::Function> makeShared(jsi::Function&& value) {
|
|
97
|
+
BorrowingReference<jsi::Function> owning(new jsi::Function(std::move(value)));
|
|
92
98
|
_strongCache->_functionCache.push_back(owning.weak());
|
|
93
99
|
return owning;
|
|
94
100
|
}
|
|
95
|
-
|
|
96
|
-
|
|
101
|
+
BorrowingReference<jsi::WeakObject> makeShared(jsi::WeakObject&& value) {
|
|
102
|
+
BorrowingReference<jsi::WeakObject> owning(new jsi::WeakObject(std::move(value)));
|
|
97
103
|
_strongCache->_weakObjectCache.push_back(owning.weak());
|
|
98
104
|
return owning;
|
|
99
105
|
}
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
BorrowingReference<jsi::ArrayBuffer> makeShared(jsi::ArrayBuffer&& value) {
|
|
107
|
+
BorrowingReference<jsi::ArrayBuffer> owning(new jsi::ArrayBuffer(std::move(value)));
|
|
102
108
|
_strongCache->_arrayBufferCache.push_back(owning.weak());
|
|
103
109
|
return owning;
|
|
104
110
|
}
|
|
@@ -34,7 +34,7 @@ struct JSIConverter<std::function<ReturnType(Args...)>> final {
|
|
|
34
34
|
// Make function global - it'll be managed by the Runtime's memory, and we only have a weak_ref to it.
|
|
35
35
|
auto cache = JSICache::getOrCreateCache(runtime);
|
|
36
36
|
jsi::Function function = arg.asObject(runtime).asFunction(runtime);
|
|
37
|
-
|
|
37
|
+
BorrowingReference<jsi::Function> sharedFunction = cache.makeShared(std::move(function));
|
|
38
38
|
|
|
39
39
|
std::shared_ptr<Dispatcher> strongDispatcher = Dispatcher::getRuntimeGlobalDispatcher(runtime);
|
|
40
40
|
std::weak_ptr<Dispatcher> weakDispatcher = strongDispatcher;
|
|
@@ -94,7 +94,8 @@ struct JSIConverter<std::function<ReturnType(Args...)>> final {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
private:
|
|
97
|
-
static inline ResultingType callJSFunction(jsi::Runtime& runtime, const
|
|
97
|
+
static inline ResultingType callJSFunction(jsi::Runtime& runtime, const BorrowingReference<jsi::Function>& function,
|
|
98
|
+
const Args&... args) {
|
|
98
99
|
if (!function) {
|
|
99
100
|
if constexpr (std::is_void_v<ResultingType>) {
|
|
100
101
|
// runtime has already been deleted. since this returns void, we can just ignore it being deleted.
|
package/cpp/jsi/JSIHelpers.hpp
CHANGED
|
@@ -46,7 +46,7 @@ static inline bool isPlainObject(jsi::Runtime& runtime, const jsi::Object& objec
|
|
|
46
46
|
*/
|
|
47
47
|
static inline std::string getRuntimeId(jsi::Runtime& runtime) {
|
|
48
48
|
std::string threadName = ThreadUtils::getThreadName();
|
|
49
|
-
return runtime.description() +
|
|
49
|
+
return runtime.description() + " (" + threadName + ")";
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
} // namespace margelo::nitro
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
#include "HybridObjectPrototype.hpp"
|
|
9
9
|
#include "NitroDefines.hpp"
|
|
10
10
|
#include "NitroLogger.hpp"
|
|
11
|
-
#include "
|
|
11
|
+
#include "NitroTypeInfo.hpp"
|
|
12
12
|
|
|
13
13
|
namespace margelo::nitro {
|
|
14
14
|
|
|
@@ -26,7 +26,7 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
|
|
|
26
26
|
auto& prototypeCache = _prototypeCache[&runtime];
|
|
27
27
|
auto cachedPrototype = prototypeCache.find(prototype->getNativeInstanceId());
|
|
28
28
|
if (cachedPrototype != prototypeCache.end()) {
|
|
29
|
-
const
|
|
29
|
+
const BorrowingReference<jsi::Object>& cachedObject = cachedPrototype->second;
|
|
30
30
|
return jsi::Value(runtime, *cachedObject).getObject(runtime);
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -68,7 +68,7 @@ jsi::Value HybridObjectPrototype::createPrototype(jsi::Runtime& runtime, const s
|
|
|
68
68
|
|
|
69
69
|
// 6. Throw it into our cache so the next lookup can be cached and therefore faster
|
|
70
70
|
JSICacheReference jsiCache = JSICache::getOrCreateCache(runtime);
|
|
71
|
-
|
|
71
|
+
BorrowingReference<jsi::Object> cachedObject = jsiCache.makeShared(std::move(object));
|
|
72
72
|
prototypeCache.emplace(prototype->getNativeInstanceId(), cachedObject);
|
|
73
73
|
|
|
74
74
|
// 7. In DEBUG, add a __type info to the prototype object.
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
#pragma once
|
|
9
9
|
|
|
10
|
+
#include "BorrowingReference.hpp"
|
|
10
11
|
#include "HybridFunction.hpp"
|
|
11
|
-
#include "OwningReference.hpp"
|
|
12
12
|
#include "Prototype.hpp"
|
|
13
13
|
#include "PrototypeChain.hpp"
|
|
14
14
|
#include <functional>
|
|
@@ -46,7 +46,7 @@ public:
|
|
|
46
46
|
|
|
47
47
|
private:
|
|
48
48
|
static jsi::Value createPrototype(jsi::Runtime& runtime, const std::shared_ptr<Prototype>& prototype);
|
|
49
|
-
using PrototypeCache = std::unordered_map<NativeInstanceId,
|
|
49
|
+
using PrototypeCache = std::unordered_map<NativeInstanceId, BorrowingReference<jsi::Object>>;
|
|
50
50
|
static std::unordered_map<jsi::Runtime*, PrototypeCache> _prototypeCache;
|
|
51
51
|
|
|
52
52
|
protected:
|