Files
react-native/ReactCommon/react/renderer/mounting/Differentiator.h
T
Joshua Gross d1b1e8b80d Differ: ensure all ShadowViews generated by differ have correct LayoutMetrics
Summary:
While I think this was a very marginal bug with no known issues in the wild, incorrect layout values were sometimes being propagated to certain nodes. This would only occur during complex nested (un)flattening operations and may only impact node consistency, specifically with setting the "previous" ShadowView of mutation instructions, specifically REMOVE and DELETE. Even in rigorous testing I had trouble hitting this case and it didn't seem to impact the "next" values in CREATE, INSERT, or UPDATE.

The issue: previously `sliceChildShadowNodeViewPairsV2` assumed that the node it's operating on is a child of a non-flattened view, and the baseline origin is `{0,0}`. You can see when `sliceChildShadowNodeViewPairsRecursivelyV2` is called, a `layoutOffset` is passed in. If we ever got a list of a node that was in a flattened parent by calling `sliceChildShadowNodeViewPairsV2`, we would incorrectly assume that baseline layoutOffset for the node is `0,0`.

Now, we store the layoutOffset in the ShadowViewNodePair and can retrieve it when getting child pairs of a node.

Changelog: [internal]

Reviewed By: sammy-SC

Differential Revision: D27759380

fbshipit-source-id: a89756190a1cb377bcc55ff31799c2afbaecdaa9
2021-04-14 19:50:10 -07:00

73 lines
2.7 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.
*/
#pragma once
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/debug/flags.h>
#include <react/renderer/mounting/ShadowViewMutation.h>
#include <deque>
namespace facebook {
namespace react {
enum class ReparentMode { Flatten, Unflatten };
/**
* During differ, we need to keep some `ShadowViewNodePair`s in memory.
* Some `ShadowViewNodePair`s are referenced from std::vectors returned
* by `sliceChildShadowNodeViewPairsV2`; some are referenced in TinyMaps
* for view (un)flattening especially; and it is not always clear which
* std::vectors will outlive which TinyMaps, and vice-versa, so it doesn't
* make sense for the std::vector or TinyMap to own any `ShadowViewNodePair`s.
*
* Thus, we introduce the concept of a scope.
*
* For the duration of some operation, we keep a ViewNodePairScope around, such
* that: (1) the ViewNodePairScope keeps each
* ShadowViewNodePair alive, (2) we have a stable pointer value that we can
* use to reference each ShadowViewNodePair (not guaranteed with std::vector,
* for example, which may have to resize and move values around).
*
* As long as we only manipulate the data-structure with push_back, std::deque
* both (1) ensures that pointers into the data-structure are never invalidated,
* and (2) tries to efficiently allocate storage such that as many objects as
* possible are close in memory, but does not guarantee adjacency.
*/
using ViewNodePairScope = std::deque<ShadowViewNodePair>;
/*
* 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.
*/
ShadowViewMutation::List calculateShadowViewMutations(
ShadowNode const &oldRootShadowNode,
ShadowNode const &newRootShadowNode,
bool useNewDiffer);
/**
* 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::NonOwningList sliceChildShadowNodeViewPairsV2(
ShadowNode const &shadowNode,
ViewNodePairScope &viewNodePairScope,
bool allowFlattened = false,
Point layoutOffset = {0, 0});
/*
* Generates a list of `ShadowViewNodePair`s that represents a layer of a
* flattened view hierarchy. This is *only* used by unit tests currently.
*/
ShadowViewNodePair::OwningList sliceChildShadowNodeViewPairsLegacy(
ShadowNode const &shadowNode);
} // namespace react
} // namespace facebook