From 625d330ed9846e6ec33346f611ccb079a7436a04 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Thu, 4 Jul 2024 10:10:13 -0700 Subject: [PATCH] Fix dynamic_cast (RTTI) by adding key function to ShadowNodeWrapper again (#45290) Summary: This PR restores the virtual destructor for `ShadowNodeWrapper` which was added in https://github.com/facebook/react-native/pull/33500 and unfortunately removed in https://github.com/facebook/react-native/pull/40864. The virtual destructor here serves as a key function. Without a key function, `obj.hasNativeState(rt)` **does not** work correctly between shared library boundaries on Android and always returns false. We need this pretty badly in third-party libraries like react-native-reanimated or react-native-gesture-handler. ## Changelog: [ANDROID] [FIXED] - Fix dynamic_cast (RTTI) for ShadowNodeWrapper when accessed by third-party libraries again Pull Request resolved: https://github.com/facebook/react-native/pull/45290 Test Plan: This patch fixes an issue in Reanimated's fabric-example app. Reviewed By: fabriziocucci Differential Revision: D59375554 Pulled By: javache fbshipit-source-id: 09f3eda89a67c26d6dacca3428e08d1b7138d350 --- .../ReactCommon/react/renderer/core/ShadowNode.cpp | 6 ++++++ .../ReactCommon/react/renderer/core/ShadowNode.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp index 5b60ac9842825f..68da528464b628 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -410,4 +410,10 @@ SharedDebugStringConvertibleList ShadowNode::getDebugProps() const { } #endif +// Explicitly define destructors here, as they need to exist in order to act as +// a "key function" for the ShadowNodeWrapper class -- this allows for RTTI to +// work properly across dynamic library boundaries (i.e. dynamic_cast that is +// used by getNativeState method) +ShadowNodeWrapper::~ShadowNodeWrapper() = default; + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h index e40321c257410b..ea5dae23eebdcd 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.h @@ -282,6 +282,11 @@ struct ShadowNodeWrapper : public jsi::NativeState { explicit ShadowNodeWrapper(ShadowNode::Shared shadowNode) : shadowNode(std::move(shadowNode)) {} + // The below method needs to be implemented out-of-line in order for the class + // to have at least one "key function" (see + // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#vague-vtable) + ~ShadowNodeWrapper() override; + ShadowNode::Shared shadowNode; };