Copy Differ implementation to new file, feature-flag-gate new differ

Summary:
Changes in following diffs will be gated by this feature flag.

The differ in the new file is copied from the current stable implementation and will not be modified until it's deleted.

Changelog: [Internal]

Reviewed By: sammy-SC, mdvacca

Differential Revision: D27775698

fbshipit-source-id: 03d9518ffd2b1f25712386c56a38bd2b4d839fc2
This commit is contained in:
Joshua Gross 2021-04-14 19:47:39 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 5eba5c11b0
Коммит 39b8233c93
17 изменённых файлов: 1746 добавлений и 22 удалений

Просмотреть файл

@ -6,6 +6,7 @@
*/
#include "Differentiator.h"
#include "DifferentiatorFlatteningClassic.h"
#include <better/map.h>
#include <better/small_vector.h>
@ -1583,7 +1584,13 @@ ShadowViewNodePair::List sliceChildShadowNodeViewPairsLegacy(
ShadowViewMutation::List calculateShadowViewMutations(
ShadowNode const &oldRootShadowNode,
ShadowNode const &newRootShadowNode) {
ShadowNode const &newRootShadowNode,
bool useNewDiffer) {
if (!useNewDiffer) {
return DifferOld::calculateShadowViewMutations(
oldRootShadowNode, newRootShadowNode);
}
SystraceSection s("calculateShadowViewMutations");
// Root shadow nodes must be belong the same family.

Просмотреть файл

@ -23,7 +23,8 @@ enum class ReparentMode { Flatten, Unflatten };
*/
ShadowViewMutationList calculateShadowViewMutations(
ShadowNode const &oldRootShadowNode,
ShadowNode const &newRootShadowNode);
ShadowNode const &newRootShadowNode,
bool useNewDiffer);
/**
* Generates a list of `ShadowViewNodePair`s that represents a layer of a

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,52 @@
/*
* 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.
*/
#pragma once
// This file exists as an experimental baseline against which
// we can compare changes in Differentiator.
// Once changes in Differentiator have been verified safe,
// this file will be deleted.
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/debug/flags.h>
#include <react/renderer/mounting/ShadowViewMutation.h>
namespace facebook {
namespace react {
namespace DifferOld {
enum class ReparentMode { Flatten, Unflatten };
/*
* Calculates a list of view mutations which describes how the old
* `ShadowTree` can be transformed to the new one.
* The list of mutations might be and might not be optimal.
*/
ShadowViewMutationList calculateShadowViewMutations(
ShadowNode const &oldRootShadowNode,
ShadowNode const &newRootShadowNode);
/**
* Generates a list of `ShadowViewNodePair`s that represents a layer of a
* flattened view hierarchy. The V2 version preserves nodes even if they do
* not form views and their children are flattened.
*/
ShadowViewNodePair::List sliceChildShadowNodeViewPairsV2(
ShadowNode const &shadowNode,
bool allowFlattened = false);
/*
* Generates a list of `ShadowViewNodePair`s that represents a layer of a
* flattened view hierarchy. This is *only* used by unit tests currently.
*/
ShadowViewNodePair::List sliceChildShadowNodeViewPairsLegacy(
ShadowNode const &shadowNode);
} // namespace DifferOld
} // namespace react
} // namespace facebook

Просмотреть файл

@ -90,7 +90,9 @@ better::optional<MountingTransaction> MountingCoordinator::pullTransaction()
telemetry.willDiff();
auto mutations = calculateShadowViewMutations(
*baseRevision_.rootShadowNode, *lastRevision_->rootShadowNode);
*baseRevision_.rootShadowNode,
*lastRevision_->rootShadowNode,
enableNewDiffer_);
telemetry.didDiff();
@ -186,5 +188,9 @@ void MountingCoordinator::setMountingOverrideDelegate(
mountingOverrideDelegate_ = delegate;
}
void MountingCoordinator::setEnableNewDiffer(bool enabled) const {
enableNewDiffer_ = enabled;
}
} // namespace react
} // namespace facebook

Просмотреть файл

@ -71,6 +71,8 @@ class MountingCoordinator final {
TelemetryController const &getTelemetryController() const;
void setEnableNewDiffer(bool enabled) const;
/*
* Methods from this section are meant to be used by
* `MountingOverrideDelegate` only.
@ -112,6 +114,8 @@ class MountingCoordinator final {
TelemetryController telemetryController_;
mutable bool enableNewDiffer_{false};
#ifdef RN_SHADOW_TREE_INTROSPECTION
mutable StubViewTree stubViewTree_; // Protected by `mutex_`.
#endif

Просмотреть файл

@ -223,7 +223,8 @@ ShadowTree::ShadowTree(
SurfaceId surfaceId,
LayoutConstraints const &layoutConstraints,
LayoutContext const &layoutContext,
ShadowTreeDelegate const &delegate)
ShadowTreeDelegate const &delegate,
bool enableNewDiffer)
: surfaceId_(surfaceId), delegate_(delegate) {
const auto noopEventEmitter = std::make_shared<const ViewEventEmitter>(
nullptr, -1, std::shared_ptr<const EventDispatcher>());
@ -252,6 +253,7 @@ ShadowTree::ShadowTree(
mountingCoordinator_ =
std::make_shared<MountingCoordinator const>(currentRevision_);
mountingCoordinator_->setEnableNewDiffer(enableNewDiffer);
}
ShadowTree::~ShadowTree() {

Просмотреть файл

@ -70,7 +70,8 @@ class ShadowTree final {
SurfaceId surfaceId,
LayoutConstraints const &layoutConstraints,
LayoutContext const &layoutContext,
ShadowTreeDelegate const &delegate);
ShadowTreeDelegate const &delegate,
bool enableNewDiffer);
~ShadowTree();

Просмотреть файл

@ -88,7 +88,7 @@ StubViewTree buildStubViewTreeUsingDifferentiator(
ShadowNode::emptySharedShadowNodeSharedList()});
auto mutations =
calculateShadowViewMutations(*emptyRootShadowNode, rootShadowNode);
calculateShadowViewMutations(*emptyRootShadowNode, rootShadowNode, true);
auto stubViewTree = StubViewTree(ShadowView(*emptyRootShadowNode));
stubViewTree.mutate(mutations);

Просмотреть файл

@ -242,7 +242,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
}*/
// Calculating mutations.
auto mutations1 = calculateShadowViewMutations(*rootNodeV1, *rootNodeV2);
auto mutations1 =
calculateShadowViewMutations(*rootNodeV1, *rootNodeV2, true);
// The order and exact mutation instructions here may change at any time.
// This test just ensures that any changes are intentional.
@ -258,7 +259,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
EXPECT_TRUE(mutations1[1].index == 0);
// Calculating mutations.
auto mutations2 = calculateShadowViewMutations(*rootNodeV2, *rootNodeV3);
auto mutations2 =
calculateShadowViewMutations(*rootNodeV2, *rootNodeV3, true);
// The order and exact mutation instructions here may change at any time.
// This test just ensures that any changes are intentional.
@ -274,7 +276,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
EXPECT_TRUE(mutations2[1].oldChildShadowView.tag == 100);
// Calculating mutations.
auto mutations3 = calculateShadowViewMutations(*rootNodeV3, *rootNodeV4);
auto mutations3 =
calculateShadowViewMutations(*rootNodeV3, *rootNodeV4, true);
LOG(ERROR) << "Num mutations IN OLD TEST mutations3: " << mutations3.size();
// The order and exact mutation instructions here may change at any time.
@ -296,7 +299,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
EXPECT_TRUE(mutations3[3].index == 2);
// Calculating mutations.
auto mutations4 = calculateShadowViewMutations(*rootNodeV4, *rootNodeV5);
auto mutations4 =
calculateShadowViewMutations(*rootNodeV4, *rootNodeV5, true);
// The order and exact mutation instructions here may change at any time.
// This test just ensures that any changes are intentional.
@ -321,7 +325,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
EXPECT_TRUE(mutations4[5].newChildShadowView.tag == 102);
EXPECT_TRUE(mutations4[5].index == 3);
auto mutations5 = calculateShadowViewMutations(*rootNodeV5, *rootNodeV6);
auto mutations5 =
calculateShadowViewMutations(*rootNodeV5, *rootNodeV6, true);
// The order and exact mutation instructions here may change at any time.
// This test just ensures that any changes are intentional.
@ -340,7 +345,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
EXPECT_TRUE(mutations5[3].newChildShadowView.tag == 105);
EXPECT_TRUE(mutations5[3].index == 3);
auto mutations6 = calculateShadowViewMutations(*rootNodeV6, *rootNodeV7);
auto mutations6 =
calculateShadowViewMutations(*rootNodeV6, *rootNodeV7, true);
// The order and exact mutation instructions here may change at any time.
// This test just ensures that any changes are intentional.
@ -594,7 +600,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) {
rootNodeV5->sealRecursive();
// Calculating mutations.
auto mutations1 = calculateShadowViewMutations(*rootNodeV1, *rootNodeV2);
auto mutations1 =
calculateShadowViewMutations(*rootNodeV1, *rootNodeV2, true);
EXPECT_EQ(mutations1.size(), 5);
EXPECT_EQ(mutations1[0].type, ShadowViewMutation::Update);
@ -608,7 +615,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) {
EXPECT_EQ(mutations1[4].type, ShadowViewMutation::Insert);
EXPECT_EQ(mutations1[4].newChildShadowView.tag, 1000);
auto mutations2 = calculateShadowViewMutations(*rootNodeV2, *rootNodeV3);
auto mutations2 =
calculateShadowViewMutations(*rootNodeV2, *rootNodeV3, true);
EXPECT_EQ(mutations2.size(), 5);
EXPECT_EQ(mutations2[0].type, ShadowViewMutation::Update);
@ -624,7 +632,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) {
EXPECT_EQ(mutations2[4].type, ShadowViewMutation::Insert);
EXPECT_EQ(mutations2[4].newChildShadowView.tag, 1000);
auto mutations3 = calculateShadowViewMutations(*rootNodeV3, *rootNodeV4);
auto mutations3 =
calculateShadowViewMutations(*rootNodeV3, *rootNodeV4, true);
// between these two trees, lots of new nodes are created and inserted - this
// is all correct, and this is the minimal amount of mutations
@ -661,7 +670,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) {
EXPECT_EQ(mutations3[14].type, ShadowViewMutation::Insert);
EXPECT_EQ(mutations3[14].newChildShadowView.tag, 1000);
auto mutations4 = calculateShadowViewMutations(*rootNodeV4, *rootNodeV5);
auto mutations4 =
calculateShadowViewMutations(*rootNodeV4, *rootNodeV5, true);
EXPECT_EQ(mutations4.size(), 9);
EXPECT_EQ(mutations4[0].type, ShadowViewMutation::Update);

Просмотреть файл

@ -75,7 +75,7 @@ static void testShadowNodeTreeLifeCycle(
// Building an initial view hierarchy.
auto viewTree = buildStubViewTreeWithoutUsingDifferentiator(*emptyRootNode);
viewTree.mutate(
calculateShadowViewMutations(*emptyRootNode, *currentRootNode));
calculateShadowViewMutations(*emptyRootNode, *currentRootNode, true));
for (int j = 0; j < stages; j++) {
auto nextRootNode = currentRootNode;
@ -102,7 +102,7 @@ static void testShadowNodeTreeLifeCycle(
// Calculating mutations.
auto mutations =
calculateShadowViewMutations(*currentRootNode, *nextRootNode);
calculateShadowViewMutations(*currentRootNode, *nextRootNode, true);
// Make sure that in a single frame, a DELETE for a
// view is not followed by a CREATE for the same view.

Просмотреть файл

@ -171,8 +171,8 @@ class StackingContextTest : public ::testing::Test {
callback(buildStubViewTreeUsingDifferentiator(*rootShadowNode_));
callback(buildStubViewTreeWithoutUsingDifferentiator(*rootShadowNode_));
auto mutations =
calculateShadowViewMutations(*currentRootShadowNode_, *rootShadowNode_);
auto mutations = calculateShadowViewMutations(
*currentRootShadowNode_, *rootShadowNode_, true);
currentRootShadowNode_ = rootShadowNode_;
currentStubViewTree_.mutate(mutations);
callback(currentStubViewTree_);

Просмотреть файл

@ -98,7 +98,11 @@ TEST(StateReconciliationTest, testStateReconciliation) {
auto state1 = shadowNodeAB->getState();
auto shadowTreeDelegate = DummyShadowTreeDelegate{};
ShadowTree shadowTree{
SurfaceId{11}, LayoutConstraints{}, LayoutContext{}, shadowTreeDelegate};
SurfaceId{11},
LayoutConstraints{},
LayoutContext{},
shadowTreeDelegate,
true};
shadowTree.commit(
[&](RootShadowNode const &oldRootShadowNode) {

Просмотреть файл

@ -129,11 +129,15 @@ Scheduler::Scheduler(
#ifdef ANDROID
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
"react_fabric:remove_outstanding_surfaces_on_destruction_android");
enableNewDiffer_ = reactNativeConfig_->getBool(
"react_fabric:enable_new_differ_h1_2021_android");
Constants::setPropsForwardingEnabled(reactNativeConfig_->getBool(
"react_fabric:enable_props_forwarding_android"));
#else
removeOutstandingSurfacesOnDestruction_ = reactNativeConfig_->getBool(
"react_fabric:remove_outstanding_surfaces_on_destruction_ios");
enableNewDiffer_ =
reactNativeConfig_->getBool("react_fabric:enable_new_differ_h1_2021_ios");
#endif
uiManager->extractUIManagerBindingOnDemand_ = reactNativeConfig_->getBool(
@ -199,6 +203,7 @@ Scheduler::~Scheduler() {
void Scheduler::registerSurface(
SurfaceHandler const &surfaceHandler) const noexcept {
surfaceHandler.setUIManager(uiManager_.get());
surfaceHandler.setEnableNewDiffer(enableNewDiffer_);
}
void Scheduler::unregisterSurface(

Просмотреть файл

@ -121,6 +121,7 @@ class Scheduler final : public UIManagerDelegate {
* Temporary flags.
*/
bool removeOutstandingSurfacesOnDestruction_{false};
bool enableNewDiffer_{false};
};
} // namespace react

Просмотреть файл

@ -71,7 +71,8 @@ void SurfaceHandler::start() const noexcept {
parameters.surfaceId,
parameters.layoutConstraints,
parameters.layoutContext,
*link_.uiManager);
*link_.uiManager,
enableNewDiffer_);
link_.shadowTree = shadowTree.get();
@ -138,6 +139,11 @@ DisplayMode SurfaceHandler::getDisplayMode() const noexcept {
return parameters_.displayMode;
}
#pragma mark - Feature Flags
void SurfaceHandler::setEnableNewDiffer(bool enabled) const noexcept {
enableNewDiffer_ = enabled;
}
#pragma mark - Accessors
SurfaceId SurfaceHandler::getSurfaceId() const noexcept {

Просмотреть файл

@ -138,6 +138,9 @@ class SurfaceHandler final {
LayoutConstraints getLayoutConstraints() const noexcept;
LayoutContext getLayoutContext() const noexcept;
#pragma mark - Feature Flags
void setEnableNewDiffer(bool enabled) const noexcept;
private:
friend class Scheduler;
@ -195,6 +198,11 @@ class SurfaceHandler final {
*/
mutable better::shared_mutex parametersMutex_;
mutable Parameters parameters_;
/**
* Feature flags.
*/
mutable bool enableNewDiffer_{false};
};
} // namespace react