Files
react-native/ReactCommon/react/renderer/mounting/stubs.cpp
T
Valentin Shergin 9a720ad47f Fabric: buildStubViewTreeWithoutUsingDifferentiator & buildStubViewTreeUsingDifferentiator
Summary:
After fixing `calculateShadowViewMutationsForNewTree` I realized that it will be even better to test Stacking Context and mutation instructions infra using both functions: `calculateShadowViewMutationsForNewTree` (used for testing) and the Differentiator itself. This diff implements it.

Now we have two similarly working functions with different implementations that we can use for testing Differentiator and other parts of the infra.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D25576922

fbshipit-source-id: 7922e9ebfb9d6ef1792566554ba0c4a14f835ae2
2020-12-16 10:57:37 -08:00

100 lines
3.2 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "stubs.h"
#include <react/renderer/core/LayoutableShadowNode.h>
#include <react/renderer/core/ShadowNodeFragment.h>
#include <react/renderer/mounting/Differentiator.h>
namespace facebook {
namespace react {
/*
* Sorting comparator for `reorderInPlaceIfNeeded`.
*/
static bool shouldFirstPairComesBeforeSecondOne(
ShadowViewNodePair const &lhs,
ShadowViewNodePair const &rhs) noexcept {
return lhs.shadowNode->getOrderIndex() < rhs.shadowNode->getOrderIndex();
}
/*
* Reorders pairs in-place based on `orderIndex` using a stable sort algorithm.
*/
static void reorderInPlaceIfNeeded(ShadowViewNodePair::List &pairs) noexcept {
// This is a simplified version of the function intentionally copied from
// `Differentiator.cpp`.
std::stable_sort(
pairs.begin(), pairs.end(), &shouldFirstPairComesBeforeSecondOne);
}
/*
* Generates `create` and `insert` instructions recursively traversing a shadow
* tree.
* This is a trivial implementation of diffing algorithm that can only "diff"
* an empty tree with some other one.
*/
static void calculateShadowViewMutationsForNewTree(
ShadowViewMutation::List &mutations,
ShadowView const &parentShadowView,
ShadowViewNodePair::List newChildPairs) {
// Sorting pairs based on `orderIndex` if needed.
reorderInPlaceIfNeeded(newChildPairs);
for (auto index = 0; index < newChildPairs.size(); index++) {
auto const &newChildPair = newChildPairs[index];
mutations.push_back(
ShadowViewMutation::CreateMutation(newChildPair.shadowView));
mutations.push_back(ShadowViewMutation::InsertMutation(
parentShadowView, newChildPair.shadowView, index));
auto newGrandChildPairs =
sliceChildShadowNodeViewPairsLegacy(*newChildPair.shadowNode);
calculateShadowViewMutationsForNewTree(
mutations, newChildPair.shadowView, newGrandChildPairs);
}
}
StubViewTree buildStubViewTreeWithoutUsingDifferentiator(
ShadowNode const &rootShadowNode) {
auto mutations = ShadowViewMutation::List{};
mutations.reserve(256);
calculateShadowViewMutationsForNewTree(
mutations,
ShadowView(rootShadowNode),
sliceChildShadowNodeViewPairsLegacy(rootShadowNode));
auto emptyRootShadowNode = rootShadowNode.clone(
ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(),
ShadowNode::emptySharedShadowNodeSharedList()});
auto stubViewTree = StubViewTree(ShadowView(*emptyRootShadowNode));
stubViewTree.mutate(mutations);
return stubViewTree;
}
StubViewTree buildStubViewTreeUsingDifferentiator(
ShadowNode const &rootShadowNode) {
auto emptyRootShadowNode = rootShadowNode.clone(
ShadowNodeFragment{ShadowNodeFragment::propsPlaceholder(),
ShadowNode::emptySharedShadowNodeSharedList()});
auto mutations =
calculateShadowViewMutations(*emptyRootShadowNode, rootShadowNode);
auto stubViewTree = StubViewTree(ShadowView(*emptyRootShadowNode));
stubViewTree.mutate(mutations);
return stubViewTree;
}
} // namespace react
} // namespace facebook