1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | #include "Differentiator.h"
|
7 |
|
8 | #include <better/map.h>
|
9 | #include <react/core/LayoutableShadowNode.h>
|
10 | #include <react/debug/SystraceSection.h>
|
11 | #include "ShadowView.h"
|
12 |
|
13 | namespace facebook {
|
14 | namespace react {
|
15 |
|
16 | static void sliceChildShadowNodeViewPairsRecursively(
|
17 | ShadowViewNodePairList &pairList,
|
18 | Point layoutOffset,
|
19 | const ShadowNode &shadowNode) {
|
20 | for (const auto &childShadowNode : shadowNode.getChildren()) {
|
21 | auto shadowView = ShadowView(*childShadowNode);
|
22 |
|
23 | const auto layoutableShadowNode =
|
24 | dynamic_cast<const LayoutableShadowNode *>(childShadowNode.get());
|
25 | #ifndef ANDROID
|
26 |
|
27 |
|
28 |
|
29 | if (!layoutableShadowNode || layoutableShadowNode->isLayoutOnly()) {
|
30 | #else
|
31 |
|
32 |
|
33 |
|
34 | if (layoutableShadowNode && layoutableShadowNode->isLayoutOnly()) {
|
35 | #endif
|
36 | sliceChildShadowNodeViewPairsRecursively(
|
37 | pairList,
|
38 | layoutOffset + shadowView.layoutMetrics.frame.origin,
|
39 | *childShadowNode);
|
40 | } else {
|
41 | shadowView.layoutMetrics.frame.origin += layoutOffset;
|
42 | pairList.push_back({shadowView, *childShadowNode});
|
43 | }
|
44 | }
|
45 | }
|
46 |
|
47 | static ShadowViewNodePairList sliceChildShadowNodeViewPairs(
|
48 | const ShadowNode &shadowNode) {
|
49 | ShadowViewNodePairList pairList;
|
50 | sliceChildShadowNodeViewPairsRecursively(pairList, {0, 0}, shadowNode);
|
51 | return pairList;
|
52 | }
|
53 |
|
54 | static void calculateShadowViewMutations(
|
55 | ShadowViewMutationList &mutations,
|
56 | const ShadowView &parentShadowView,
|
57 | const ShadowViewNodePairList &oldChildPairs,
|
58 | const ShadowViewNodePairList &newChildPairs) {
|
59 |
|
60 |
|
61 |
|
62 | if (oldChildPairs == newChildPairs) {
|
63 | return;
|
64 | }
|
65 |
|
66 | if (oldChildPairs.size() == 0 && newChildPairs.size() == 0) {
|
67 | return;
|
68 | }
|
69 |
|
70 | better::map<Tag, ShadowViewNodePair> insertedPairs;
|
71 | int index = 0;
|
72 |
|
73 | ShadowViewMutationList createMutations = {};
|
74 | ShadowViewMutationList deleteMutations = {};
|
75 | ShadowViewMutationList insertMutations = {};
|
76 | ShadowViewMutationList removeMutations = {};
|
77 | ShadowViewMutationList updateMutations = {};
|
78 | ShadowViewMutationList downwardMutations = {};
|
79 | ShadowViewMutationList destructiveDownwardMutations = {};
|
80 |
|
81 |
|
82 | for (index = 0; index < oldChildPairs.size() && index < newChildPairs.size();
|
83 | index++) {
|
84 | const auto &oldChildPair = oldChildPairs[index];
|
85 | const auto &newChildPair = newChildPairs[index];
|
86 |
|
87 | if (oldChildPair.shadowView.tag != newChildPair.shadowView.tag) {
|
88 |
|
89 | break;
|
90 | }
|
91 |
|
92 | if (oldChildPair.shadowView != newChildPair.shadowView) {
|
93 | updateMutations.push_back(ShadowViewMutation::UpdateMutation(
|
94 | parentShadowView,
|
95 | oldChildPair.shadowView,
|
96 | newChildPair.shadowView,
|
97 | index));
|
98 | }
|
99 |
|
100 | const auto oldGrandChildPairs =
|
101 | sliceChildShadowNodeViewPairs(oldChildPair.shadowNode);
|
102 | const auto newGrandChildPairs =
|
103 | sliceChildShadowNodeViewPairs(newChildPair.shadowNode);
|
104 | calculateShadowViewMutations(
|
105 | *(newGrandChildPairs.size() ? &downwardMutations
|
106 | : &destructiveDownwardMutations),
|
107 | oldChildPair.shadowView,
|
108 | oldGrandChildPairs,
|
109 | newGrandChildPairs);
|
110 | }
|
111 |
|
112 | int lastIndexAfterFirstStage = index;
|
113 |
|
114 |
|
115 | for (; index < newChildPairs.size(); index++) {
|
116 | const auto &newChildPair = newChildPairs[index];
|
117 |
|
118 | insertMutations.push_back(ShadowViewMutation::InsertMutation(
|
119 | parentShadowView, newChildPair.shadowView, index));
|
120 |
|
121 | insertedPairs.insert({newChildPair.shadowView.tag, newChildPair});
|
122 | }
|
123 |
|
124 |
|
125 | for (index = lastIndexAfterFirstStage; index < oldChildPairs.size();
|
126 | index++) {
|
127 | const auto &oldChildPair = oldChildPairs[index];
|
128 |
|
129 |
|
130 |
|
131 | removeMutations.push_back(ShadowViewMutation::RemoveMutation(
|
132 | parentShadowView, oldChildPair.shadowView, index));
|
133 |
|
134 | const auto &it = insertedPairs.find(oldChildPair.shadowView.tag);
|
135 |
|
136 | if (it == insertedPairs.end()) {
|
137 |
|
138 |
|
139 |
|
140 | deleteMutations.push_back(
|
141 | ShadowViewMutation::DeleteMutation(oldChildPair.shadowView));
|
142 |
|
143 |
|
144 |
|
145 | calculateShadowViewMutations(
|
146 | destructiveDownwardMutations,
|
147 | oldChildPair.shadowView,
|
148 | sliceChildShadowNodeViewPairs(oldChildPair.shadowNode),
|
149 | {});
|
150 | } else {
|
151 |
|
152 |
|
153 |
|
154 | const auto &newChildPair = it->second;
|
155 | if (newChildPair.shadowView != oldChildPair.shadowView) {
|
156 | const auto oldGrandChildPairs =
|
157 | sliceChildShadowNodeViewPairs(oldChildPair.shadowNode);
|
158 | const auto newGrandChildPairs =
|
159 | sliceChildShadowNodeViewPairs(newChildPair.shadowNode);
|
160 | calculateShadowViewMutations(
|
161 | *(newGrandChildPairs.size() ? &downwardMutations
|
162 | : &destructiveDownwardMutations),
|
163 | newChildPair.shadowView,
|
164 | oldGrandChildPairs,
|
165 | newGrandChildPairs);
|
166 | }
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | insertedPairs.erase(it);
|
173 | }
|
174 | }
|
175 |
|
176 |
|
177 | for (index = lastIndexAfterFirstStage; index < newChildPairs.size();
|
178 | index++) {
|
179 | const auto &newChildPair = newChildPairs[index];
|
180 |
|
181 | if (insertedPairs.find(newChildPair.shadowView.tag) ==
|
182 | insertedPairs.end()) {
|
183 |
|
184 | continue;
|
185 | }
|
186 |
|
187 | createMutations.push_back(
|
188 | ShadowViewMutation::CreateMutation(newChildPair.shadowView));
|
189 |
|
190 | calculateShadowViewMutations(
|
191 | downwardMutations,
|
192 | newChildPair.shadowView,
|
193 | {},
|
194 | sliceChildShadowNodeViewPairs(newChildPair.shadowNode));
|
195 | }
|
196 |
|
197 |
|
198 | mutations.insert(
|
199 | mutations.end(),
|
200 | destructiveDownwardMutations.begin(),
|
201 | destructiveDownwardMutations.end());
|
202 | mutations.insert(
|
203 | mutations.end(), updateMutations.begin(), updateMutations.end());
|
204 | mutations.insert(
|
205 | mutations.end(), removeMutations.rbegin(), removeMutations.rend());
|
206 | mutations.insert(
|
207 | mutations.end(), deleteMutations.begin(), deleteMutations.end());
|
208 | mutations.insert(
|
209 | mutations.end(), createMutations.begin(), createMutations.end());
|
210 | mutations.insert(
|
211 | mutations.end(), insertMutations.begin(), insertMutations.end());
|
212 | mutations.insert(
|
213 | mutations.end(), downwardMutations.begin(), downwardMutations.end());
|
214 | }
|
215 |
|
216 | ShadowViewMutationList calculateShadowViewMutations(
|
217 | const ShadowNode &oldRootShadowNode,
|
218 | const ShadowNode &newRootShadowNode) {
|
219 | SystraceSection s("calculateShadowViewMutations");
|
220 |
|
221 |
|
222 | assert(oldRootShadowNode.getTag() == newRootShadowNode.getTag());
|
223 |
|
224 | ShadowViewMutationList mutations;
|
225 |
|
226 | auto oldRootShadowView = ShadowView(oldRootShadowNode);
|
227 | auto newRootShadowView = ShadowView(newRootShadowNode);
|
228 |
|
229 | if (oldRootShadowView != newRootShadowView) {
|
230 | mutations.push_back(ShadowViewMutation::UpdateMutation(
|
231 | ShadowView(), oldRootShadowView, newRootShadowView, -1));
|
232 | }
|
233 |
|
234 | calculateShadowViewMutations(
|
235 | mutations,
|
236 | ShadowView(oldRootShadowNode),
|
237 | sliceChildShadowNodeViewPairs(oldRootShadowNode),
|
238 | sliceChildShadowNodeViewPairs(newRootShadowNode));
|
239 |
|
240 | return mutations;
|
241 | }
|
242 |
|
243 | }
|
244 | }
|