Skip to content

Commit

Permalink
Add support for React Native 0.71 (#3745)
Browse files Browse the repository at this point in the history
## Description

Closes #3871.

### TODO

- [x] Update Example app template to 0.71.0-rc.5
- [x] Update FabricExample app template to 0.71.0-rc.5
- [x] Consume shared libraries and headers from prefabs (partially done)
- [x] Use `implementation "com.facebook.react:react-native` (without plus) for RN 0.71+
- [x] Use `implementation "com.facebook.react:react-native:+" // From node_modules` for older RN versions (leave as it it now)
- [x] Make it work with Hermes
- [x] Make it works with JSC
- [x] Properly detect Hermes on Android
- [x] Include `folly-flags.cmake` directly
- [x] Use headers from path instead of prefabs
- [x] Depend on `jscexecutor` and `hermes-executor`
- [x] Fix Layout Animations on Paper due after removal of deprecated `UIImplementation` (facebook/react-native@e7d7563)
- [x] Use TypeScript types directly from package
- [x] Add #ifdefs for backward-incompatible code changes (e.g. `debugToken_`)
- [x] Use different sourcesets for `UIImplementationProvider`
- [x] Add missing `SystraceSection` in `UIManager_cloneNode`
- [x] Confirm that `UIManager_cloneNode` and `UIManagerBinding` are identical to those in react-native
- [x] Remove react-native.config.js
- [x] Update metro-inspector-proxy patch

### Won't do
- [ ] Declare dependency on `React-jsi` & `React-jsc` based on `ENV['USE_HERMES']` in RNReanimated.podspec - not necessary
- [ ] Fix Jest `testEnvironment`, use `react-native-env.js` - still doesn't work
- [ ] Do we still need `kotlinVersion` in build.gradle? - probably yes
- [ ] Restore MBFingerTip in ReanimatedExample

### Checklist

- [ ] Check compatibility with older RN versions
- [ ] Check if debugging worklets with Flipper works
- [ ] Check if debugging in Android Studio works
  • Loading branch information
tomekzaw authored Jan 3, 2023
1 parent 6396098 commit d3aea04
Show file tree
Hide file tree
Showing 104 changed files with 6,296 additions and 8,316 deletions.
105 changes: 3 additions & 102 deletions Common/cpp/Fabric/FabricUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "FabricUtils.h"

#include <react/renderer/debug/SystraceSection.h>
#include <react/renderer/uimanager/UIManagerBinding.h>

using namespace facebook::react;
Expand All @@ -22,110 +23,10 @@ RuntimeExecutor getRuntimeExecutorFromBinding(Binding *binding) {
}
#endif

inline static const UIManagerPublic *getUIManagerPublic(
const UIManager *uiManager) {
return reinterpret_cast<const UIManagerPublic *>(uiManager);
}

std::shared_ptr<const ContextContainer> getContextContainerFromUIManager(
const UIManager *uiManager) {
return getUIManagerPublic(uiManager)->contextContainer_;
}

inline static UIManagerDelegate *getDelegateFromUIManager(
const UIManager *uiManager) {
return getUIManagerPublic(uiManager)->delegate_;
}

void UIManager_dispatchCommand(
const std::shared_ptr<UIManager> &uiManager,
const ShadowNode::Shared &shadowNode,
std::string const &commandName,
folly::dynamic const &args) {
auto delegate_ = getDelegateFromUIManager(&*uiManager);

// copied from UIManager.cpp
if (delegate_) {
delegate_->uiManagerDidDispatchCommand(shadowNode, commandName, args);
}
}

LayoutMetrics UIManager_getRelativeLayoutMetrics(
const std::shared_ptr<UIManager> &uiManager,
ShadowNode const &shadowNode,
ShadowNode const *ancestorShadowNode,
LayoutableShadowNode::LayoutInspectingPolicy policy) {
// based on implementation from UIManager.cpp
const auto &shadowTreeRegistry = uiManager->getShadowTreeRegistry();

// We might store here an owning pointer to `ancestorShadowNode` to ensure
// that the node is not deallocated during method execution lifetime.
auto owningAncestorShadowNode = ShadowNode::Shared{};

if (!ancestorShadowNode) {
shadowTreeRegistry.visit(
shadowNode.getSurfaceId(), [&](ShadowTree const &shadowTree) {
owningAncestorShadowNode =
shadowTree.getCurrentRevision().rootShadowNode;
ancestorShadowNode = owningAncestorShadowNode.get();
});
} else {
// It is possible for JavaScript (or other callers) to have a reference
// to a previous version of ShadowNodes, but we enforce that
// metrics are only calculated on most recently committed versions.
owningAncestorShadowNode =
uiManager->getNewestCloneOfShadowNode(*ancestorShadowNode);
ancestorShadowNode = owningAncestorShadowNode.get();
}

auto layoutableAncestorShadowNode =
traitCast<LayoutableShadowNode const *>(ancestorShadowNode);

if (!layoutableAncestorShadowNode) {
return EmptyLayoutMetrics;
}

return LayoutableShadowNode::computeRelativeLayoutMetrics(
shadowNode.getFamily(), *layoutableAncestorShadowNode, policy);
}

ShadowNode::Shared UIManager_cloneNode(
const UIManager *uiManager,
const ShadowNode::Shared &shadowNode,
const ShadowNode::SharedListOfShared &children,
const RawProps *rawProps) {
auto delegate_ = getDelegateFromUIManager(uiManager);
auto contextContainer_ = getContextContainerFromUIManager(uiManager);

// copied from UIManager.cpp
PropsParserContext propsParserContext{
shadowNode->getFamily().getSurfaceId(), *contextContainer_.get()};

auto &componentDescriptor = shadowNode->getComponentDescriptor();
auto clonedShadowNode = componentDescriptor.cloneShadowNode(
*shadowNode,
{
/* .props = */
rawProps ? componentDescriptor.cloneProps(
propsParserContext, shadowNode->getProps(), *rawProps)
: ShadowNodeFragment::propsPlaceholder(),
/* .children = */ children,
});

if (delegate_) {
delegate_->uiManagerDidCloneShadowNode(
*shadowNode.get(), *clonedShadowNode);
}

return clonedShadowNode;
}

void UIManager_appendChild(
const ShadowNode::Shared &parentShadowNode,
const ShadowNode::Shared &childShadowNode) {
// copied from UIManager.cpp
auto &componentDescriptor = parentShadowNode->getComponentDescriptor();
componentDescriptor.appendChild(parentShadowNode, childShadowNode);
return reinterpret_cast<const UIManagerPublic *>(uiManager)
->contextContainer_;
}

} // namespace reanimated
Expand Down
27 changes: 3 additions & 24 deletions Common/cpp/Fabric/FabricUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
#ifdef RCT_NEW_ARCH_ENABLED

#ifdef ANDROID
#include <Binding.h>
#include <fbjni/fbjni.h>
#include <react/fabric/Binding.h>
#endif
#include <react/renderer/uimanager/UIManager.h>

#include <memory>
#include <string>

using namespace facebook::react;
using namespace facebook;
using namespace react;

namespace reanimated {

Expand Down Expand Up @@ -52,28 +53,6 @@ RuntimeExecutor getRuntimeExecutorFromBinding(Binding *binding);
std::shared_ptr<const ContextContainer> getContextContainerFromUIManager(
const UIManager *uiManager);

void UIManager_dispatchCommand(
const std::shared_ptr<UIManager> &uiManager,
const ShadowNode::Shared &shadowNode,
std::string const &commandName,
folly::dynamic const &args);

LayoutMetrics UIManager_getRelativeLayoutMetrics(
const std::shared_ptr<UIManager> &uiManager,
ShadowNode const &shadowNode,
ShadowNode const *ancestorShadowNode,
LayoutableShadowNode::LayoutInspectingPolicy policy);

ShadowNode::Shared UIManager_cloneNode(
const UIManager *uiManager,
const ShadowNode::Shared &shadowNode,
const ShadowNode::SharedListOfShared &children = nullptr,
const RawProps *rawProps = nullptr);

void UIManager_appendChild(
const ShadowNode::Shared &parentShadowNode,
const ShadowNode::Shared &childShadowNode);

} // namespace reanimated

#endif // RCT_NEW_ARCH_ENABLED
91 changes: 54 additions & 37 deletions Common/cpp/Fabric/ReanimatedUIManagerBinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "FabricUtils.h"
#include "NewestShadowNodesRegistry.h"

#include <react/renderer/debug/SystraceSection.h>

#include <utility>

using namespace facebook;
Expand Down Expand Up @@ -51,7 +53,7 @@ ReanimatedUIManagerBinding::ReanimatedUIManagerBinding(
RuntimeExecutor runtimeExecutor,
std::unique_ptr<EventHandler const> eventHandler,
std::shared_ptr<NewestShadowNodesRegistry> newestShadowNodesRegistry)
: UIManagerBinding(uiManager, runtimeExecutor),
: UIManagerBinding(uiManager),
uiManager_(std::move(uiManager)),
newestShadowNodesRegistry_(newestShadowNodesRegistry) {
if (eventHandler != nullptr) {
Expand All @@ -62,25 +64,44 @@ ReanimatedUIManagerBinding::ReanimatedUIManagerBinding(

ReanimatedUIManagerBinding::~ReanimatedUIManagerBinding() {}

static inline ShadowNode::Shared cloneNode(
static inline ShadowNode::Shared cloneNodeUsingNewest(
UIManager *uiManager,
NewestShadowNodesRegistry *newestShadowNodesRegistry,
const ShadowNode::Shared &shadowNode,
const ShadowNode::SharedListOfShared &children = nullptr,
const RawProps *rawProps = nullptr) {
ShadowNode const &shadowNode,
ShadowNode::SharedListOfShared const &children = nullptr,
RawProps const *rawProps = nullptr) {
{
auto lock = newestShadowNodesRegistry->createLock();
auto newest = newestShadowNodesRegistry->get(shadowNode->getTag());
auto newest = newestShadowNodesRegistry->get(shadowNode.getTag());
if (newest != nullptr) {
// ShadowNode managed by Reanimated, use newest ShadowNode from registry
auto clone = UIManager_cloneNode(uiManager, newest, children, rawProps);
auto clone = uiManager->cloneNode(*newest, children, rawProps);
newestShadowNodesRegistry->update(clone);
return clone;
}
} // release lock since we don't need registry anymore

// ShadowNode not managed by Reanimated (yet?)
return UIManager_cloneNode(uiManager, shadowNode, children, rawProps);
return uiManager->cloneNode(shadowNode, children, rawProps);
}

static inline void appendChildUsingNewest(
UIManager *uiManager,
NewestShadowNodesRegistry *newestShadowNodesRegistry,
const ShadowNode::Shared &parentShadowNode,
const ShadowNode::Shared &childShadowNode) {
{
auto lock = newestShadowNodesRegistry->createLock();
auto newestChildShadowNode =
newestShadowNodesRegistry->get(childShadowNode->getTag());
if (newestChildShadowNode != nullptr) {
uiManager->appendChild(parentShadowNode, newestChildShadowNode);
return;
}
} // release lock since we don't need registry anymore

// child ShadowNode not managed by Reanimated (yet?)
uiManager->appendChild(parentShadowNode, childShadowNode);
}

jsi::Value ReanimatedUIManagerBinding::get(
Expand All @@ -94,6 +115,7 @@ jsi::Value ReanimatedUIManagerBinding::get(

// based on implementation from UIManagerBinding.cpp
auto methodName = name.utf8(runtime);
SystraceSection s("ReanimatedUIManagerBinding::get", "name", methodName);
UIManager *uiManager = uiManager_.get();
NewestShadowNodesRegistry *newestShadowNodesRegistry =
newestShadowNodesRegistry_.get();
Expand All @@ -106,15 +128,15 @@ jsi::Value ReanimatedUIManagerBinding::get(
1,
[uiManager, newestShadowNodesRegistry](
jsi::Runtime &runtime,
jsi::Value const &thisValue,
jsi::Value const & /*thisValue*/,
jsi::Value const *arguments,
size_t count) noexcept -> jsi::Value {
size_t /*count*/) noexcept -> jsi::Value {
return valueFromShadowNode(
runtime,
cloneNode(
cloneNodeUsingNewest(
uiManager,
newestShadowNodesRegistry,
shadowNodeFromValue(runtime, arguments[0])));
*shadowNodeFromValue(runtime, arguments[0])));
});
}

Expand All @@ -126,15 +148,15 @@ jsi::Value ReanimatedUIManagerBinding::get(
1,
[uiManager, newestShadowNodesRegistry](
jsi::Runtime &runtime,
jsi::Value const &thisValue,
jsi::Value const & /*thisValue*/,
jsi::Value const *arguments,
size_t count) noexcept -> jsi::Value {
size_t /*count*/) noexcept -> jsi::Value {
return valueFromShadowNode(
runtime,
cloneNode(
cloneNodeUsingNewest(
uiManager,
newestShadowNodesRegistry,
shadowNodeFromValue(runtime, arguments[0]),
*shadowNodeFromValue(runtime, arguments[0]),
ShadowNode::emptySharedShadowNodeSharedList()));
});
}
Expand All @@ -147,16 +169,16 @@ jsi::Value ReanimatedUIManagerBinding::get(
2,
[uiManager, newestShadowNodesRegistry](
jsi::Runtime &runtime,
jsi::Value const &thisValue,
jsi::Value const & /*thisValue*/,
jsi::Value const *arguments,
size_t count) noexcept -> jsi::Value {
size_t /*count*/) noexcept -> jsi::Value {
auto const &rawProps = RawProps(runtime, arguments[1]);
return valueFromShadowNode(
runtime,
cloneNode(
cloneNodeUsingNewest(
uiManager,
newestShadowNodesRegistry,
shadowNodeFromValue(runtime, arguments[0]),
*shadowNodeFromValue(runtime, arguments[0]),
nullptr,
&rawProps));
});
Expand All @@ -170,16 +192,16 @@ jsi::Value ReanimatedUIManagerBinding::get(
2,
[uiManager, newestShadowNodesRegistry](
jsi::Runtime &runtime,
jsi::Value const &thisValue,
jsi::Value const & /*thisValue*/,
jsi::Value const *arguments,
size_t count) noexcept -> jsi::Value {
size_t /*count*/) noexcept -> jsi::Value {
auto const &rawProps = RawProps(runtime, arguments[1]);
return valueFromShadowNode(
runtime,
cloneNode(
cloneNodeUsingNewest(
uiManager,
newestShadowNodesRegistry,
shadowNodeFromValue(runtime, arguments[0]),
*shadowNodeFromValue(runtime, arguments[0]),
ShadowNode::emptySharedShadowNodeSharedList(),
&rawProps));
});
Expand All @@ -190,21 +212,16 @@ jsi::Value ReanimatedUIManagerBinding::get(
runtime,
name,
2,
[newestShadowNodesRegistry](
[uiManager, newestShadowNodesRegistry](
jsi::Runtime &runtime,
jsi::Value const &thisValue,
jsi::Value const & /*thisValue*/,
jsi::Value const *arguments,
size_t count) noexcept -> jsi::Value {
auto parent = shadowNodeFromValue(runtime, arguments[0]);
auto child = shadowNodeFromValue(runtime, arguments[1]);
{
auto lock = newestShadowNodesRegistry->createLock();
auto newest = newestShadowNodesRegistry->get(child->getTag());
if (newest != nullptr) {
child = newest;
}
}
UIManager_appendChild(parent, child);
size_t /*count*/) noexcept -> jsi::Value {
appendChildUsingNewest(
uiManager,
newestShadowNodesRegistry,
shadowNodeFromValue(runtime, arguments[0]),
shadowNodeFromValue(runtime, arguments[1]));
return jsi::Value::undefined();
});
}
Expand Down
14 changes: 5 additions & 9 deletions Common/cpp/NativeModules/NativeReanimatedModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,9 +597,7 @@ void NativeReanimatedModule::dispatchCommand(
ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
std::string commandName = stringFromValue(rt, commandNameValue);
folly::dynamic args = commandArgsFromValue(rt, argsValue);

// TODO: use uiManager_->dispatchCommand once it's public
UIManager_dispatchCommand(uiManager_, shadowNode, commandName, args);
uiManager_->dispatchCommand(shadowNode, commandName, args);
}

jsi::Value NativeReanimatedModule::measure(
Expand All @@ -608,11 +606,8 @@ jsi::Value NativeReanimatedModule::measure(
// based on implementation from UIManagerBinding.cpp

auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
// TODO: use uiManager_->getRelativeLayoutMetrics once it's public
// auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(
// *shadowNode, nullptr, {/* .includeTransform = */ true});
auto layoutMetrics = UIManager_getRelativeLayoutMetrics(
uiManager_, *shadowNode, nullptr, {/* .includeTransform = */ true});
auto layoutMetrics = uiManager_->getRelativeLayoutMetrics(
*shadowNode, nullptr, {/* .includeTransform = */ true});

if (layoutMetrics == EmptyLayoutMetrics) {
// Originally, in this case React Native returns `{0, 0, 0, 0, 0, 0}`, most
Expand All @@ -626,7 +621,8 @@ jsi::Value NativeReanimatedModule::measure(

auto layoutableShadowNode =
traitCast<LayoutableShadowNode const *>(newestCloneOfShadowNode.get());
facebook::react::Point originRelativeToParent = layoutableShadowNode
facebook::react::Point originRelativeToParent =
layoutableShadowNode != nullptr
? layoutableShadowNode->getLayoutMetrics().frame.origin
: facebook::react::Point();

Expand Down
Loading

0 comments on commit d3aea04

Please sign in to comment.