Skip to content

Commit 43403be

Browse files
sammy-SCfacebook-github-bot
authored andcommitted
fix crash in view culling when parent-child go from flattened-unflattened to unflattened-flattened (facebook#50844)
Summary: Pull Request resolved: facebook#50844 changelog: [internal] Fixes a problem where during reparenting differentiator will generate invalid mounting instructions. In tests, this fails with assertion failure on [StubViewTree.cpp:177](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactCommon/react/renderer/mounting/stubs/StubViewTree.cpp#L177). Reviewed By: rubennorte Differential Revision: D72822113 fbshipit-source-id: 924fca76a87119c3a86c19dc974f4ec282b149d5
1 parent 4ab7d53 commit 43403be

File tree

2 files changed

+78
-4
lines changed

2 files changed

+78
-4
lines changed

packages/react-native/Libraries/Components/ScrollView/__tests__/ScrollView-viewCulling-itest.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* @oncall react_native
1010
* @fantom_flags enableViewCulling:true
1111
* @fantom_flags enableSynchronousStateUpdates:true
12+
* @fantom_flags enableFixForParentTagDuringReparenting:true
1213
*/
1314

1415
import 'react-native/Libraries/Core/InitializeCore.js';
@@ -1239,3 +1240,78 @@ test('parent-child flattening with culling', () => {
12391240
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
12401241
]);
12411242
});
1243+
1244+
test('parent-child switching from unflattened-flattened to flattened-unflattened', () => {
1245+
const root = Fantom.createRoot({viewportWidth: 100, viewportHeight: 100});
1246+
1247+
Fantom.runTask(() => {
1248+
root.render(
1249+
<ScrollView
1250+
style={{height: 100, width: 100}}
1251+
contentOffset={{x: 0, y: 60}}>
1252+
<View
1253+
style={{
1254+
marginTop: 100,
1255+
opacity: 0,
1256+
}}>
1257+
<View
1258+
style={{
1259+
marginTop: 50,
1260+
}}>
1261+
<View
1262+
nativeID={'child'}
1263+
style={{height: 10, width: 10, backgroundColor: 'red'}}
1264+
/>
1265+
</View>
1266+
</View>
1267+
</ScrollView>,
1268+
);
1269+
});
1270+
1271+
expect(root.takeMountingManagerLogs()).toEqual([
1272+
'Update {type: "RootView", nativeID: (root)}',
1273+
'Create {type: "ScrollView", nativeID: (N/A)}',
1274+
'Create {type: "View", nativeID: (N/A)}',
1275+
'Create {type: "View", nativeID: (N/A)}',
1276+
'Create {type: "View", nativeID: "child"}',
1277+
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
1278+
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
1279+
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
1280+
'Insert {type: "ScrollView", parentNativeID: (root), index: 0, nativeID: (N/A)}',
1281+
]);
1282+
1283+
// force view to be flattened.
1284+
Fantom.runTask(() => {
1285+
root.render(
1286+
<ScrollView
1287+
style={{height: 100, width: 100}}
1288+
contentOffset={{x: 0, y: 60}}>
1289+
<View
1290+
style={{
1291+
marginTop: 100,
1292+
}}>
1293+
<View
1294+
style={{
1295+
marginTop: 50,
1296+
opacity: 0,
1297+
}}>
1298+
<View
1299+
nativeID={'child'}
1300+
style={{height: 10, width: 10, backgroundColor: 'red'}}
1301+
/>
1302+
</View>
1303+
</View>
1304+
</ScrollView>,
1305+
);
1306+
});
1307+
1308+
expect(root.takeMountingManagerLogs()).toEqual([
1309+
'Update {type: "View", nativeID: "child"}',
1310+
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
1311+
'Remove {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
1312+
'Delete {type: "View", nativeID: (N/A)}',
1313+
'Create {type: "View", nativeID: (N/A)}',
1314+
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: "child"}',
1315+
'Insert {type: "View", parentNativeID: (N/A), index: 0, nativeID: (N/A)}',
1316+
]);
1317+
});

packages/react-native/ReactCommon/react/renderer/mounting/Differentiator.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,6 @@ static void calculateShadowViewMutationsFlattener(
736736
// Flatten parent, unflatten child
737737
else {
738738
// Unflatten old list into new tree
739-
// TODO(T217775046): Find a test case for this branch of view
740-
// flattening + culling.
741739
auto parentTagForUpdateWhenFlattened =
742740
ReactNativeFeatureFlags::
743741
enableFixForParentTagDuringReparenting()
@@ -759,8 +757,8 @@ static void calculateShadowViewMutationsFlattener(
759757
: parentTag),
760758
/* parentSubVisitedOtherNewNodes */ subVisitedNewMap,
761759
/* parentSubVisitedOtherOldNodes */ subVisitedOldMap,
762-
/* oldCullingContext */ adjustedOldCullingContext,
763-
/* newCullingContext */ adjustedNewCullingContext);
760+
oldCullingContext,
761+
newCullingContext);
764762

765763
// If old nodes were not visited, we know that we can delete them
766764
// now. They will be removed from the hierarchy by the outermost

0 commit comments

Comments
 (0)