mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/49307 changelog: [internal] There were parts of Differentiator that were leaking outside of "mounting" module. This diff moves them to "internal" folder and changes buck so they can't be imported from outside the module. Reviewed By: NickGerleman Differential Revision: D69401878 fbshipit-source-id: 8aa8c96e91b088dab4f9c8b9a5e6937e09be7eb4
192 lines
5.8 KiB
C++
192 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "sliceChildShadowNodeViewPairs.h"
|
|
#include <react/featureflags/ReactNativeFeatureFlags.h>
|
|
#include <react/renderer/core/LayoutableShadowNode.h>
|
|
|
|
#include "ShadowViewNodePair.h"
|
|
|
|
namespace facebook::react {
|
|
|
|
/*
|
|
* Sorting comparator for `reorderInPlaceIfNeeded`.
|
|
*/
|
|
static bool shouldFirstPairComesBeforeSecondOne(
|
|
const ShadowViewNodePair* lhs,
|
|
const ShadowViewNodePair* rhs) noexcept {
|
|
return lhs->shadowNode->getOrderIndex() < rhs->shadowNode->getOrderIndex();
|
|
}
|
|
|
|
/*
|
|
* Reorders pairs in-place based on `orderIndex` using a stable sort algorithm.
|
|
*/
|
|
static void reorderInPlaceIfNeeded(
|
|
std::vector<ShadowViewNodePair*>& pairs) noexcept {
|
|
if (pairs.size() < 2) {
|
|
return;
|
|
}
|
|
|
|
auto isReorderNeeded = false;
|
|
for (const auto& pair : pairs) {
|
|
if (pair->shadowNode->getOrderIndex() != 0) {
|
|
isReorderNeeded = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isReorderNeeded) {
|
|
return;
|
|
}
|
|
|
|
std::stable_sort(
|
|
pairs.begin(), pairs.end(), &shouldFirstPairComesBeforeSecondOne);
|
|
}
|
|
|
|
static void sliceChildShadowNodeViewPairsRecursively(
|
|
std::vector<ShadowViewNodePair*>& pairList,
|
|
size_t& startOfStaticIndex,
|
|
ViewNodePairScope& scope,
|
|
Point layoutOffset,
|
|
const ShadowNode& shadowNode,
|
|
const CullingContext& cullingContext) {
|
|
for (const auto& sharedChildShadowNode : shadowNode.getChildren()) {
|
|
auto& childShadowNode = *sharedChildShadowNode;
|
|
#ifndef ANDROID
|
|
// T153547836: Disabled on Android because the mounting infrastructure
|
|
// is not fully ready yet.
|
|
if (childShadowNode.getTraits().check(ShadowNodeTraits::Trait::Hidden)) {
|
|
continue;
|
|
}
|
|
#endif
|
|
auto shadowView = ShadowView(childShadowNode);
|
|
|
|
if (ReactNativeFeatureFlags::enableViewCulling()) {
|
|
if (cullingContext.shouldConsiderCulling() &&
|
|
shadowView.layoutMetrics != EmptyLayoutMetrics) {
|
|
auto overflowInsetFrame =
|
|
shadowView.layoutMetrics.getOverflowInsetFrame() *
|
|
cullingContext.transform;
|
|
if (auto layoutableShadowNode =
|
|
dynamic_cast<const LayoutableShadowNode*>(&childShadowNode)) {
|
|
overflowInsetFrame =
|
|
overflowInsetFrame * layoutableShadowNode->getTransform();
|
|
}
|
|
auto doesIntersect =
|
|
Rect::intersect(cullingContext.frame, overflowInsetFrame) != Rect{};
|
|
if (!doesIntersect) {
|
|
continue; // Culling.
|
|
}
|
|
}
|
|
}
|
|
|
|
auto origin = layoutOffset;
|
|
auto cullingContextCopy = cullingContext.adjustCullingContextIfNeeded(
|
|
{.shadowView = shadowView, .shadowNode = &childShadowNode});
|
|
|
|
if (shadowView.layoutMetrics != EmptyLayoutMetrics) {
|
|
origin += shadowView.layoutMetrics.frame.origin;
|
|
shadowView.layoutMetrics.frame.origin += layoutOffset;
|
|
}
|
|
|
|
// This might not be a FormsView, or a FormsStackingContext. We let the
|
|
// differ handle removal of flattened views from the Mounting layer and
|
|
// shuffling their children around.
|
|
bool childrenFormStackingContexts = shadowNode.getTraits().check(
|
|
ShadowNodeTraits::Trait::ChildrenFormStackingContext);
|
|
bool isConcreteView = (childShadowNode.getTraits().check(
|
|
ShadowNodeTraits::Trait::FormsView) ||
|
|
childrenFormStackingContexts) &&
|
|
!childShadowNode.getTraits().check(
|
|
ShadowNodeTraits::Trait::ForceFlattenView);
|
|
bool areChildrenFlattened =
|
|
(!childShadowNode.getTraits().check(
|
|
ShadowNodeTraits::Trait::FormsStackingContext) &&
|
|
!childrenFormStackingContexts) ||
|
|
childShadowNode.getTraits().check(
|
|
ShadowNodeTraits::Trait::ForceFlattenView);
|
|
|
|
Point storedOrigin = {};
|
|
if (areChildrenFlattened) {
|
|
storedOrigin = origin;
|
|
}
|
|
scope.push_back(
|
|
{shadowView,
|
|
&childShadowNode,
|
|
areChildrenFlattened,
|
|
isConcreteView,
|
|
storedOrigin});
|
|
|
|
if (shadowView.layoutMetrics.positionType == PositionType::Static) {
|
|
auto it = pairList.begin();
|
|
std::advance(it, startOfStaticIndex);
|
|
pairList.insert(it, &scope.back());
|
|
startOfStaticIndex++;
|
|
if (areChildrenFlattened) {
|
|
sliceChildShadowNodeViewPairsRecursively(
|
|
pairList,
|
|
startOfStaticIndex,
|
|
scope,
|
|
origin,
|
|
childShadowNode,
|
|
cullingContextCopy);
|
|
}
|
|
} else {
|
|
pairList.push_back(&scope.back());
|
|
if (areChildrenFlattened) {
|
|
size_t pairListSize = pairList.size();
|
|
sliceChildShadowNodeViewPairsRecursively(
|
|
pairList,
|
|
pairListSize,
|
|
scope,
|
|
origin,
|
|
childShadowNode,
|
|
cullingContextCopy);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<ShadowViewNodePair*> sliceChildShadowNodeViewPairs(
|
|
const ShadowViewNodePair& shadowNodePair,
|
|
ViewNodePairScope& scope,
|
|
bool allowFlattened,
|
|
Point layoutOffset,
|
|
const CullingContext& cullingContext) {
|
|
const auto& shadowNode = *shadowNodePair.shadowNode;
|
|
auto pairList = std::vector<ShadowViewNodePair*>{};
|
|
|
|
if (shadowNodePair.flattened && shadowNodePair.isConcreteView &&
|
|
!allowFlattened) {
|
|
return pairList;
|
|
}
|
|
|
|
size_t startOfStaticIndex = 0;
|
|
|
|
sliceChildShadowNodeViewPairsRecursively(
|
|
pairList,
|
|
startOfStaticIndex,
|
|
scope,
|
|
layoutOffset,
|
|
shadowNode,
|
|
cullingContext);
|
|
|
|
// Sorting pairs based on `orderIndex` if needed.
|
|
reorderInPlaceIfNeeded(pairList);
|
|
|
|
// Set list and mountIndex for each after reordering
|
|
size_t mountIndex = 0;
|
|
for (auto child : pairList) {
|
|
child->mountIndex =
|
|
(child->isConcreteView ? mountIndex++ : static_cast<unsigned long>(-1));
|
|
}
|
|
|
|
return pairList;
|
|
}
|
|
|
|
} // namespace facebook::react
|