Skip to content

Commit

Permalink
[Fabric] Reanimated for Fabric (software-mansion#3206)
Browse files Browse the repository at this point in the history
## Description

This PR adds Fabric support to React Native Reanimated.

Co-authored by @piaskowyk, @graszka22, @j-piasecki, @Szymon20000 and @kmagiera.

# Conflicts:
#	Example/yarn.lock
#	FabricExample/android/app/build.gradle
#	FabricExample/android/build.gradle
#	FabricExample/android/gradle.properties
#	FabricExample/babel.config.js
#	FabricExample/ios/Podfile
#	FabricExample/ios/Podfile.lock
#	FabricExample/metro.config.js
#	FabricExample/package.json
#	FabricExample/yarn.lock
#	android/src/main/cpp/NativeProxy.cpp
#	android/src/main/java/com/swmansion/reanimated/NodesManager.java
#	ios/REAModule.m
#	ios/REANodesManager.h
#	ios/REANodesManager.mm
#	ios/native/REAInitializer.mm
  • Loading branch information
tomekzaw authored and sunnylqm committed Jun 13, 2022
1 parent 64d5909 commit 2756cd3
Show file tree
Hide file tree
Showing 119 changed files with 15,499 additions and 3,500 deletions.
11 changes: 5 additions & 6 deletions .github/workflows/android-build.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Test Android build
on:
pull_request:
branches:
- main
paths:
- 'android/**'
- 'Common/**'
Expand All @@ -12,8 +10,9 @@ on:
jobs:
build:
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: Example
strategy:
matrix:
working-directory: [Example, FabricExample]
concurrency:
group: android-${{ github.ref }}
cancel-in-progress: true
Expand Down Expand Up @@ -41,8 +40,8 @@ jobs:
- name: Install root node dependencies
run: yarn
- name: Install example app node dependencies
working-directory: ${{ env.WORKING_DIRECTORY }}
working-directory: ${{ matrix.working-directory }}
run: yarn
- name: Build app
working-directory: ${{ env.WORKING_DIRECTORY }}/android
working-directory: ${{ matrix.working-directory }}/android
run: ./gradlew assembleDebug --console=plain
2 changes: 0 additions & 2 deletions .github/workflows/docs-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ name: Test docs build

on:
pull_request:
branches:
- main
paths:
- 'docs/**'

Expand Down
13 changes: 6 additions & 7 deletions .github/workflows/ios-build.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Test iOS build
on:
pull_request:
branches:
- main
paths:
- 'ios/**'
- 'Common/**'
Expand All @@ -13,8 +11,9 @@ jobs:
build:
# runs-on: macos-latest // issue: https://github.com/actions/virtual-environments/issues/4060
runs-on: macos-11
env:
WORKING_DIRECTORY: Example
strategy:
matrix:
working-directory: [Example, FabricExample]
concurrency:
group: ios-${{ github.ref }}
cancel-in-progress: true
Expand All @@ -29,11 +28,11 @@ jobs:
- name: Install Reanimated node dependencies
run: yarn
- name: Install node dependencies
working-directory: ${{ env.WORKING_DIRECTORY }}
working-directory: ${{ matrix.working-directory }}
run: yarn
- name: Install pods
working-directory: ${{ env.WORKING_DIRECTORY }}/ios
working-directory: ${{ matrix.working-directory }}/ios
run: pod install
- name: Build app
working-directory: ${{ env.WORKING_DIRECTORY }}
working-directory: ${{ matrix.working-directory }}
run: npx react-native run-ios
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
name: Test Example App TypeScript and Lint
name: Test TypeScript and Lint
on:
pull_request:
branches:
- main
paths:
- 'Example/**'
- 'FabricExample/**'
push:
branches:
- main
jobs:
check:
runs-on: ubuntu-latest
env:
WORKING_DIRECTORY: Example
strategy:
matrix:
working-directory: [Example, FabricExample]
concurrency:
group: static-example-${{ github.ref }}
cancel-in-progress: true
Expand All @@ -26,12 +26,12 @@ jobs:
cache: 'yarn'
- name: Install root node dependencies
run: yarn
- name: Install example app node dependencies
working-directory: ${{ env.WORKING_DIRECTORY }}
- name: Install ${{ matrix.working-directory }} app node dependencies
working-directory: ${{ matrix.working-directory }}
run: yarn
- name: Check types
working-directory: ${{ env.WORKING_DIRECTORY }}
working-directory: ${{ matrix.working-directory }}
run: yarn tsc --noEmit
- name: Lint
working-directory: ${{ env.WORKING_DIRECTORY }}
working-directory: ${{ matrix.working-directory }}
run: yarn lint:js
2 changes: 0 additions & 2 deletions .github/workflows/static-root-checks.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Test TypeScript and Lint
on:
pull_request:
branches:
- main
paths:
- 'src/**'
- '*'
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/tv-os-build.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Test tvOS build
on:
pull_request:
branches:
- main
paths:
- 'ios/**'
- 'Common/**'
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/validate-java.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
name: Java Lint
on:
pull_request:
branches:
- main
paths:
- 'android/src/main/java/**'
push:
Expand Down
128 changes: 128 additions & 0 deletions Common/cpp/Fabric/FabricUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#ifdef RCT_NEW_ARCH_ENABLED

#include "FabricUtils.h"

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

using namespace facebook::react;

namespace reanimated {

#ifdef ANDROID
RuntimeExecutor getRuntimeExecutorFromBinding(Binding *binding) {
BindingPublic *bindingPublic = reinterpret_cast<BindingPublic *>(binding);
SchedulerPublic *schedulerPublic =
reinterpret_cast<SchedulerPublic *>((bindingPublic->scheduler_).get());
return schedulerPublic->runtimeExecutor_;
}
#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);
}

SharedShadowNode UIManager_cloneNode(
const UIManager *uiManager,
const ShadowNode::Shared &shadowNode,
const SharedShadowNodeSharedList &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);
}

} // namespace reanimated

#endif // RCT_NEW_ARCH_ENABLED
Loading

0 comments on commit 2756cd3

Please sign in to comment.