Skip to content

Commit 5b1f4c1

Browse files
committed
refactor: explicit invalidations for native and cpp
1 parent 6713c4c commit 5b1f4c1

File tree

12 files changed

+62
-11
lines changed

12 files changed

+62
-11
lines changed

packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,4 +844,10 @@ void ReanimatedModuleProxy::unsubscribeFromKeyboardEvents(
844844
unsubscribeFromKeyboardEventsFunction_(listenerId.asNumber());
845845
}
846846

847+
void ReanimatedModuleProxy::invalidate() {
848+
// Make sure to release WorkletsModuleProxy on invalidate to allow it
849+
// to destroy its runtime during the invalidation stage.
850+
workletsModuleProxy_.reset();
851+
}
852+
847853
} // namespace reanimated

packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec {
4242

4343
~ReanimatedModuleProxy();
4444

45+
void invalidate();
46+
4547
jsi::Value registerEventHandler(
4648
jsi::Runtime &rt,
4749
const jsi::Value &worklet,
@@ -175,7 +177,7 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec {
175177

176178
const bool isBridgeless_;
177179
const bool isReducedMotion_;
178-
const std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
180+
std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
179181
const std::string valueUnpackerCode_;
180182

181183
std::unique_ptr<EventHandlerRegistry> eventHandlerRegistry_;

packages/react-native-reanimated/Common/cpp/worklets/Tools/SingleInstanceChecker.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,8 @@ SingleInstanceChecker<T>::SingleInstanceChecker() {
5252
std::string className =
5353
__cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
5454

55-
// Only one instance should exist, but it is possible for two instances
56-
// to co-exist during a reload.
5755
assertWithMessage(
58-
instanceCount_ <= 1,
56+
instanceCount_ < 1,
5957
"[Reanimated] More than one instance of " + className +
6058
" present. This may indicate a memory leak due to a retain cycle.");
6159

packages/react-native-reanimated/android/src/fabric/java/com/swmansion/reanimated/NativeProxy.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ protected HybridData getHybridData() {
7070
return mHybridData;
7171
}
7272

73+
private native void invalidateCpp();
74+
75+
public void invalidate() {
76+
invalidateCpp();
77+
}
78+
7379
public static NativeMethodsHolder createNativeMethodsHolder(
7480
LayoutAnimations ignoredLayoutAnimations) {
7581
return new NativeMethodsHolder() {

packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,8 @@ void NativeProxy::registerNatives() {
194194
makeNativeMethod(
195195
"isAnyHandlerWaitingForEvent",
196196
NativeProxy::isAnyHandlerWaitingForEvent),
197-
makeNativeMethod("performOperations", NativeProxy::performOperations)});
197+
makeNativeMethod("performOperations", NativeProxy::performOperations),
198+
makeNativeMethod("invalidateCpp", NativeProxy::invalidateCpp)});
198199
}
199200

200201
void NativeProxy::requestRender(
@@ -619,4 +620,10 @@ void NativeProxy::setupLayoutAnimations() {
619620
});
620621
}
621622

623+
void NativeProxy::invalidateCpp() {
624+
workletsModuleProxy_.reset();
625+
reanimatedModuleProxy_->invalidate();
626+
reanimatedModuleProxy_.reset();
627+
}
628+
622629
} // namespace reanimated

packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ class NativeProxy : public jni::HybridClass<NativeProxy> {
279279
void commonInit(jni::alias_ref<facebook::react::JFabricUIManager::javaobject>
280280
&fabricUIManager);
281281
#endif // RCT_NEW_ARCH_ENABLED
282+
283+
void invalidateCpp();
282284
};
283285

284286
} // namespace reanimated

packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,14 @@ jni::local_ref<WorkletsModule::jhybriddata> WorkletsModule::initHybrid(
6161
uiScheduler);
6262
}
6363

64+
void WorkletsModule::invalidateCpp() {
65+
workletsModuleProxy_.reset();
66+
}
67+
6468
void WorkletsModule::registerNatives() {
65-
registerHybrid({makeNativeMethod("initHybrid", WorkletsModule::initHybrid)});
69+
registerHybrid(
70+
{makeNativeMethod("initHybrid", WorkletsModule::initHybrid),
71+
makeNativeMethod("invalidateCpp", WorkletsModule::invalidateCpp)});
6672
}
6773

6874
} // namespace worklets

packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ class WorkletsModule : public jni::HybridClass<WorkletsModule> {
4646
}
4747

4848
private:
49-
friend HybridBase;
50-
jni::global_ref<WorkletsModule::javaobject> javaPart_;
51-
jsi::Runtime *rnRuntime_;
52-
std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
53-
5449
explicit WorkletsModule(
5550
jni::alias_ref<WorkletsModule::jhybridobject> jThis,
5651
jsi::Runtime *rnRuntime,
@@ -59,6 +54,13 @@ class WorkletsModule : public jni::HybridClass<WorkletsModule> {
5954
const std::shared_ptr<facebook::react::CallInvoker> &jsCallInvoker,
6055
const std::shared_ptr<worklets::JSScheduler> &jsScheduler,
6156
const std::shared_ptr<UIScheduler> &uiScheduler);
57+
58+
void invalidateCpp();
59+
60+
friend HybridBase;
61+
jni::global_ref<WorkletsModule::javaobject> javaPart_;
62+
jsi::Runtime *rnRuntime_;
63+
std::shared_ptr<WorkletsModuleProxy> workletsModuleProxy_;
6264
};
6365

6466
} // namespace worklets

packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NodesManager.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ public void invalidate() {
128128
}
129129

130130
if (mNativeProxy != null) {
131+
mNativeProxy.invalidate();
131132
mNativeProxy = null;
132133
}
133134
}

packages/react-native-reanimated/android/src/main/java/com/swmansion/worklets/WorkletsModule.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ public boolean installTurboModule(String valueUnpackerCode) {
6969
}
7070

7171
public void invalidate() {
72+
// We have to destroy extra runtimes when invalidate is called. If we clean
73+
// it up later instead there's a chance the runtime will retain references
74+
// to invalidated memory and will crash on destruction.
75+
invalidateCpp();
7276
mAndroidUIScheduler.deactivate();
7377
}
78+
79+
private native void invalidateCpp();
7480
}

0 commit comments

Comments
 (0)